转换矩阵

3

我有一个小的numpy矩阵,矩阵中的值只能是0或1。实际使用的矩阵大小要大得多,但为了演示,这个大小可以接受。它的形状是(8,11)

np_array = np.matrix(
   [[0,0,0,0,1,0,0,0,0,0,0],
    [0,0,0,1,0,1,0,0,0,0,0],
    [0,0,0,1,0,1,0,0,0,0,0],
    [0,0,1,0,0,1,1,0,0,0,0],
    [0,0,1,0,0,0,1,0,0,0,0],
    [0,1,0,0,0,0,1,1,0,1,1],
    [0,1,0,0,0,0,0,1,0,1,0],
    [1,0,0,0,0,0,0,1,1,1,0]]
)

我需要以这样的方式更改它,使得每列只有一行具有值1。这样,如果同一列中有多行值为1,则保留值最高的1行,并将其余部分替换为0。

这是我想要的结果:

np_array1 = np.matrix(
   [[0,0,0,0,1,0,0,0,0,0,0],
    [0,0,0,1,0,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0],
    [0,0,1,0,0,0,1,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0],
    [0,1,0,0,0,0,0,1,0,1,1],
    [0,0,0,0,0,0,0,0,0,0,0],
    [1,0,0,0,0,0,0,0,1,0,0]]
)

基本上每一列都可以有一个值为1,如果有多行,则保留最高的值。我必须提到,也可能存在没有行具有值为1的列。这些列必须保持不变。转换后矩阵的形状必须与之前完全相同。

4个回答

3

这里有一种方法 -

def per_col(a):
    idx = a.argmax(0)
    out = np.zeros_like(a)
    r = np.arange(a.shape[1])
    out[idx, r] = a[idx, r]
    return out

样例运行

案例 #1 :

In [41]: a
Out[41]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1],
       [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0],
       [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0]])

In [42]: per_col(a)
Out[42]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]])

案例 #2(插入全0列):

In [78]: a[:,1] = 0

In [79]: a
Out[79]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
       [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0]])

In [80]: per_col(a)
Out[80]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]])

如果你喜欢单行代码或者是广播技术的粉丝,这里有另一种——
((a.argmax(0) == np.arange(a.shape[0])[:,None]).astype(int))*a.any(0)

运行示例 -

In [89]: a
Out[89]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
       [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0]])

In [90]: ((a.argmax(0) == np.arange(a.shape[0])[:,None]).astype(int))*a.any(0)
Out[90]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]])

运行时测试 -

In [98]: a = np.random.randint(0,2,(100,10000))

# @DSM's soln
In [99]: %timeit ((a == 1) & (a.cumsum(axis=0) == 1)).astype(int)
100 loops, best of 3: 5.19 ms per loop

# Proposed in this post : soln1
In [100]: %timeit per_col(a)
100 loops, best of 3: 3.4 ms per loop

# Proposed in this post : soln2
In [101]: %timeit ((a.argmax(0) == np.arange(a.shape[0])[:,None]).astype(int))*a.any(0)
100 loops, best of 3: 7.73 ms per loop

3

您可以使用 cumsum 函数来计算出现的 1 的数量,然后选择第一个:

In [42]: arr.cumsum(axis=0)
Out[42]: 
matrix([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0],
        [0, 0, 1, 2, 1, 3, 1, 0, 0, 0, 0],
        [0, 0, 2, 2, 1, 3, 2, 0, 0, 0, 0],
        [0, 1, 2, 2, 1, 3, 3, 1, 0, 1, 1],
        [0, 2, 2, 2, 1, 3, 3, 2, 0, 2, 1],
        [1, 2, 2, 2, 1, 3, 3, 3, 1, 3, 1]])

因此
In [43]: ((arr == 1) & (arr.cumsum(axis=0) == 1)).astype(int)
Out[43]: 
matrix([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]])

1

another approach is:

for i in range(a.shape[1]):
    a[np.where(a[:,i]==1)[0][1:],i] = 0

输出:

[[0 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 1 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0]
 [0 1 0 0 0 0 0 1 0 1 1]
 [0 0 0 0 0 0 0 0 0 0 0]
 [1 0 0 0 0 0 0 0 1 0 0]]

1

您可以使用非零和唯一函数:

c, r = np.nonzero(np_array.T)
_, ind = np.unique(c, return_index=True)
np_array[:] = 0
np_array[r[ind], c[ind]] = 1

给定这个例子,结果是:
[[0 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 1 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0]
 [0 0 1 0 0 0 1 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0]
 [0 1 0 0 0 0 0 1 0 1 1]
 [0 0 0 0 0 0 0 0 0 0 0]
 [1 0 0 0 0 0 0 0 1 0 0]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接