【问题标题】:Pandas groupby result into multiple columnsPandas groupby 结果分为多列
【发布时间】:2016-01-26 21:10:58
【问题描述】:

我有一个数据框,我希望在其中进行分组,然后将组内的值划分为多个列。

例如:假设我有以下数据框:

>>> import pandas as pd
>>> import numpy as np
>>> df=pd.DataFrame()
>>> df['Group']=['A','C','B','A','C','C']
>>> df['ID']=[1,2,3,4,5,6]
>>> df['Value']=np.random.randint(1,100,6)
>>> df
  Group  ID  Value
0     A   1     66
1     C   2      2
2     B   3     98
3     A   4     90
4     C   5     85
5     C   6     38
>>> 

我想通过“Group”字段进行分组,得到“Value”字段的总和,并获得新的字段,每个字段都包含该组的 ID 值。

目前我可以按以下方式执行此操作,但我正在寻找一种更简洁的方法:

首先,我创建一个数据框,其中包含每个组中的 ID 列表。

>>> g=df.groupby('Group')
>>> result=g.agg({'Value':np.sum, 'ID':lambda x:x.tolist()})
>>> result
              ID  Value
Group                  
A         [1, 4]     98
B            [3]     76
C      [2, 5, 6]    204
>>> 

然后我使用 pd.Series 将它们拆分为列,重命名它们,然后将其加入。

>>> id_df=result.ID.apply(lambda x:pd.Series(x))
>>> id_cols=['ID'+str(x) for x in range(1,len(id_df.columns)+1)]
>>> id_df.columns=id_cols
>>> 
>>> result.join(id_df)[id_cols+['Value']]
       ID1  ID2  ID3  Value
Group                      
A        1    4  NaN     98
B        3  NaN  NaN     76
C        2    5    6    204
>>> 

有没有一种方法可以做到这一点而无需首先创建值列表?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    你可以使用

    id_df = grouped['ID'].apply(lambda x: pd.Series(x.values)).unstack()
    

    在没有中间 result DataFrame 的情况下创建 id_df


    import pandas as pd
    import numpy as np
    np.random.seed(2016)
    
    df = pd.DataFrame({'Group': ['A', 'C', 'B', 'A', 'C', 'C'],
                       'ID': [1, 2, 3, 4, 5, 6],
                       'Value': np.random.randint(1, 100, 6)})
    
    grouped = df.groupby('Group')
    values = grouped['Value'].agg('sum')
    id_df = grouped['ID'].apply(lambda x: pd.Series(x.values)).unstack()
    id_df = id_df.rename(columns={i: 'ID{}'.format(i + 1) for i in range(id_df.shape[1])})
    result = pd.concat([id_df, values], axis=1)
    print(result)
    

    产量

           ID1  ID2  ID3  Value
    Group                      
    A        1    4  NaN     77
    B        3  NaN  NaN     84
    C        2    5    6     86
    

    【讨论】:

      【解决方案2】:

      使用 get_dummies 和 MultiLabelBinarizer (scikit-learn):

      import pandas as pd
      import numpy as np
      from sklearn import preprocessing
      df = pd.DataFrame()
      df['Group']=['A','C','B','A','C','C']
      df['ID']=[1,2,3,4,5,6]
      df['Value']=np.random.randint(1,100,6)
      
      mlb = preprocessing.MultiLabelBinarizer(classes=classes).fit([])
      
      df2 = pd.get_dummies(df, '', '', columns=['ID']).groupby(by='Group').sum()
      df3 = pd.DataFrame(mlb.inverse_transform(df2[df['ID'].unique()].values), index=df2.index)
      df3.columns = ['ID' + str(x + 1) for x in range(df3.shape[0])]
      pd.concat([df3, df2['Value']], axis=1)
      
      
             ID1  ID2  ID3  Value
      Group                      
      A        1    4  NaN     63
      B        3  NaN  NaN     59
      C        2    5    6    230
      

      【讨论】:

        【解决方案3】:

        执行此操作的另一种方法是首先在您的数据上添加一个“帮助”列,然后使用“帮助”列旋转您的数据框,在“ID_Count”下面的情况下:

        使用@unutbu 设置:

        import pandas as pd
        import numpy as np
        np.random.seed(2016)
        
        df = pd.DataFrame({'Group': ['A', 'C', 'B', 'A', 'C', 'C'],
                           'ID': [1, 2, 3, 4, 5, 6],
                           'Value': np.random.randint(1, 100, 6)})
        #Create group
        grp = df.groupby('Group')
        
        #Create helper column 
        df['ID_Count'] = grp['ID'].cumcount() + 1
        
        #Pivot dataframe using helper column and add 'Value' column to pivoted output.
        df_out = df.pivot('Group','ID_Count','ID').add_prefix('ID').assign(Value = grp['Value'].sum())
        

        输出:

        ID_Count  ID1  ID2  ID3  Value
        Group                         
        A         1.0  4.0  NaN     77
        B         3.0  NaN  NaN     84
        C         2.0  5.0  6.0     86
        

        【讨论】:

          猜你喜欢
          • 2013-07-14
          • 2013-03-06
          • 2018-02-23
          • 2020-09-10
          • 1970-01-01
          • 2021-05-24
          • 2017-01-28
          • 1970-01-01
          相关资源
          最近更新 更多