选择沿Numpy数组中每一列的顶部K值的所有出现



假设我有一个numpy数组,如下所示:我的原始数组是50k x8.5k。这是样本

array([[ 1. ,  2. ,  3. ],
   [ 1. ,  0.5,  2. ],
   [ 2. ,  3. ,  1. ]])

现在,我想要的是,对于每列,只保留顶部的K值(在此处以K为2),然后将其他重新编码为零。

所以我希望输出是这样的:

array([[ 1.,  2.,  3.],
       [ 1.,  0.,  2.],
       [ 2.,  3.,  0.]])

基本上,如果我们看到的话,我们将每个列值排序降序,然后检查该列的每个值是否不在该列的最大值之中,然后将该值重新编码为零

我尝试了这样的事情,但是它给出了错误

for x in range(e.shape[1]):
    e[:,x]=map(np.where(lambda x: x in e[:,x][::-1][:2], x, 0), e[:,x])

     2 
      3 for x in range(e.shape[1]):
----> 4     e[:,x]=map(np.where(lambda x: x in e[:,x][::-1][:2], x, 0), e[:,x])
      5 
TypeError: 'numpy.ndarray' object is not callable

目前,我也在迭代每一列。由于我喜欢50k行和8k列以来,任何快速起作用的解决方案都可以为每列迭代,然后为每列进行每个值的映射,在该列中,我猜是很耗时。

请建议。

重点是这样大数组的性能,这是一种矢量化的方法来解决它 -

K = 2 # Select top K values along each column
# Sort A, store the argsort for later usage
sidx = np.argsort(A,axis=0)
sA = A[sidx,np.arange(A.shape[1])]
# Perform differentiation along rows and look for non-zero differentiations
df = np.diff(sA,axis=0)!=0
# Perform cumulative summation along rows from bottom upwards. 
# Thus, summations < K should give us a mask of valid ones that are to 
# be kept per column. Use this mask to set rest as zeros in sorted array.
mask = (df[::-1].cumsum(0)<K)[::-1]
sA[:-1] *=mask
# Finally revert back to unsorted order by using sorted indices sidx
out = sA[sidx.argsort(0),np.arange(sA.shape[1])]

请注意,要获得更多性能提升,np.argsort可以用np.argpartition代替。

样品输入,ouput-

In [343]: A
Out[343]: 
array([[106, 106, 102],
       [105, 101, 104],
       [106, 107, 101],
       [107, 103, 106],
       [106, 105, 108],
       [106, 104, 105],
       [107, 101, 101],
       [105, 103, 102],
       [104, 102, 106],
       [104, 106, 101]])
In [344]: out
Out[344]: 
array([[106, 106,   0],
       [  0,   0,   0],
       [106, 107,   0],
       [107,   0, 106],
       [106,   0, 108],
       [106,   0,   0],
       [107,   0,   0],
       [  0,   0,   0],
       [  0,   0, 106],
       [  0, 106,   0]])

这应该把您带到那里:

def rwhere(a, b, p, k):
    if p >= len(b) or p >= k:
        return 0
    else:
        return np.where(a == b[p], b[p], rwhere(a, b, p + 1, k))
def codek(a, k):
    b = a.copy()
    b.sort(0)
    b = b[::-1]
    return rwhere(a, b, 0, k)
codek(a, 2)
array([[ 1.,  2.,  3.],
       [ 1.,  0.,  2.],
       [ 2.,  3.,  0.]])

好。我只是弄清楚我的代码中有什么问题。Where子句应为Lambda功能的返回条件。以下工作正常。

array([[ 1. ,  2. ,  3. ],
       [ 1. ,  0.5,  2. ],
       [ 2. ,  3. ,  1. ]])
e=copy.deepcopy(a)
for y in range(e.shape[1]):
    e[:,y]=map(lambda x: np.where(x in np.sort(a[:,y])[::-1][:2],x, 0), e[:,y])
array([[ 1.,  2.,  3.],
       [ 1.,  0.,  2.],
       [ 2.,  3.,  0.]])
In [297]:

我可以将其保留为k,也应该为此效果很好。

相关内容

最新更新