首页 > 解决方案 > Numpy,改变数组的行值,每一行满足一个特殊条件

问题描述

我有一个二维数组,它有大量的行(大于 5000)。

为了简单起见,假设 A 是我的矩阵的简单版本

A=([[1,2,2,3,3,3],
   [[2,1,1,7,7,7],
   [[4,4,1,1,1,1]])

现在,A 只有 3 行:

第一行有 3 个值:一个 1、两个 2、三个 3。

第二行有 3 个值,一个 2,两个 1,三个 7。

最后一行有 2 个值,两个 4,四个 1。

现在我可以很容易地找到每一行的多数值:

第一个是 3,第二个是 7,第三个是 1。(意味着我的代码已经找到每一行的多数值并将它们存储为 [3,7,1] )

我想要做的是将每一行的多数值设置为 0。

意味着集合

A=([[1,2,2,0,0,0],
   [[2,1,1,0,0,0],
   [[4,4,0,0,0,0]])

A 只是一个简单的实例。我的矩阵有大量的行。

那么,如何更轻松、更高效地做这件事呢?

我不想编写一个 for 循环来设置每一行的值。

(意味着我可以做 A[0,A[0,:]==3]=0, A[1,A[1,:]==7]=0, A[2,A[2,:]= =1]=0,但这太复杂了)

我想要的是这样的表格:

A[:,A[:,:]==[3,7,1]]=0

但是numpy没有这个能力。

任何人都可以给我一个有效的方法吗?非常感谢!!!

对于更一般的情况,如果我想将每行的第一个最大值设置为 0,第二个最大值设置为 -1,第三个最大值(如果存在)设置为 -2 ....,该怎么做?

意味着设置:

A=([[-2,-1,-1,0,0,0],
   [[-2,-1,-1,0,0,0],
   [[-1,-1,0,0,0,0]])

标签: arraysnumpy

解决方案


方法#1

使用2D bincount-

# https://stackoverflow.com/a/46256361/ @Divakar
def bincount2D_vectorized(a):    
    N = a.max()+1
    a_offs = a + np.arange(a.shape[0])[:,None]*N
    return np.bincount(a_offs.ravel(), minlength=a.shape[0]*N).reshape(-1,N)

A[A==bincount2D_vectorized(A).argmax(1)[:,None]] = 0

样品运行 -

In [16]: A
Out[16]: 
array([[1, 2, 2, 3, 3, 3],
       [2, 1, 1, 7, 7, 7],
       [4, 4, 1, 1, 1, 1]])

In [17]: A[A==bincount2D_vectorized(A).argmax(1)[:,None]] = 0

In [18]: A
Out[18]: 
array([[1, 2, 2, 0, 0, 0],
       [2, 1, 1, 0, 0, 0],
       [4, 4, 0, 0, 0, 0]])

方法#2

有效使用2D mode-

A[A==mode(A.T,axis=0)[0][:,None]] = 0

或者,从同一个问答中,我们可以使用 Scipy -

from scipy import stats

A[A==stats.mode(A.T)[0][0][:,None]] = 0

推荐阅读