【问题标题】:Numpy Convert String Representation of Boolean Array To Boolean ArrayNumpy 将布尔数组的字符串表示形式转换为布尔数组
【发布时间】:2013-06-05 16:10:05
【问题描述】:

是否有一种原生的 numpy 方法来转换布尔值的字符串表示形式的数组,例如:

['True','False','True','False']

到一个可以用于屏蔽/索引的实际布尔数组?我可以做一个 for 循环遍历并重建数组,但对于大型数组,这很慢。

【问题讨论】:

  • 是numpy字符串数组(如果存在这种东西的话)还是python字符串数组?
  • 这是一个 numpy 字符串数组 - 很奇怪,我知道。
  • @Newmu -- 我认为解决方案是首先避免获取字符串表示形式的数组。你是怎么从那个数组来的?也许这就是我们应该开始寻求优化的地方...
  • 我得从别人的代码中处理。

标签: python numpy


【解决方案1】:

您应该能够进行布尔比较,IIUC,dtype 是字符串还是 object

>>> a = np.array(['True', 'False', 'True', 'False'])
>>> a
array(['True', 'False', 'True', 'False'], 
      dtype='|S5')
>>> a == "True"
array([ True, False,  True, False], dtype=bool)

>>> a = np.array(['True', 'False', 'True', 'False'], dtype=object)
>>> a
array(['True', 'False', 'True', 'False'], dtype=object)
>>> a == "True"
array([ True, False,  True, False], dtype=bool)

【讨论】:

  • 广播的奇迹?它也很快(比其他答案快 20 倍)。
  • @Newmu 和字符串实习,如果我没记错的话(至少,a 中所有 'True' 的项目对于 id() 具有相同的值,对于所有'False' 元素[虽然奇怪的是,is 似乎不适用于这些元素。事实上,即使您针对自身测试条目,它也不起作用。a[0] is a[0] 返回False,即使id(a[0]) == id(a[0])返回True]) 我相信实习就是为什么这里的相等检查比numpy.char.startswith() 快得多,即使numpy.char 中的函数应该对numpy 数组执行快速字符串操作。
【解决方案2】:

我发现了一种比 DSM 更快的方法,从 Eric 那里获得了灵感,尽管在较小的值列表中可以看到这种改进;在非常大的值下,迭代本身的成本开始超过在创建 numpy 数组期间而不是之后执行真值测试的优势。使用is== 进行测试(对于字符串被实习的情况与它们可能不被实习的情况,因为is 不适用于非实习字符串。因为'True' 可能会是一个文字不过,它应该被实习的脚本)表明,虽然我使用 == 的版本比使用 is 的版本慢,但它仍然比 DSM 的版本快得多。

测试设置:

import timeit
def timer(statement, count):
    return timeit.repeat(statement, "from random import choice;import numpy as np;x = [choice(['True', 'False']) for i in range(%i)]" % count)

>>> stateIs = "y = np.fromiter((e is 'True' for e in x), bool)"
>>> stateEq = "y = np.fromiter((e == 'True' for e in x), bool)"
>>> stateDSM = "y = np.array(x) == 'True'"

对于 1000 个项目,更快的语句大约需要 DSM 的 66% 的时间:

>>> timer(stateIs, 1000)
[101.77722641656146, 100.74985342340369, 101.47228618107965]
>>> timer(stateEq, 1000)
[112.26464996250706, 112.50754567379681, 112.76057346127709]
>>> timer(stateDSM, 1000)
[155.67689949529995, 155.96820504501557, 158.32394669279802]

对于较小的字符串数组(数百个而不是数千个),经过的时间少于 DSM 的 50%:

>>> timer(stateIs, 100)
[11.947757485669172, 11.927990253608186, 12.057855628259858]
>>> timer(stateEq, 100)
[13.064947253943501, 13.161545451986967, 13.30599035623618]
>>> timer(stateDSM, 100)
[31.270060799078237, 30.941749748808434, 31.253922641324607]

当每个列表包含 50 个项目时,超过 25% 的 DSM:

>>> timer(stateIs, 50)
[6.856538342483873, 6.741083326021908, 6.708402786859551]
>>> timer(stateEq, 50)
[7.346079345032194, 7.312723444475523, 7.309259899921017]
>>> timer(stateDSM, 50)
[24.154247576229864, 24.173593700599667, 23.946403452288905]

对于 5 件商品,约占 DSM 的 11%:

>>> timer(stateIs, 5)
[1.8826215278058953, 1.850232652068371, 1.8559381315990322]
>>> timer(stateEq, 5)
[1.9252821868467436, 1.894011299061276, 1.894306935199893]
>>> timer(stateDSM, 5)
[18.060974208809057, 17.916322392367874, 17.8379771602049]

【讨论】:

  • 你有没有注意到结果中他们都是True? :-P
  • @DSM 我的新答案似乎比我的旧答案有了很大的改进。
  • @Newmu 我的两个即使是 5K 值仍然比 DSM 稍快,只是改进比较小的列表要小很多。
  • 啊,好吧!很难超越 DSM 的简单性。
【解决方案3】:

这够好吗?

my_list = ['True', 'False', 'True', 'False']
np.array(x == 'True' for x in my_list)

它不是原生的,但如果你从非原生列表开始,那真的没关系。

【讨论】:

  • 这不会像写的那样工作,因为 numpy 不能很好地处理生成器表达式。
  • 将它作为列表组合装箱是可行的,但它比 DSM 对具有数千个值的数组的回答慢 20 倍。
猜你喜欢
  • 2019-12-25
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多