【问题标题】:Delete diagonals of zero elements删除零元素的对角线
【发布时间】:2020-12-30 11:41:43
【问题描述】:

我正在尝试从其原始形状重塑一个数组,以使每一行的元素沿对角线下降:

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]])

从这里我认为有可能删除所有零对角线,但我不知道该怎么做。

【问题讨论】:

  • 不要忘记选择一个答案以将您的问题从未回答队列中删除,并为任何对您提供帮助的人投票。
  • 谢谢大家的帮助!
  • 感谢的正确方式是点赞。当所选答案的赞成票为零时,这看起来很奇怪。

标签: python numpy numpy-ndarray diagonal


【解决方案1】:

一种使用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]]])

【讨论】:

    【解决方案2】:
    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]])
    

    【讨论】:

      【解决方案3】:

      numpy 中可能有 shift 功能,但我不熟悉它,所以这里有一个使用 pandas 的解决方案。您将 np.zeros 连接到原始数组,其中行数等于 ncols - 1。然后遍历每个 col 并将其向下移动等于列号的数字。

      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.]])
      

      【讨论】:

        【解决方案4】:

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

        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])]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-16
          • 1970-01-01
          • 2022-01-07
          • 2014-05-04
          • 2013-05-24
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多