在groupby上设置应用结果的列名

MrT*_*MrT 15 python pandas

这是一个相当微不足道的问题,但它触发了我的强迫症,而我在过去的半小时内未能找到合适的解决方案.

对于背景,我希望为DataFrame中的每个组计算一个值(我们称之为F),该值来自现有DataFrame中不同的聚合度量列.

这是我正在尝试做的一个玩具示例:

import pandas as pd
import numpy as np

df = pd.DataFrame({'A': ['X', 'Y', 'X', 'Y', 'Y', 'Y', 'Y', 'X', 'Y', 'X'],
                'B': ['N', 'N', 'N', 'M', 'N', 'M', 'M', 'N', 'M', 'N'],
                'C': [69, 83, 28, 25, 11, 31, 14, 37, 14,  0],
                'D': [ 0.3,  0.1,  0.1,  0.8,  0.8,  0. ,  0.8,  0.8,  0.1,  0.8],
                'E': [11, 11, 12, 11, 11, 12, 12, 11, 12, 12]
                })

df_grp = df.groupby(['A','B'])
df_grp.apply(lambda x: x['C'].sum() * x['D'].mean() / x['E'].max())
Run Code Online (Sandbox Code Playgroud)

我想做的是为apply(或lambda)的结果指定一个名称.反正有没有移动lambda到命名函数或在运行最后一行后重命名列?

Ale*_*der 29

让lambda函数返回一个新系列:

df_grp.apply(lambda x: pd.Series({'new_name':
                    x['C'].sum() * x['D'].mean() / x['E'].max()}))

     new_name
A B          
X N  5.583333
Y M  2.975000
  N  3.845455
Run Code Online (Sandbox Code Playgroud)

  • 这种事情让我想念 R。但是,+1,谢谢。 (5认同)
  • 效率不高。前任:; 如果每次迭代都使用带有名称的 pd.Series,则计算某些 groupby.apply 从 1'32'' 到 2'32'' (2认同)

Zer*_*ero 16

您可以将您转换series为dataframe使用reset_index()并提供name='yout_col_name'- 与Series值对应的列的名称

(df_grp.apply(lambda x: x['C'].sum() * x['D'].mean() / x['E'].max())
      .reset_index(name='your_col_name'))

   A  B  your_col_name
0  X  N   5.583333
1  Y  M   2.975000
2  Y  N   3.845455
Run Code Online (Sandbox Code Playgroud)

  • 显然“name”参数已被删除。也许现在是“名称” - 鉴于最近的“多索引”支持 (3认同)

Sud*_*nha 5

接受的答案似乎适用于当前版本的 Pandas,但不是根据文档name的参数之一。有一个论点,但在我看来,它有不同的目的。reset_indexnames

由于 apply 的输出是一个系列,我们可以简单地使用pandas.Series.rename()来获得结果。

df = pd.DataFrame({'A': ['X', 'Y', 'X', 'Y', 'Y', 'Y', 'Y', 'X', 'Y', 'X'],
                'B': ['N', 'N', 'N', 'M', 'N', 'M', 'M', 'N', 'M', 'N'],
                'C': [69, 83, 28, 25, 11, 31, 14, 37, 14,  0],
                'D': [ 0.3,  0.1,  0.1,  0.8,  0.8,  0. ,  0.8,  0.8,  0.1,  0.8],
                'E': [11, 11, 12, 11, 11, 12, 12, 11, 12, 12]
                })

df_grp = df.groupby(['A','B'])
df_grp.apply(lambda x: x['C'].sum() * x['D'].mean() / x['E'].max()).rename("your_col_name")
Run Code Online (Sandbox Code Playgroud)