【问题标题】:From ND to 1D arrays从 ND 到 1D 阵列
【发布时间】:2012-11-23 16:56:35
【问题描述】:

假设我有一个数组a

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

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

我想将其转换为一维数组(即列向量):

b = np.reshape(a, (1,np.product(a.shape)))

但这会返回

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

不一样的是:

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

我可以将该数组的第一个元素手动转换为一维数组:

b = np.reshape(a, (1,np.product(a.shape)))[0]

但这需要我知道原始数组有多少维(并在处理更高维时连接 [0])

是否有一种与维度无关的方式从任意 ndarray 中获取列/行向量?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    使用np.ravel(用于一维视图)或np.ndarray.flatten(用于一维副本)或np.ndarray.flat(用于一维迭代器):

    In [12]: a = np.array([[1,2,3], [4,5,6]])
    
    In [13]: b = a.ravel()
    
    In [14]: b
    Out[14]: array([1, 2, 3, 4, 5, 6])
    

    请注意,ravel() 尽可能返回 viewa。所以修改b也会修改a。当一维元素在内存中连续时,ravel() 返回 view,但如果 a 是使用非单位步长对另一个数组进行切片(例如 a = x[::2]),则返回 copy )。

    如果您想要副本而不是视图,请使用

    In [15]: c = a.flatten()
    

    如果您只想要一个迭代器,请使用np.ndarray.flat

    In [20]: d = a.flat
    
    In [21]: d
    Out[21]: <numpy.flatiter object at 0x8ec2068>
    
    In [22]: list(d)
    Out[22]: [1, 2, 3, 4, 5, 6]
    

    【讨论】:

    • 在这个例子中,ravel() 返回一个视图,但这并不总是正确的。在某些情况下,ravel() 会返回一个副本。
    • a.ravel() 的速度似乎是 a.reshape(-1) 的三倍左右。 a.flatten() 要慢得多,因为它需要复制。
    【解决方案2】:

    我想看看答案中提到的函数的基准测试结果,包括unutbu's

    还想指出numpy doc 建议使用arr.reshape(-1) 以防万一视图更可取。 (尽管ravel 在下面的结果中要快一点)


    TL;DRnp.ravel 是性能最高的(数量很少)。

    基准测试

    功能:

    numpy 版本:'1.18.0'

    不同ndarray 大小的执行时间

    +-------------+----------+-----------+-----------+-------------+
    |  function   |   10x10  |  100x100  | 1000x1000 | 10000x10000 |
    +-------------+----------+-----------+-----------+-------------+
    | ravel       | 0.002073 |  0.002123 |  0.002153 |    0.002077 |
    | reshape(-1) | 0.002612 |  0.002635 |  0.002674 |    0.002701 |
    | flatten     | 0.000810 |  0.007467 |  0.587538 |  107.321913 |
    | flat        | 0.000337 |  0.000255 |  0.000227 |    0.000216 |
    +-------------+----------+-----------+-----------+-------------+
    

    结论

    ravelreshape(-1) 的执行时间是一致的,并且与 ndarray 大小无关。 但是,ravel 稍微快一点,但reshape 在调整大小方面提供了灵活性。 (也许这就是为什么numpy doc 建议改用它的原因。或者在某些情况下reshape 返回视图而ravel 不返回)。
    如果您正在处理大尺寸的 ndarray,使用 flatten 可能会导致性能问题。建议不要使用。除非您需要数据副本来做其他事情。

    使用的代码

    import timeit
    setup = '''
    import numpy as np
    nd = np.random.randint(10, size=(10, 10))
    '''
    
    timeit.timeit('nd = np.reshape(nd, -1)', setup=setup, number=1000)
    timeit.timeit('nd = np.ravel(nd)', setup=setup, number=1000)
    timeit.timeit('nd = nd.flatten()', setup=setup, number=1000)
    timeit.timeit('nd.flat', setup=setup, number=1000)
    

    【讨论】:

    • 您提到可能存在reshape 返回视图而ravel 不返回的情况。一种这样的情况是y=x[::2]。因为y 不是连续的,所以 ravel 必须复制,即使它已经是一维数组。您可以使用它来设计 ravel 较慢的情况。
    【解决方案3】:

    对于不同大小的数组列表,使用以下:

    import numpy as np
    
    # ND array list with different size
    a = [[1],[2,3,4,5],[6,7,8]]
    
    # stack them
    b = np.hstack(a)
    
    print(b)
    

    输出:

    [1 2 3 4 5 6 7 8]

    【讨论】:

    【解决方案4】:

    最简单的方法之一是使用flatten(),就像这个例子:

     import numpy as np
    
     batch_y =train_output.iloc[sample, :]
     batch_y = np.array(batch_y).flatten()
    

    我的数组是这样的:

        0
    0   6
    1   6
    2   5
    3   4
    4   3
    .
    .
    .
    

    使用flatten()后:

    array([6, 6, 5, ..., 5, 3, 6])
    

    也是此类错误的解决方法:

    Cannot feed value of shape (100, 1) for Tensor 'input/Y:0', which has shape '(?,)' 
    

    【讨论】:

      【解决方案5】:

      虽然这没有使用 np 数组格式,(懒得修改我的代码)这应该做你想做的事......如果你真的想要一个列向量,你会想要转置向量结果。这完全取决于您打算如何使用它。

      def getVector(data_array,col):
          vector = []
          imax = len(data_array)
          for i in range(imax):
              vector.append(data_array[i][col])
          return ( vector )
      a = ([1,2,3], [4,5,6])
      b = getVector(a,1)
      print(b)
      
      Out>[2,5]
      

      所以如果你需要转置,你可以这样做:

      def transposeArray(data_array):
          # need to test if this is a 1D array 
          # can't do a len(data_array[0]) if it's 1D
          two_d = True
          if isinstance(data_array[0], list):
              dimx = len(data_array[0])
          else:
              dimx = 1
              two_d = False
          dimy = len(data_array)
          # init output transposed array
          data_array_t = [[0 for row in range(dimx)] for col in range(dimy)]
          # fill output transposed array
          for i in range(dimx):
              for j in range(dimy):
                  if two_d:
                      data_array_t[j][i] = data_array[i][j]
                  else:
                      data_array_t[j][i] = data_array[j]
          return data_array_t
      

      【讨论】:

        【解决方案6】:
        In [14]: b = np.reshape(a, (np.product(a.shape),))
        
        In [15]: b
        Out[15]: array([1, 2, 3, 4, 5, 6])
        

        或者,简单地说:

        In [16]: a.flatten()
        Out[16]: array([1, 2, 3, 4, 5, 6])
        

        【讨论】:

        • 第一个例子可以用b = a.reshape(-1)简称。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-03
        • 1970-01-01
        • 2018-10-29
        • 2013-12-14
        • 1970-01-01
        相关资源
        最近更新 更多