我正在从python2迁移到python3,并且遇到了一个我简化为的问题:
import numpy as np
a = np.array([1, 2, None])
(a > 0).nonzero()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: '>' not supported between instances of 'NoneType' and 'int'
实际上,我正在处理具有数百万个数据的np阵列,确实需要保持np操作以提高性能。在python 2中,这工作正常,并返回了我期望的结果,因为python2不太热衷于类型。迁移此内容的最佳方法是什么?
答案 0 :(得分:1)
最后,在@CDJB和@DeepSpace的帮助下,我发现的最佳解决方案是 将None值替换为适合特定操作的值。还包括用于不弄乱原始数据的数组的深层副本。
import numpy as np
a = np.array([1, None, 2, None])
deep_copy = np.copy(a)
deep_copy[deep_copy == None] = 0
result = (deep_copy > 0).nonzero()[0]
print(result)
[0 2]
答案 1 :(得分:1)
获得预期结果的一种方法是对np.vectorize
使用lambda函数:
>>> a = np.array([1, 2, None, 4, -1])
>>> f = np.vectorize(lambda t: t and t>0)
>>> np.where(f(a))
(array([0, 1, 3], dtype=int64),)
当然,如果数组不包含负整数,则可以只使用np.where(a)
,因为None
和0
都将得出False
:>
>>> a = np.array([1, 2, None, 4, 0])
>>> np.where(a)
(array([0, 1, 3], dtype=int64),)
可以解决此问题的另一种方法是,首先将数组转换为使用float dtype,其效果是将None
转换为np.nan
。然后np.where(a>0)
可以正常使用。
>>> a = np.array([1, 2, None, 4, -1])
>>> np.where(a.astype(float) > 0)
(array([0, 1, 3], dtype=int64),)
时间比较:
因此,鲍勃(Bob)的方法虽然不那么容易看,但它的速度大约是np.vectorise
方法的两倍,并且比浮点转换方法稍慢。
要复制的代码:
import perfplot
import numpy as np
f = np.vectorize(lambda t: t and t>0)
choices = list(range(-10,11)) + [None]
def cdjb(arr):
return np.where(f(arr))
def cdjb2(arr):
return np.where(arr.astype(float) > 0)
def Bob(arr):
deep_copy = np.copy(arr)
deep_copy[deep_copy == None] = 0
return (deep_copy > 0).nonzero()[0]
perfplot.show(
setup=lambda n: np.random.choice(choices, size=n),
n_range=[2**k for k in range(25)],
kernels=[
cdjb, cdjb2, Bob
],
xlabel='len(a)',
)