【问题标题】:Pythonic Way of Inserting Columns at Arbitrary Positions在任意位置插入列的 Pythonic 方式
【发布时间】:2013-12-14 20:30:10
【问题描述】:

我有一个由行列表表示的数据网格:

tableData = [
    [-27.37, 36.61 , 8.90  , -11.20, -36.03, -42.34],
    [16.83 , -33.45, -5.15 , 12.90 , -48.60, -8.70],
    [-19.73, 2.64  , 7.21  , 24.16 , 18.38 , 20.47],
    [-31.05, 15.07 , 42.69 , -32.13, -36.02, 42.31],
    [15.18 , 30.54 , -47.31, 48.38 , 31.60 , -1.98]
]

现在,我想插入包含 None 值的两列,例如在列 2&3 和 4&5 之间,这样我就有了以下内容:

tableDataWithNones = [
    [-27.37, 36.61 , None,  8.90  , -11.20, None, -36.03, -42.34],
    [16.83 , -33.45, None,  -5.15 , 12.90 , None,  -48.60, -8.70],
    [-19.73, 2.64  , None,  7.21  , 24.16 , None,  18.38 , 20.47],
    [-31.05, 15.07 , None,  42.69 , -32.13, None,  -36.02, 42.31],
    [15.18 , 30.54 , None,  -47.31, 48.38 , None,  31.60 , -1.98]
]

我可以像这样使用双 for 循环来做到这一点:

spacerPositions = [2, 4]
for i in tableData:
    for j in reversed(spacerPositions):
        i.insert(j, None)

但这感觉不像是pythonic的方式。

我在想我可以使用 numpy 转置数据,以便列可以变成行,然后我可以使用 insert 将行 Nones 放入,然后将数据转回。但是 insert 不能为索引取多个值,所以我仍然必须使用 for 循环。

有什么想法可以更好地做到这一点吗?

【问题讨论】:

    标签: python numpy matrix data-manipulation


    【解决方案1】:

    使用numpy.insert

    >>> import numpy as np
    >>> arr = np.array(tableData)
    >>> np.insert(arr, (2, 4), None, axis=1)
    array([[-27.37,  36.61,    nan,   8.9 , -11.2 ,    nan, -36.03, -42.34],
           [ 16.83, -33.45,    nan,  -5.15,  12.9 ,    nan, -48.6 ,  -8.7 ],
           [-19.73,   2.64,    nan,   7.21,  24.16,    nan,  18.38,  20.47],
           [-31.05,  15.07,    nan,  42.69, -32.13,    nan, -36.02,  42.31],
           [ 15.18,  30.54,    nan, -47.31,  48.38,    nan,  31.6 ,  -1.98]])
    

    【讨论】:

      【解决方案2】:

      一种非 numpy 的功能性方式:

      from functools import partial
      
          def insertFunc(data, locs):
              out = []
      
              for i,d in enumerate(data):
                  if i in locs:
                      out.append(None)
      
                  out.append(d)
      
              return out
      
      map(partial(insertFunc,locs=spacerPositions),tableData)
      

      对比一下

      for i in spacerPositions: 
          for row in tableData: 
              row.insert(i, None)
      

      使用timeit(...,number=10000),我得到:

      0.144109010696 对于第一个算法 第二种算法0.606826066971

      这是有道理的,因为插入是 O(n),而追加是 O(1)。

      令人惊讶的是,使用 numpy 为接受的解决方案计时:

       timeit.timeit('np.insert(arr,(2,4), None, axis=1)',number=10000,setup='import numpy as np;from __main__ import tableData; arr = np.array(tableData)')
      

      给出 0.44481992721557617

      【讨论】:

      • 请不要使用map 来获得副作用。这更快,并且(对我而言)更具可读性:for i in spacerPositions: for row in tableData: row.insert(i, None)
      • 显示我所知道的!感谢您的洞察力。你的推理是有道理的,因为函数式编程的重点是(尽可能)没有副作用。
      猜你喜欢
      • 2015-05-21
      • 2011-12-12
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 2016-11-03
      相关资源
      最近更新 更多