选择NumPy数组中每列的所有顶部K值

时间:2016-06-20 19:33:40

标签: python numpy

假设我有一个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.]])

所以基本上如果我们看到,我们会按降序对每个列值进行排序,然后检查该列的每个值是否不在该列的k-最大值之间,然后将该值重新编码为零

我尝试过这样的事情,但是却出错了

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列,因此对每列进行迭代,然后对于每列执行该列中每个值的映射将是耗时的。

请指教。

3 个答案:

答案 0 :(得分:1)

关注这些大型阵列的性能,这是解决它的矢量化方法 -

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

样本输入,输出 -

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]])

答案 1 :(得分: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.]])

答案 2 :(得分: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]:

而不是2我可以将它保持为K,并且应该也可以正常工作。