You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行groupby操作后,如何从DataFrame中获取其他列?

解决Pandas Groupby后丢失关键列的问题

核心问题分析

你原来的代码存在两个关键问题:

  • 用x.day分组会把不同月份的同一天(比如1月1日和2月1日)错误归为一组,逻辑不严谨;
  • grouping.apply(...)返回的是单个布尔值,无法携带recipient_id和完整日期这类字段,自然会丢失信息。

改进方案(直接保留所需字段)

通过agg()方法直接提取分组后的关键信息,既能避免分组逻辑错误,又能完整保留需要的列:

import pandas as pd

# 转换日期格式为datetime类型
caller_history['date_called'] = pd.to_datetime(caller_history['date_called'], format='%Y-%m-%d %H:%M:%S')

# 按「呼叫者ID+完整自然日」分组,提取每组的首次/末次通话信息
grouped_data = caller_history.groupby(
    ['caller_id', caller_history['date_called'].dt.date], 
    as_index=False
).agg(
    recipient_id=('recipient_id', 'first'),  # 首次和末次相同,取任意一个即可
    first_call_time=('date_called', 'first'),
    last_call_time=('date_called', 'last')
)

# 筛选首次与末次通话对象一致的记录
final_result = grouped_data[
    grouped_data['recipient_id'] == grouped_data.groupby(['caller_id', 'date_called'])['recipient_id'].transform('last')
]

# 整理成要求的输出格式
final_output = final_result[['caller_id', 'recipient_id', 'date_called']]

print(final_output)

关键细节说明

  1. 分组逻辑修正:用date_called.dt.date替代x.day,确保同一个自然日的通话才会被分到一组,避免跨月日期混淆;
  2. 保留字段技巧:使用agg()方法直接指定要提取的字段和规则,相比apply()返回单个值,能完整保留分组后的关键信息;
  3. 筛选逻辑简化:因为首次和末次recipient_id相同,所以直接用first提取的值和last提取的值对比即可,完全匹配需求。

另一种思路(对齐你原有的排序逻辑)

如果你更倾向于先排序再处理,可以用标记首次/末次通话的方式实现:

import pandas as pd

caller_history['date_called'] = pd.to_datetime(caller_history['date_called'], format='%Y-%m-%d %H:%M:%S')
# 按呼叫者ID和通话时间排序
caller_history = caller_history.sort_values(by=['caller_id', 'date_called'])

# 标记每个呼叫者每天的首次和末次通话
caller_history['is_first'] = caller_history.groupby(['caller_id', caller_history['date_called'].dt.date]).cumcount() == 0
caller_history['is_last'] = caller_history.groupby(['caller_id', caller_history['date_called'].dt.date]).cumcount(ascending=False) == 0

# 提取首次和末次通话记录,合并后筛选匹配项
first_calls = caller_history[caller_history['is_first']][['caller_id', 'recipient_id', 'date_called']]
last_calls = caller_history[caller_history['is_last']][['caller_id', 'recipient_id', 'date_called']]

merged = pd.merge(first_calls, last_calls, on=['caller_id', 'date_called'], suffixes=('_first', '_last'))
final_output = merged[merged['recipient_id_first'] == merged['recipient_id_last']][['caller_id', 'recipient_id_first', 'date_called']]
final_output.rename(columns={'recipient_id_first': 'recipient_id'}, inplace=True)

print(final_output)

内容的提问来源于stack exchange,提问作者Jgl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 08:04:55