【问题标题】:Inserting rows of zeros at specific places along the rows of a NumPy array在 NumPy 数组的行中的特定位置插入零行
【发布时间】:2016-08-16 10:46:07
【问题描述】:

我有一个两列 numpy 数组。我想遍历第二列的每一行,并计算每组 2 个数字(9.6-0、19.13-9.6 等)之间的差异。如果差值 > 15,我想为两列插入一行 0。我真的只需要在第一列中得到值(我只需要第二列来确定在哪里放置 0),所以如果更容易将它们分开就可以了。

这是我的输入数组:

 [[0.00 0.00]
 [1.85 9.60]
 [2.73 19.13]
 [0.30 28.70]
 [2.64 38.25]
 [2.29 47.77]
 [2.01 57.28]
 [2.61 66.82]
 [2.20 76.33]
 [2.49 85.85]
 [2.55 104.90]
 [2.65 114.47]
 [1.79 123.98]
 [2.86 133.55]]

它应该变成:

 [[0.00 0.00]
 [1.85 9.60]
 [2.73 19.13]
 [0.30 28.70]
 [2.64 38.25]
 [2.29 47.77]
 [2.01 57.28]
 [2.61 66.82]
 [2.20 76.33]
 [2.49 85.85]
 [0.00 0.00]
 [2.55 104.90]
 [2.65 114.47]
 [1.79 123.98]
 [2.86 133.55]]

