删除零元素的对角线



我试图从原始形状重塑数组,使每行的元素沿对角线下降:

np.random.seed(0) 
my_array = np.random.randint(1, 50, size=(5, 3))
array([[45, 48,  1],
[ 4,  4, 40],
[10, 20, 22],
[37, 24,  7],
[25, 25, 13]])

我希望结果看起来像这样:

my_array_2 = np.array([[45,  0,  0],
[ 4, 48,  0],
[10,  4,  1],
[37, 20, 40],
[25, 24, 22],
[ 0, 25,  7],
[ 0,  0, 13]])

这是我能得到的最接近的解决方案:

my_diag = []
for i in range(len(my_array)):
my_diag_ = np.diag(my_array[i], k=0)
my_diag.append(my_diag_)
my_array1 = np.vstack(my_diag)
array([[45,  0,  0],
[ 0, 48,  0],
[ 0,  0,  1],
[ 4,  0,  0],
[ 0,  4,  0],
[ 0,  0, 40],
[10,  0,  0],
[ 0, 20,  0],
[ 0,  0, 22],
[37,  0,  0],
[ 0, 24,  0],
[ 0,  0,  7],
[25,  0,  0],
[ 0, 25,  0],
[ 0,  0, 13]])

从这里开始,我认为可以去除所有的零对角线,但我不确定如何做到这一点。

单向使用numpy.pad:

n = my_array.shape[1] - 1
np.dstack([np.pad(a, (i, n-i), "constant") 
for i, a in enumerate(my_array.T)])

输出:

array([[[45,  0,  0],
[ 4, 48,  0],
[10,  4,  1],
[37, 20, 40],
[25, 24, 22],
[ 0, 25,  7],
[ 0,  0, 13]]])
In [134]: arr = np.array([[45, 48,  1],
...:        [ 4,  4, 40],
...:        [10, 20, 22],
...:        [37, 24,  7],
...:        [25, 25, 13]])
In [135]: res= np.zeros((arr.shape[0]+arr.shape[1]-1, arr.shape[1]), arr.dtype)

np.diag如何索引对角线中得到提示,对arr:的行进行迭代

In [136]: for i in range(arr.shape[0]):
...:     n = i*arr.shape[1]
...:     m = arr.shape[1]
...:     res.flat[n:n+m**2:m+1] = arr[i,:]
...: 
In [137]: res
Out[137]: 
array([[45,  0,  0],
[ 4, 48,  0],
[10,  4,  1],
[37, 20, 40],
[25, 24, 22],
[ 0, 25,  7],
[ 0,  0, 13]])

numpy中可能有一个shift功能,但我不熟悉,所以这里有一个使用panda的解决方案。将np.zeros连接到原始数组,行数等于ncols-1。然后对每个列进行迭代,并将其下移等于列编号的数字。

import numpy as np
import pandas as pd
np.random.seed(0) 
my_array = np.random.randint(1,50, size=(5,3))
df = pd.DataFrame(np.concatenate((my_array,np.zeros((my_array.shape[1]-1, 
my_array.shape[1])))))
for col in df.columns:
df[col] = df[col].shift(int(col))
df.fillna(0).values

输出

array([[45.,  0.,  0.],
[ 4., 48.,  0.],
[10.,  4.,  1.],
[37., 20., 40.],
[25., 24., 22.],
[ 0., 25.,  7.],
[ 0.,  0., 13.]])

您可以使用简单的广播和填充为输出创建一个奇特的索引。首先填充数据的末尾:

a = np.concatenate((a, np.zeros((a.shape[1] - 1, a.shape[1]), a.dtype)), axis=0)

现在制作一个索引,使用负索引获取元素。这将使绕着终点滚动变得微不足道:

cols = np.arange(a.shape[1])
rows = np.arange(a.shape[0]).reshape(-1, 1) - cols

现在只是简单地索引:

result = a[rows, cols]

对于大型阵列,这可能不如运行小型循环那样高效。同时,这避免了实际的循环,并允许您编写一行代码(但请不要(:

result = np.concatenate((a, np.zeros((a.shape[1] - 1, a.shape[1]), a.dtype)), axis=0)[np.arange(a.shape[0] + a.shape[1] - 1).reshape(-1, 1) - np.arange(a.shape[1]), np.arange(a.shape[1])]

最新更新