假设我有两个数组:a = array([1,2,3,0,4,5,0])
和b = array([1,2,3,4,0,5,6])
。我有兴趣删除a
和b
为0
的实例。但我也想从两个列表中删除相应的实例。因此,我最终想要的是a = array([1,2,3,5])
和b = array([1,2,3,5])
。这是因为a[3] == 0
和a[6] == 0
,因此同时删除了b[3]
和b[6]
。同样,由于b[4] == 0
,a[4]
也被删除。对于两个数组来说,这样做很简单:
import numpy as np
a = np.array([1,2,3,0,4,5,0])
b = np.array([1,2,3,4,0,5,6])
ix = np.where(b == 0)
b = np.delete(b, ix)
a = np.delete(a, ix)
ix = np.where(a == 0)
b = np.delete(b, ix)
a = np.delete(a, ix)
然而,如果我有许多阵列(我这样做),这个解决方案不会扩展。什么是更优雅的方式来做到这一点?
如果我尝试以下方法:
import numpy as np
a = np.array([1,2,3,0,4,5,0])
b = np.array([1,2,3,4,0,5,6])
arrays = [a,b]
for array in arrays:
ix = np.where(array == 0)
b = np.delete(b, ix)
a = np.delete(a, ix)
我得到a = array([1, 2, 3, 4])
和b = array([1, 2, 3, 0])
,而不是我需要的答案。知道这是错的吗?
答案 0 :(得分:3)
假设两个/所有数组的长度始终相同,则可以使用masks:
ma = a != 0 # mask elements which are not equal to zero in a
mb = b != 0 # mask elements which are not equal to zero in b
m = ma * mb # assign the intersection of ma and mb to m
print a[m], b[m] # [1 2 3 5] [1 2 3 5]
您当然也可以在一行中完成
m = (a != 0) * (b != 0)
或使用反向
ma = a == 0
mb = b == 0
m = ~(ma + mb) # not the union of ma and mb
答案 1 :(得分:1)
这种情况正在发生,因为从np.delete返回时,会得到一个存储在b和循环内部的数组。但是,存储在数组变量中的数组是副本,而不是引用。因此,当您通过删除数组更新数组时,它会删除与原始数组有关的数组。第一个循环将返回数组中的校正索引0,但第二个循环将ix返回为4(查看原始数组)。
如果在每次迭代中显示数组变量,它将保留同样的。
完成处理一个数组后,需要重新分配数组,以便在下一次迭代时将其考虑在内。这是你如何做到的 -
a = np.array([1, 2, 3, 0, 4, 5, 0])
b = np.array([1, 2, 3, 4, 0, 5, 6])
arrays = [a,b]
for i in range(0, len(arrays)):
ix = np.where(arrays[i] == 0)
b = np.delete(b, ix)
a = np.delete(a, ix)
arrays = [a, b]
当然,您可以自动化循环内部发生的事情。我只是想解释发生了什么。
答案 2 :(得分:0)
慢速方法涉及对整个列表进行两次操作,首先构建要删除的索引的中间列表,然后再删除这些索引处的所有值:
Time.at(1441584686)
=> 2015-09-06 17:11:26 -0700
答案 3 :(得分:0)
建立在Christoph Terasa的答案之上,您可以使用数组操作而不是for循环:
arrays = np.vstack([a,b]) # ...long list of arrays of equal length
zeroind = (arrays==0).max(0)
pos_arrays = arrays[:,~zeroind] # a 2d array only containing those columns where none of the lines contained zeros