【问题标题】:Append array in for loop在for循环中追加数组
【发布时间】:2019-04-07 17:06:26
【问题描述】:

我有一个包含 1000 行和 1000 列的数据框。我正在尝试使用 for 循环从该数据帧生成一个 numpy 数组,我使用 for 循环在每个循环中随机选择 5 列。我需要附加或连接每个周期生成的每个数组(1000 行和 5 列)。但是,它发现如果不先指定维度,就无法创建 numpy 数组。

我已经尝试了以下代码:

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))

l =  np.array([])

for i in range(0,100):
 rand_cols = np.random.permutation(df.columns)[0:5]
 df2 = df[rand_cols].copy()
 l = np.append(l, df2, axis=0)

但是,我收到以下错误:

ValueError: all the input arrays must have same number of 
dimensions

这段代码总结了我正在做的事情,但是,根据这个例子,我需要的结果是一个 1000 行和 500 列的数组,它是由我用每个 for 循环生成的每个数组的串联生成的循环。

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    列表追加总是优于np.append。它更快,更容易正确使用。

    但让我们更详细地看一下您的代码:

    In [128]: df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))    
    In [129]: l = np.array([])                                                      
    In [130]: rand_cols = np.random.permutation(df.columns)[0:5]                    
    In [131]: rand_cols                                                             
    Out[131]: array([190, 106, 618, 557, 514])
    In [132]: df2 = df[rand_cols].copy()                                            
    In [133]: df2.shape                                                             
    Out[133]: (1000, 5)
    In [134]: l1 = np.append(l, df2, axis=0)                                        
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-134-64d82acc3963> in <module>
    ----> 1 l1 = np.append(l, df2, axis=0)
    
    /usr/local/lib/python3.6/dist-packages/numpy/lib/function_base.py in append(arr, values, axis)
       4692         values = ravel(values)
       4693         axis = arr.ndim-1
    -> 4694     return concatenate((arr, values), axis=axis)
       4695 
       4696 
    
    ValueError: all the input arrays must have same number of dimensions
    

    由于您指定了轴,所有np.append 正在做的是:

    np.concatenate([l, df2], axis=0)
    

    l 是 (0,) 形状,df2 是 (1000,5)。 1d 和 2d,因此抱怨尺寸。

    从 2d l 数组开始工作:

    In [144]: l = np.zeros((0,5))                                                   
    In [145]: np.concatenate([l, df2], axis=0).shape                                
    Out[145]: (1000, 5)
    In [146]: np.concatenate([df2, df2], axis=0).shape                              
    Out[146]: (2000, 5)
    

    我认为np.append 应该被弃用。我们看到太多的 SO 错误。如您的案例所示,很难创建正确的初始数组。 np.array([]) 仅在构建一维数组时有效。加上重复连接很慢,每次都会创建一个全新的数组。

    【讨论】:

      【解决方案2】:

      IIUC

      l=[]
      
      for i in range(0,100):
       rand_cols = np.random.permutation(df.columns)[0:5]
       df2 = df[rand_cols].copy()
       l.append(df2.values)
      
      
      a=np.concatenate(l,1)
      a.shape
      (1000, 500)
      

      【讨论】:

        【解决方案3】:

        建议的解决方案

        您收到此错误的原因是您尝试将形状为 (1000, 5) 的矩阵 df2 附加到形状为 ( 的矩阵 l 0,)(只有一维)。问题是,对于 numpy,两个连接矩阵必须匹配维度,并且除了要附加的维度之外的所有维度必须对齐,即您应该使用 (0, 5)的形状初始化 l >.

        这是代码的工作版本:

        import numpy as np
        import pandas as pd
        
        
        df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))
        
        l =  np.empty(shape=(0, 5))
        
        for _ in range(0,100):
            rand_cols = np.random.permutation(df.columns)[0:5]
            df2 = df[rand_cols]
            l = np.append(l, df2, axis=0)
        

        建议改进

        现在,最好的做法是避免在循环中附加矩阵,因为这在计算上效率不高(每次迭代都必须创建一个新的 numpy 数组,这需要时间)。您最好将循环迭代的结果附加到标准 python 列表中,然后等到循环执行结束时将所有结果堆叠在一起。

        代码如下:

        import numpy as np
        import pandas as pd
        
        
        df = pd.DataFrame(np.random.choice([0.0, 0.05], size=(1000,1000)))
        
        df_list = []
        
        for _ in range(0,100):
            rand_cols = np.random.permutation(df.columns)[0:5]
            df2 = df[rand_cols]
            df_list += [df2]
        l = np.vstack(df_list)
        

        这里我使用numpy.vstack 沿行轴连接。其他具有适当参数的 numpy 函数会给您相同的结果。请注意,无需将 pandas 数据帧转换为 numpy 数组。

        在我的计算机上,这个小小的改进将计算时间从 164 毫秒减少到 107 毫秒(从每个版本的快速执行中选取的值)。当然这在这里并不重要,但我认为这很高兴:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-03
          • 2018-10-08
          • 2016-08-22
          • 2021-08-10
          • 1970-01-01
          • 2018-10-04
          • 1970-01-01
          • 2022-01-25
          相关资源
          最近更新 更多