【问题标题】:Pandas: How do I split multiple lists in columns into multiple rows?Pandas:如何将列中的多个列表拆分为多行?
【发布时间】:2016-04-06 18:01:05
【问题描述】:

我有一个熊猫 DataFrame,如下所示:

     bus_uid   bus_type    type                      obj_uid  \
0     biomass: DEB31    biomass  output       Simple_139804698384200   
0     biomass: DEB31    biomass   other                        duals   
0     biomass: DEB31    biomass   other                       excess   

                                         datetime  \
0   DatetimeIndex(['2015-01-01 00:00:00',  '2015-01-01 01:00:00',  '2015-01-01 02:00:00', ...   
0   DatetimeIndex(['2015-01-01 00:00:00',  '2015-01-01 01:00:00',  '2015-01-01 02:00:00', ...   
0   DatetimeIndex(['2015-01-01 00:00:00',  '2015-01-01 01:00:00',  '2015-01-01 02:00:00', ...   

                                           values  
0   [1.0, 2.0, 3.0, ...  
0   [4.0, 5.0, 6.0, ...  
0   [7.0, 8.0, 9.0, ...

并想将其转换成以下格式:

     bus_uid   bus_type    type                          obj_uid  datetime             values
0     biomass: DEB31    biomass  output   Simple_139804698384200  2015-01-01 00:00:00  1.0
0     biomass: DEB31    biomass  output   Simple_139804698384200  2015-01-01 01:00:00  2.0
0     biomass: DEB31    biomass  output   Simple_139804698384200  2015-01-01 02:00:00  3.0
0     biomass: DEB31    biomass   other                    duals  2015-01-01 00:00:00  4.0
0     biomass: DEB31    biomass   other                    duals  2015-01-01 01:00:00  5.0
0     biomass: DEB31    biomass   other                    duals  2015-01-01 02:00:00  6.0
0     biomass: DEB31    biomass   other                   excess  2015-01-01 00:00:00  7.0
0     biomass: DEB31    biomass   other                   excess  2015-01-01 01:00:00  8.0
0     biomass: DEB31    biomass   other                   excess  2015-01-01 02:00:00  9.0

datetime 和 values 列具有相同的维度。

我已经问过一个类似的问题here,但我无法用两列解决我的问题。

将DataFrame 转换为所需格式的最佳方法是什么?

【问题讨论】:

    标签: python list pandas dataframe


    【解决方案1】:

    您可以遍历行以从单元格中提取 Index 和 Series 信息。当您需要同时提取信息时,我认为 reshaping 方法效果不佳:

    样本数据:

    rows = 3
    df = pd.DataFrame(data={'bus_uid': list(repeat('biomass: DEB31', rows)), 'type': list(repeat('biomass', 3)), 'id': ['id1', 'id2', 'id3'], 'datetime': list(repeat(pd.DatetimeIndex(start=datetime(2016,1,1), periods=3, freq='D'), rows)), 'values': list(repeat([1,2,3], rows))})
    
              bus_uid                                           datetime   id  \
    0  biomass: DEB31  DatetimeIndex(['2016-01-01', '2016-01-02', '20...  id1   
    1  biomass: DEB31  DatetimeIndex(['2016-01-01', '2016-01-02', '20...  id2   
    2  biomass: DEB31  DatetimeIndex(['2016-01-01', '2016-01-02', '20...  id3   
    
          type     values  
    0  biomass  [1, 2, 3]  
    1  biomass  [1, 2, 3]  
    2  biomass  [1, 2, 3]  
    

    在您遍历 DataFrame rows 时构建新的 DataFrame:

    new_df = pd.DataFrame()
    for index, cols in df.iterrows():
        extract_df = pd.DataFrame.from_dict({'datetime': cols.ix['datetime'], 'values': cols.ix['values']})
        extract_df = pd.concat([extract_df, cols.drop(['datetime', 'values']).to_frame().T], axis=1).fillna(method='ffill').fillna(method='bfill')
        new_df = pd.concat([new_df, extract_df], ignore_index=True)
    

    得到:

        datetime  values         bus_uid   id     type
    0 2016-01-01       1  biomass: DEB31  id1  biomass
    1 2016-01-02       2  biomass: DEB31  id1  biomass
    2 2016-01-03       3  biomass: DEB31  id1  biomass
    3 2016-01-01       1  biomass: DEB31  id2  biomass
    4 2016-01-02       2  biomass: DEB31  id2  biomass
    5 2016-01-03       3  biomass: DEB31  id2  biomass
    6 2016-01-01       1  biomass: DEB31  id3  biomass
    7 2016-01-02       2  biomass: DEB31  id3  biomass
    8 2016-01-03       3  biomass: DEB31  id3  biomass
    

    【讨论】:

      【解决方案2】:

      您可以从values 和datetime 列中提取新的Series,然后将它们与concat 的原始数据框df 合并:

      s1 = df['values'].apply(pd.Series, 1).stack()
      s1.index = s1.index.droplevel(-1) # to line up with df's index
      s1.name = 'values' # needs a name to join
      
      s2 = df['datetime'].apply(pd.Series, 1).stack()
      s2.index = s2.index.droplevel(-1) # to line up with df's index
      s2.name = 'datetime' # needs a name to join
      
      #remove duplicity columns
      df = df.drop( ['values', 'datetime'], axis=1)
      
      #concat all together
      df= pd.concat([df,s1,s2], axis=1).reset_index(drop=True)
      
      print df
      
         bus_uid        bus_type            type                 obj_uid values  \
      0        0  biomass: DEB31  biomass output  Simple_139804698384200    1.0   
      1        0  biomass: DEB31  biomass output  Simple_139804698384200    2.0   
      2        0  biomass: DEB31  biomass output  Simple_139804698384200    3.0   
      3        0  biomass: DEB31   biomass other                   duals    4.0   
      4        0  biomass: DEB31   biomass other                   duals    5.0   
      5        0  biomass: DEB31   biomass other                   duals    6.0   
      6        0  biomass: DEB31   biomass other                  excess    7.0   
      7        0  biomass: DEB31   biomass other                  excess    8.0   
      8        0  biomass: DEB31   biomass other                  excess    9.0   
      
                   datetime  
      0 2015-01-01 00:00:00  
      1 2015-01-01 01:00:00  
      2 2015-01-01 02:00:00  
      3 2015-01-01 00:00:00  
      4 2015-01-01 01:00:00  
      5 2015-01-01 02:00:00  
      6 2015-01-01 00:00:00  
      7 2015-01-01 01:00:00  
      8 2015-01-01 02:00:00  
      

      【讨论】:

      • 感谢您的所有回答!我选择了 jezraels 的答案,因为它是我认为最直观的选择。
      • 但是我没有考虑过性能问题。 “datetime”和“values”的维度分别为 192 个条目,重塑已经花费了 8 个多小时。使用我当前的数据框和最大值。 “日期时间”和“值”的 8760 个条目的维度,重塑为长格式将导致数据帧具有超过 70.000.000 个条目。也许首先获取所需的子集然后创建用于统计和绘图的长格式会更聪明。您对此有什么建议吗?
      • 嗯,如果DataFrame 很大,那就很复杂了。您可以尝试将s1 = df['values'].apply(pd.Series, 1).stack() 更改为s1 = pd.DataFrame([x for x in df['values']]).stack() 并与datetime 类似。
      • Stefans 的回答只用了 240 秒的时间,所以我现在改变了我接受的答案。我稍后会做一些性能测试,包括你的建议,然后看看哪一个最适合我。谢谢!
      • 你的建议用了 5 个多小时,所以其他选项似乎要快得多。
      猜你喜欢
      • 2023-01-11
      • 2016-05-31
      • 2020-02-10
      • 2021-01-24
      • 1970-01-01
      • 2018-05-28
      • 2013-06-11
      相关资源
      最近更新 更多