将python2混合类型的np.array操作迁移到python3

时间:2020-02-10 09:24:24

标签: python-3.x numpy migration numpy-ndarray mixed-type

我正在从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不太热衷于类型。迁移此内容的最佳方法是什么?

2 个答案:

答案 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),因为None0都将得出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),)

时间比较:

enter image description here

因此,鲍勃(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)',
    )