【问题标题】:Efficient approach to transform list of numpy array in a list在列表中转换 numpy 数组列表的有效方法
【发布时间】:2020-11-18 08:02:03
【问题描述】:

我有一个列表,列表中有两个形状为 (1,3) 的 ndarray。这个内部列表有 3 个类似的副本。这些内部列表中的每一个都进一步分组在外部列表中,它们对应于一个长度为 3 的外部列表。

想法是将嵌套列表从形状 3(外部)和 2(内部)转换为形状 2(外部)和 3(内部)的形状。

以下代码为草稿

from operator import itemgetter

all_l=[[np.array([[1, 2, 3]]),np.array([[4, 5, 6]])],
       [np.array([[1, 2, 3]]),np.array([[4, 5, 6]])],
       [np.array([[1, 2, 3]]),np.array([[4, 5, 6]])]]


trans_format=[list ( map ( itemgetter ( i),all_l) ) for i in range (0,len(all_l[0]))]

但是,我想知道是否有更有效的方法来实现这一点?在实际实现中,列表的外部和内部 len 如果很大。

【问题讨论】:

    标签: python python-3.x list numpy


    【解决方案1】:

    以下代码将以numpy 数组的形式提供您所需的数据结构:

    new_arr = np.array(my_list).transpose(1,0,2,3)
    

    测试一下:

    from pprint import pprint
    my_list = [[np.arange(3).reshape(1,3), np.arange(3,6).reshape(1,3)],
               [10* np.arange(3).reshape(1,3), 10* np.arange(3,6).reshape(1,3)],
               [100*np.arange(3).reshape(1,3), 100*np.arange(3,6).reshape(1,3)]]
    pprint (my_list)
    new_arr = np.array(my_list).transpose(1,0,2,3)
    print (new_arr.shape)
    print (new_arr.dtype)
    print (new_arr)
    

    输出:

    [[array([[0, 1, 2]]), array([[3, 4, 5]])],
     [array([[ 0, 10, 20]]), array([[30, 40, 50]])],
     [array([[  0, 100, 200]]), array([[300, 400, 500]])]]
    
    (3, 2, 1, 3)
    int32
    [[[[  0   1   2]]
    
      [[  3   4   5]]]
    
    
     [[[  0  10  20]]
    
      [[ 30  40  50]]]
    
    
     [[[  0 100 200]]
    
      [[300 400 500]]]]
    

    转换回numpy 数组的 2x3 列表:

    (无法想象你为什么要这样做!)

    new_list = [list(slice) for slice in new_arr]
    

    测试转换:

    pprint (new_list)
    

    转换的输出:

    [[array([[0, 1, 2]]), array([[ 0, 10, 20]]), array([[  0, 100, 200]])],
     [array([[3, 4, 5]]), array([[30, 40, 50]]), array([[300, 400, 500]])]]
    

    【讨论】:

      【解决方案2】:

      您认为可以获得一些效率是正确的。以下是一些时间比较。

      值得注意的是,这些计时是在原始数据集上运行的,并且在扩大规模时可能会显示出效率变化。 (正在进行中。)

      @fountainhead 的回答:
      每个循环的时间:10.1 µs

      new_arr = np.array(all_l).transpose(1,0,2,3)
      

      原文:
      每个循环的时间:3.44 µs

      trans_format=[list ( map ( itemgetter ( i),all_l) ) for i in range (0,len(all_l[0]))]
      

      @rapchen 的回答:
      每个循环的时间:1.44 µs

      trans_format = [list(row) for row in zip(*all_l)]
      

      这个答案(详细/基本方法):
      每个循环的时间:1.18 µs

      l1 = []
      l2 = []
      for i in l:
          l1.append(i[0])
          l2.append(i[1])
          
      trans_format = [l1, l2]
      

      所有答案的输出:
      (@foundtainhead 的回答输出一个 numpy 数组。)

      [[array([[1, 2, 3]]), array([[1, 2, 3]]), array([[1, 2, 3]])],
       [array([[4, 5, 6]]), array([[4, 5, 6]]), array([[4, 5, 6]])]]
      

      【讨论】:

      • 我认为这些时序测试是使用最少的演示数据进行的。对于真正的大规模数据,这些比较可能会变得非常不同。至少有一个原因——转换开销可能会在较小的范围内扭曲性能。可能值得在更高的放大倍数中检查
      • @fountainhead - 公平点。你的回答肯定是最简洁、最棒的作品。我会看看扩大规模。
      【解决方案3】:

      也许你可以试试 zip 功能:

      trans_format = list(zip(*all_l))
      

      但是外部列表的每个元素都将是一个元组。如果您需要内部列表,您可以简单地添加转换:

      trans_format = [list(row) for row in zip(*all_l)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-10
        • 2019-03-12
        • 1970-01-01
        • 1970-01-01
        • 2023-01-02
        • 2017-03-08
        • 2019-07-15
        • 2015-09-03
        相关资源
        最近更新 更多