【问题讨论】:

    标签: python arrays python-2.7 numpy


    【解决方案1】:

    您可以使用ediff1dargmaxinsert 来自numpy 的一个班轮:

    np.insert(arr, np.argmax(np.append(False, np.ediff1d(arr[:,1])>15)), 0, axis=0)
    
    #array([[   0.  ,    0.  ],
    #       [   1.85,    9.6 ],
    #       [   2.73,   19.13],
    #       [   0.3 ,   28.7 ],
    #       [   2.64,   38.25],
    #       [   2.29,   47.77],
    #       [   2.01,   57.28],
    #       [   2.61,   66.82],
    #       [   2.2 ,   76.33],
    #       [   2.49,   85.85],
    #       [   0.  ,    0.  ],
    #       [   2.55,  104.9 ],
    #       [   2.65,  114.47],
    #       [   1.79,  123.98],
    #       [   2.86,  133.55]])
    

    【讨论】:

      【解决方案2】:

      假设A作为输入数组,这里是一个基于零初始化的向量化方法-

      # Get indices at which such diff>15 occur 
      cut_idx = np.where(np.diff(A[:,1]) > 15)[0]
      
      # Initiaize output array
      out = np.zeros((A.shape[0]+len(cut_idx),2),dtype=A.dtype)
      
      # Get row indices in the output array at which rows from A are to be inserted.
      # In other words, avoid rows to be kept as zeros. Finally, insert rows from A.
      idx = ~np.in1d(np.arange(out.shape[0]),cut_idx + np.arange(1,len(cut_idx)+1))
      out[idx] = A
      

      样本输入、输出-

      In [50]: A  # Different from the one posted in question to show variety
      Out[50]: 
      array([[   0.  ,    0.  ],
             [   1.85,    0.6 ],
             [   2.73,   19.13],
             [   2.2 ,   76.33],
             [   2.49,   85.85],
             [   2.55,  104.9 ],
             [   2.65,  114.47],
             [   1.79,  163.98],
             [   2.86,  169.55]])
      
      In [51]: out
      Out[51]: 
      array([[   0.  ,    0.  ],
             [   1.85,    0.6 ],
             [   0.  ,    0.  ],
             [   2.73,   19.13],
             [   0.  ,    0.  ],
             [   2.2 ,   76.33],
             [   2.49,   85.85],
             [   0.  ,    0.  ],
             [   2.55,  104.9 ],
             [   2.65,  114.47],
             [   0.  ,    0.  ],
             [   1.79,  163.98],
             [   2.86,  169.55]])
      

      【讨论】:

      • 哼,这不是想要的输出。
      • @ColonelBeauvel 好吧,我更改了输入数组以在其中显示更多种类。
      • 好吧,我们不能要求 OP 生成示例和所需的输出,然后就更改它:)。 (我以前做过同样的事情)。为优雅的解决方案投票,尽管我仍在努力。
      • @roadrunner66 是的,OP 有时会产生过于简单的案例,我倾向于为我的示例运行修改这些案例,以确保可以处理更多不同的案例。我认为这样更安全,希望提问者在 SO 上发布下一个问题时能从中学到一些东西:)
      • @Maria 但是问题中发布的示例输入数组没有用逗号分隔的元素,因此我们不能将其复制粘贴到我们的 Python 环境中。相反,您可以使用以下命令打印数组:print repr(A),其中A 是输入数组,它将用逗号打印出来,您可以复制 n 粘贴以备将来的问题。祝他们在 Stackoverflow 上好运:)
      【解决方案3】:
      a=[[0.00, 0.00],
       [1.85, 9.60],
       [2.73, 19.13],
       [0.30, 28.70],
       [2.64, 38.25],
       [2.29, 47.77],
       [2.01, 57.28],
       [2.61, 66.82],
       [2.20, 76.33],
       [2.49, 85.85],
       [2.55, 104.90],
       [2.65, 114.47],
       [1.79, 123.98],
       [2.86, 133.55]]
      
      i=0
      while i <len(a)-1:
          if (a[i+1][1]-a[i][1])>15:
              a.insert(i+1,[0,0])
              i=i+1
          i=i+1    
      
      for line in a :
          print line
      

      输出:

      [0.0, 0.0]
      [1.85, 9.6]
      [2.73, 19.13]
      [0.3, 28.7]
      [2.64, 38.25]
      [2.29, 47.77]
      [2.01, 57.28]
      [2.61, 66.82]
      [2.2, 76.33]
      [2.49, 85.85]
      [0, 0]
      [2.55, 104.9]
      [2.65, 114.47]
      [1.79, 123.98]
      [2.86, 133.55]
      

      【讨论】:

      • 他确实说这是一个数组(并且它显示时不带逗号),因此您的列表操作将不起作用(没有插入方法)。但是对于中等大小的列表,这可能比“纯”numpy 操作更快。并且更清晰。
      • Ty,好点子。他将不得不返回转换为列表,我猜这在嵌套时很重要。
      【解决方案4】:

      这是正确的算法:

      arr = [ ... ]
      result = []
      result.append(arr[0])
      for i in range(1, len(arr)):
          if arr[i][1] - arr[i-1][1] > 15:
              result.append([0.0,0.0])
          result.append(arr[i])
      
      print(result)
      

      【讨论】:

      • 嗯,好像没有加0。 math.abs 也给了我一个错误,所以我用 abs 替换它。输出为 [array([2.73, 19.13]), array([0.30, 28.70]), array([2.64, 38.25]), array([2.29, 47.77]), array([2.01, 57.28]), array ([2.61, 66.82]), 数组([2.20, 76.33]), 数组([2.49, 85.85]), 数组([2.55, 104.90]), 数组([2.65, 114.47]), 数组([1.79, 123.98 ]) ...
      • 我想我给你的算法完全错误。我现在将编辑它们。
      【解决方案5】:

      一种可以处理多个填充槽的单衬管。在这里,我在 OP 示例中对其进行了测试,修改了一个值。

      In [70]: np.insert(a, np.where(np.diff(a[:,1])>15)[0]+2,0, axis=0)
      
      
      In [71]: Out[70]: 
      array([[   0.  ,    0.  ],
             [   1.85,    9.6 ],
             [   2.73,   19.13],
             [   0.3 ,   28.7 ],
             [   2.64,   38.25],
             [   2.29,  140.  ],   # modified
             [   0.  ,    0.  ],
             [   2.01,   57.28],
             [   2.61,   66.82],
             [   2.2 ,   76.33],
             [   2.49,   85.85],
             [   2.55,  104.9 ],
             [   0.  ,    0.  ],
             [   2.65,  114.47],
             [   1.79,  123.98],
             [   2.86,  133.55]])
      

      使用where 代替argmaxColonel's 答案)可以处理多个插槽。 +2 是必需的,因为 diff 是短的,我们在后面插入。 ediff1d 有更多处理端点的选项。

      np.insert 有多种填充策略。在这种情况下,它可能正在执行类似于 Divakar's 答案的操作 - 创建一个 out,并将值复制到正确的插槽。

      另一个答案使用np.abs()。这可能是需要的,但在我的示例中,这将在 140 回落到 57 之后添加另一个 0 行。

      【讨论】:

        【解决方案6】:

        如果numpy 没有一些本地方法来做这种事情,我会感到惊讶,但我认为这也可以:

        i = 1
        while i < len(lst):
            if abs(lst[i][1] - lst[i-1][1]) > 15:
                lst[i] = [0.0, 0.0]
                # uncomment to change only the second column
                # lst[i][1] = 0.0
                i += 1
            i += 1
        

        输出:

        >>> lst
        array([[   0.  ,    0.  ],
               [   1.85,    9.6 ],
               [   2.73,   19.13],
               [   0.3 ,   28.7 ],
               [   2.64,   38.25],
               [   2.29,   47.77],
               [   2.01,   57.28],
               [   2.61,   66.82],
               [   2.2 ,   76.33],
               [   2.49,   85.85],
               [   2.55,  104.9 ],
               [   2.65,  114.47],
               [   1.79,  123.98],
               [   2.86,  133.55]])
        >>> 
        >>> i = 1
        >>> while i < len(lst):
        ...     if abs(lst[i][1] - lst[i-1][1]) > 15:
        ...         lst[i] = [0.0, 0.0]
        ...         i += 1
        ...     i += 1
        ... 
        >>> lst
        array([[   0.  ,    0.  ],
               [   1.85,    9.6 ],
               [   2.73,   19.13],
               [   0.3 ,   28.7 ],
               [   2.64,   38.25],
               [   2.29,   47.77],
               [   2.01,   57.28],
               [   2.61,   66.82],
               [   2.2 ,   76.33],
               [   2.49,   85.85],
               [   0.  ,    0.  ],
               [   2.65,  114.47],
               [   1.79,  123.98],
               [   2.86,  133.55]])
        >>> 
        

        【讨论】:

          猜你喜欢
          • 2017-04-11
          • 1970-01-01
          • 1970-01-01
          • 2013-10-29
          • 1970-01-01
          • 2023-03-07
          • 2021-12-28
          • 1970-01-01
          • 2020-07-07
          相关资源
          最近更新 更多