沿着下三角形numpy数组的每一行翻转非零值

时间:2021-12-16 21:22:55

I have a lower triangular array, like B:

我有一个较低的三角形数组,如B:

B = np.array([[1,0,0,0],[.25,.75,0,0], [.1,.2,.7,0],[.2,.3,.4,.1]])

>>> B
array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.25,  0.75,  0.  ,  0.  ],
       [ 0.1 ,  0.2 ,  0.7 ,  0.  ],
       [ 0.2 ,  0.3 ,  0.4 ,  0.1 ]])

I want to flip it to look like:

我想把它翻转成:

array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.75,  0.25,  0.  ,  0.  ],
       [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
       [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

That is, I want to take all the positive values, and reverse within the positive values, leaving the trailing zeros in place. This is not what fliplr does:

也就是说,我想获取所有正值,并在正值内反转,留下尾随零。这不是fliplr的作用:

>>> np.fliplr(B)
array([[ 0.  ,  0.  ,  0.  ,  1.  ],
       [ 0.  ,  0.  ,  0.75,  0.25],
       [ 0.  ,  0.7 ,  0.2 ,  0.1 ],
       [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

Any tips? Also, the actual array I am working with would be something like B.shape = (200,20,4,4) instead of (4,4). Each (4,4) block looks like the above example (with different numbers across the 200, 20 different entries).

有小费吗?此外,我正在使用的实际数组将类似于B.shape =(200,20,4,4)而不是(4,4)。每个(4,4)块看起来像上面的例子(在200个不同的条目中有不同的数字)。

2 个解决方案

#1


8  

How about this:

这个怎么样:

# row, column indices of the lower triangle of B
r, c = np.tril_indices_from(B)

# flip the column indices by subtracting them from r, which is equal to the number
# of nonzero elements in each row minus one
B[r, c] = B[r, r - c]

print(repr(B))
# array([[ 1.  ,  0.  ,  0.  ,  0.  ],
#        [ 0.75,  0.25,  0.  ,  0.  ],
#        [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
#        [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

The same approach will generalize to any arbitrary N-dimensional array that consists of multiple lower triangular submatrices:

相同的方法将推广到由多个下三角形子矩阵组成的任意N维数组:

# creates a (200, 20, 4, 4) array consisting of tiled copies of B
B2 = np.tile(B[None, None, ...], (200, 20, 1, 1))

print(repr(B2[100, 10]))
# array([[ 1.  ,  0.  ,  0.  ,  0.  ],
#        [ 0.25,  0.75,  0.  ,  0.  ],
#        [ 0.1 ,  0.2 ,  0.7 ,  0.  ],
#        [ 0.2 ,  0.3 ,  0.4 ,  0.1 ]])

r, c = np.tril_indices_from(B2[0, 0])
B2[:, :, r, c] = B2[:, :, r, r - c]

print(repr(B2[100, 10]))
# array([[ 1.  ,  0.  ,  0.  ,  0.  ],
#        [ 0.75,  0.25,  0.  ,  0.  ],
#        [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
#        [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

For an upper triangular matrix you could simply subtract r from c instead, e.g.:

对于上三角矩阵,您可以简单地从c中减去r,例如:

r, c = np.triu_indices_from(B.T)
B.T[r, c] = B.T[c - r, c]

#2


4  

Here's one approach for a 2D array case -

这是2D阵列案例的一种方法 -

mask = np.tril(np.ones((4,4),dtype=bool))
out = np.zeros_like(B)
out[mask] = B[:,::-1][mask[:,::-1]]

You can extend it to a 3D array case using the same 2D mask by masking the last two axes with it, like so -

您可以使用相同的2D蒙版将其扩展为3D阵列大小写,方法是用它来掩盖最后两个轴,就像这样 -

out = np.zeros_like(B)
out[:,mask] = B[:,:,::-1][:,mask[:,::-1]]

.. and similarly for a 4D array case, like so -

..和类似的4D阵列情况,如此 -

out = np.zeros_like(B)
out[:,:,mask] = B[:,:,:,::-1][:,:,mask[:,::-1]]

As one can see, we are keeping the masking process to the last two axes of (4,4) and the solution basically stays the same.

可以看出,我们将屏蔽过程保持到(4,4)的最后两个轴,并且解决方案基本保持不变。

Sample run -

样品运行 -

In [95]: B
Out[95]: 
array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.25,  0.75,  0.  ,  0.  ],
       [ 0.1 ,  0.2 ,  0.7 ,  0.  ],
       [ 0.2 ,  0.3 ,  0.4 ,  0.1 ]])

In [96]: mask = np.tril(np.ones((4,4),dtype=bool))
    ...: out = np.zeros_like(B)
    ...: out[mask] = B[:,::-1][mask[:,::-1]]
    ...: 

In [97]: out
Out[97]: 
array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.75,  0.25,  0.  ,  0.  ],
       [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
       [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

#1


8  

How about this:

这个怎么样:

# row, column indices of the lower triangle of B
r, c = np.tril_indices_from(B)

# flip the column indices by subtracting them from r, which is equal to the number
# of nonzero elements in each row minus one
B[r, c] = B[r, r - c]

print(repr(B))
# array([[ 1.  ,  0.  ,  0.  ,  0.  ],
#        [ 0.75,  0.25,  0.  ,  0.  ],
#        [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
#        [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

The same approach will generalize to any arbitrary N-dimensional array that consists of multiple lower triangular submatrices:

相同的方法将推广到由多个下三角形子矩阵组成的任意N维数组:

# creates a (200, 20, 4, 4) array consisting of tiled copies of B
B2 = np.tile(B[None, None, ...], (200, 20, 1, 1))

print(repr(B2[100, 10]))
# array([[ 1.  ,  0.  ,  0.  ,  0.  ],
#        [ 0.25,  0.75,  0.  ,  0.  ],
#        [ 0.1 ,  0.2 ,  0.7 ,  0.  ],
#        [ 0.2 ,  0.3 ,  0.4 ,  0.1 ]])

r, c = np.tril_indices_from(B2[0, 0])
B2[:, :, r, c] = B2[:, :, r, r - c]

print(repr(B2[100, 10]))
# array([[ 1.  ,  0.  ,  0.  ,  0.  ],
#        [ 0.75,  0.25,  0.  ,  0.  ],
#        [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
#        [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])

For an upper triangular matrix you could simply subtract r from c instead, e.g.:

对于上三角矩阵,您可以简单地从c中减去r,例如:

r, c = np.triu_indices_from(B.T)
B.T[r, c] = B.T[c - r, c]

#2


4  

Here's one approach for a 2D array case -

这是2D阵列案例的一种方法 -

mask = np.tril(np.ones((4,4),dtype=bool))
out = np.zeros_like(B)
out[mask] = B[:,::-1][mask[:,::-1]]

You can extend it to a 3D array case using the same 2D mask by masking the last two axes with it, like so -

您可以使用相同的2D蒙版将其扩展为3D阵列大小写,方法是用它来掩盖最后两个轴,就像这样 -

out = np.zeros_like(B)
out[:,mask] = B[:,:,::-1][:,mask[:,::-1]]

.. and similarly for a 4D array case, like so -

..和类似的4D阵列情况,如此 -

out = np.zeros_like(B)
out[:,:,mask] = B[:,:,:,::-1][:,:,mask[:,::-1]]

As one can see, we are keeping the masking process to the last two axes of (4,4) and the solution basically stays the same.

可以看出,我们将屏蔽过程保持到(4,4)的最后两个轴,并且解决方案基本保持不变。

Sample run -

样品运行 -

In [95]: B
Out[95]: 
array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.25,  0.75,  0.  ,  0.  ],
       [ 0.1 ,  0.2 ,  0.7 ,  0.  ],
       [ 0.2 ,  0.3 ,  0.4 ,  0.1 ]])

In [96]: mask = np.tril(np.ones((4,4),dtype=bool))
    ...: out = np.zeros_like(B)
    ...: out[mask] = B[:,::-1][mask[:,::-1]]
    ...: 

In [97]: out
Out[97]: 
array([[ 1.  ,  0.  ,  0.  ,  0.  ],
       [ 0.75,  0.25,  0.  ,  0.  ],
       [ 0.7 ,  0.2 ,  0.1 ,  0.  ],
       [ 0.1 ,  0.4 ,  0.3 ,  0.2 ]])