看起来您的列表将类似于:
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]]])