分组DataFrame聚合时Lambda函数引用多列的技术问题
分组聚合计算免税客人总数的解决方案
问题核心
你遇到的报错本质是:用pd.NamedAgg指定单列时,传入lambda的参数仅为该列的Series,无法同时访问Guest_Code列筛选免税客人。要实现需求,必须让聚合函数能获取分组内的完整数据。
最优方案:自定义聚合函数
直接定义一个接收分组DataFrame的函数,在函数内部完成筛选、判断和计算:
- 编写自定义聚合逻辑
def calc_tax_free_guests(group): # 筛选分组内Guest_Code=2的行 tax_free_subset = group[group['Guest_Code'] == 2] row_count = len(tax_free_subset) if row_count == 0: return 0 elif row_count == 1: return tax_free_subset['Guests'].iloc[0] else: return tax_free_subset['Guests'].sum()
- 执行分组聚合
假设你的数据已提取好月份列(比如booking_month),直接在groupby中调用该函数:
# 示例:包含其他聚合项的完整写法 agg_result = df.groupby(['booking_month', 'Booking_Source']).agg( total_guests=pd.NamedAgg(column='Guests', aggfunc='sum'), avg_guests=pd.NamedAgg(column='Guests', aggfunc='mean'), tax_free_guests=pd.NamedAgg(column='', aggfunc=calc_tax_free_guests) ).reset_index()
补充:提取月份列
如果原始数据只有完整日期列(比如booking_date),先提取月份:
# 生成YYYY-MM格式的字符串月份,或用dt.to_period('M')生成周期对象 df['booking_month'] = df['booking_date'].dt.strftime('%Y-%m')
替代方案:预处理辅助列
若不想用自定义函数,可先添加辅助列标记免税客人,再分组结合计数和求和计算:
# 添加临时列:仅Guest_Code=2时保留Guests值,否则为0 df['tax_free_temp'] = df.apply(lambda r: r['Guests'] if r['Guest_Code'] == 2 else 0, axis=1) # 分组统计免税行数量和临时列总和 temp_result = df.groupby(['booking_month', 'Booking_Source']).agg( tax_free_row_count=pd.NamedAgg(column='Guest_Code', aggfunc=lambda x: (x == 2).sum()), tax_free_sum=pd.NamedAgg(column='tax_free_temp', aggfunc='sum') ).reset_index() # 根据计数生成最终结果 temp_result['tax_free_guests'] = temp_result.apply( lambda r: r['tax_free_sum'] if r['tax_free_row_count'] != 1 else df[(df['booking_month'] == r['booking_month']) & (df['Booking_Source'] == r['Booking_Source']) & (df['Guest_Code'] == 2)]['Guests'].iloc[0], axis=1 ) # 删除临时列 final_result = temp_result.drop(['tax_free_row_count', 'tax_free_sum', 'tax_free_temp'], axis=1)
内容的提问来源于stack exchange,提问作者Mondonauta
相关产品推荐
相关产品推荐

