假设我有一个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,也应该为此效果很好。