Python 如何根据条件设置`np.array()`中的单元格值?
我有一个Python 如何根据条件设置`np.array()`中的单元格值?,python,arrays,numpy,Python,Arrays,Numpy,我有一个numpy数组和该数组中的有效值列表: import numpy as np arr = np.array([[1,2,0], [2,2,0], [4,1,0], [4,1,0], [3,2,0], ... ]) valid = [1,4] 是否有一种很好的pythonic方法将所有数组值设置为零,而这些值不在有效值列表中,并且就地执行?执行此操作后,列表应如下所示: [[1,0,0], [0,0,0], [4,1,0], [4,1,0], [0,0,0]
numpy
数组和该数组中的有效值列表:
import numpy as np
arr = np.array([[1,2,0], [2,2,0], [4,1,0], [4,1,0], [3,2,0], ... ])
valid = [1,4]
是否有一种很好的pythonic方法将所有数组值设置为零,而这些值不在有效值列表中,并且就地执行?执行此操作后,列表应如下所示:
[[1,0,0], [0,0,0], [4,1,0], [4,1,0], [0,0,0], ... ]
以下操作将在内存中创建阵列的副本,这对大型阵列不好:
arr = np.vectorize(lambda x: x if x in valid else 0)(arr)
这让我很恼火,现在我在每个数组元素上循环,如果它在有效的列表中,则将其设置为零
编辑:我发现了一个建议,即没有现成的功能来实现这一点。也不要改变我的空白。在arr
中更容易看到这些更改。您可以使用就地更新-
np.place(arr,~np.in1d(arr,valid),0)
样本运行-
In [66]: arr
Out[66]:
array([[1, 2, 0],
[2, 2, 0],
[4, 1, 0],
[4, 1, 0],
[3, 2, 0]])
In [67]: np.place(arr,~np.in1d(arr,valid),0)
In [68]: arr
Out[68]:
array([[1, 0, 0],
[0, 0, 0],
[4, 1, 0],
[4, 1, 0],
[0, 0, 0]])
In [70]: arr
Out[70]:
array([[1, 2, 0],
[2, 2, 0],
[4, 1, 0],
[4, 1, 0],
[3, 2, 0]])
In [71]: np.put(arr,np.where(~np.in1d(arr,valid))[0],0)
In [72]: arr
Out[72]:
array([[1, 0, 0],
[0, 0, 0],
[4, 1, 0],
[4, 1, 0],
[0, 0, 0]])
同样,也可以使用np.put
-
np.put(arr,np.where(~np.in1d(arr,valid))[0],0)
样本运行-
In [66]: arr
Out[66]:
array([[1, 2, 0],
[2, 2, 0],
[4, 1, 0],
[4, 1, 0],
[3, 2, 0]])
In [67]: np.place(arr,~np.in1d(arr,valid),0)
In [68]: arr
Out[68]:
array([[1, 0, 0],
[0, 0, 0],
[4, 1, 0],
[4, 1, 0],
[0, 0, 0]])
In [70]: arr
Out[70]:
array([[1, 2, 0],
[2, 2, 0],
[4, 1, 0],
[4, 1, 0],
[3, 2, 0]])
In [71]: np.put(arr,np.where(~np.in1d(arr,valid))[0],0)
In [72]: arr
Out[72]:
array([[1, 0, 0],
[0, 0, 0],
[4, 1, 0],
[4, 1, 0],
[0, 0, 0]])
使用布尔值进行索引也可以:
>>> arr = np.array([[1, 2, 0], [2, 2, 0], [4, 1, 0], [4, 1, 0], [3, 2, 0]])
>>> arr[~np.in1d(arr, valid).reshape(arr.shape)] = 0
>>> arr
array([[1, 0, 0],
[0, 0, 0],
[4, 1, 0],
[4, 1, 0],
[0, 0, 0]])
我怀疑这也会创建一个临时副本,因为您要重塑一个数组,并将其与原始数组相乘。所以它不符合我的“就地”要求。您可以在操作后键入arr
来查看这一点。它仍然会给你原来的数组三三两两。你真的应该只做一个新的答案,而不是一遍又一遍地编辑你的旧答案。这使讨论变得困难。使用np.place(arr,~np.in1d(arr,valid),0)
in1d部分仍然创建整个数组的内存副本,与np.put(arr,np.where(~np.in1d(arr,valid))[0]相同。
@con-f-use,据我所知,~np.in1d(arr,valid)
将是一个布尔数组,因此比典型的整数数组占用更少的内存,如果我在这里出错,请更正。然后它在arr
中进行现场更新,因此没有涉及其他副本。同意,np.zeroes((100),dtype=bool)。nbytes
np.zeroes((100),dtype=float)。nbytes
。但我的问题是,在某些目标系统上,arr
已经很难放入内存,甚至比原来的阵列小1/8的阵列也可能会导致问题。这也是一个主要问题;-)不过,我还是要感谢你花了这么多时间!我确信没有就地功能,循环是不可避免的。请看我的编辑。@con-f-use是的,我想这是你需要做的权衡,对不起!我想是情不自禁:)或者如果你喜欢中间立场,可以分块做!