我正在尝试加快对列表的理解,我尝试使用numpy.vectorize
,但无法使其正常工作。可以使用该功能吗?如果可以,如何或是否有另一种方法可以使此功能更快?列表“ a”是一个numpy ndarray(在2D模式下),因此我知道要使其更快,您应该使用numpy函数而不是列表推导,但是找不到使用这些函数的方法。
[[[255,255,255] if y else [0,0,0] for y in row ] for row in a]
答案 0 :(得分:2)
您可以使用np.where
:
In [11]: np.where(a, np.array([255, 255, 255]), 0)
Out[11]:
array([[255, 255, 255],
[ 0, 0, 0],
[255, 255, 255]]
另一种方法是先创建一个完整的数组或零个数组,然后更新行:
In [21] res = np.zeros((3, 3))
In [22]: np.where(a == 0, res, 255)
Out[22]:
array([[255., 255., 255.],
[ 0., 0., 0.],
[255., 255., 255.]])
答案 1 :(得分:1)
您的列表看起来像是这样:
In [22]: alist = [[0,1,2],[3,0,0]]
理解的结果:
In [23]: [[[255,255,255] if y else [0,0,0] for y in row] for row in alist]
Out[23]:
[[[0, 0, 0], [255, 255, 255], [255, 255, 255]],
[[255, 255, 255], [0, 0, 0], [0, 0, 0]]]
要在numpy
中执行类似的操作,请创建一个数组(子列表的长度必须全部相同):
In [24]: arr = np.array(alist)
In [25]: arr
Out[25]:
array([[0, 1, 2],
[3, 0, 0]])
制作目标数组-3d形状:
In [27]: res = np.zeros(arr.shape+(3,),int)
In [28]: res
Out[28]:
array([[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]])
y
不为0的掩码:
In [29]: mask = arr!=0
In [30]: mask
Out[30]:
array([[False, True, True],
[ True, False, False]])
此遮罩将选择res
的3个元素:
In [31]: res[mask]
Out[31]:
array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
我们可以使用标量来设置值:
In [32]: res[mask] = 255
In [33]: res
Out[33]:
array([[[ 0, 0, 0],
[255, 255, 255],
[255, 255, 255]],
[[255, 255, 255],
[ 0, 0, 0],
[ 0, 0, 0]]])
或数组:
In [34]: res[mask] = [255,255,255]
In [35]: res
Out[35]:
array([[[ 0, 0, 0],
[255, 255, 255],
[255, 255, 255]],
[[255, 255, 255],
[ 0, 0, 0],
[ 0, 0, 0]]])
有时在设置这样的掩码数组时,我们会遇到广播错误-目标数组和源数组之间不匹配。
另一种方法是将mask
视为0/1索引数组:
In [37]: x = np.array([[0,0,0],[255,255,255]])
In [39]: x[mask.astype(int)]
Out[39]:
array([[[ 0, 0, 0],
[255, 255, 255],
[255, 255, 255]],
[[255, 255, 255],
[ 0, 0, 0],
[ 0, 0, 0]]])
如果您从列表开始,则列表理解方法可能是最快的。尽管数组索引编制速度很快,但将列表转换为数组的开销却很大。
====
要使用np.vectorize
来做到这一点,我已经习惯了signature
,它比常规的vectorize
慢:
In [49]: np.vectorize(lambda y: np.array([255,255,255]) if y else np.array([0,0,
...: 0]), signature='()->(n)')(alist)
Out[49]:
array([[[ 0, 0, 0],
[255, 255, 255],
[255, 255, 255]],
[[255, 255, 255],
[ 0, 0, 0],
[ 0, 0, 0]]])
答案 2 :(得分:0)
在尝试了更多的东西之后,我发现了这个oneliner,它可以完成工作,而且速度也很快。
np.where(a != 0, 0, 255).repeat(3, 1).reshape(len(a), len(a[0]), 3)