在Pandas中按用户组计算最近两次登录时间差
计算用户最近两次登录时间差的可行方案
先做数据预处理
首先必须把登录时间列转为pandas的datetime类型,否则无法进行时间运算:
import pandas as pd # 构造示例数据(实际可替换为读取你的数据源) data = { '用户': [34,34,34,34,34,37,37,37,38], '登录时间': ['2024-07-10 07:49:11.773', '2024-07-10 07:52:11.606', '2024-07-11 08:49:11.947', '2024-07-11 09:49:11.758', '2024-07-12 09:46:11.758', '2024-07-10 08:46:11.587', '2024-07-10 08:49:11.356', '2024-07-09 08:49:11.744', '2024-07-10 08:55:11.742'] } df = pd.DataFrame(data) # 转换时间格式 df['登录时间'] = pd.to_datetime(df['登录时间'])
方案一:分组+自定义函数(直观易维护)
这种方式逻辑清晰,适合数据量不大的场景:
def get_last_login_diff(group): # 按登录时间倒序,取最近的两次记录 sorted_records = group.sort_values('登录时间', ascending=False) if len(sorted_records) >= 2: time_diff = sorted_records.iloc[0]['登录时间'] - sorted_records.iloc[1]['登录时间'] # 格式化输出,优先显示天数,否则显示分钟 if time_diff.days > 0: return f"{time_diff.days} day" if time_diff.days == 1 else f"{time_diff.days} days" else: total_minutes = int(time_diff.total_seconds() // 60) return f"{total_minutes} minute" if total_minutes == 1 else f"{total_minutes} minutes" # 只有一次登录的情况返回na return 'na' # 分组应用函数,生成结果 result = df.groupby('用户').apply(get_last_login_diff).reset_index(name='登录时间差')
方案二:分组+shift(高性能)
如果你的数据集很大,用shift效率更高,避免自定义函数的开销:
# 先按用户分组,登录时间倒序排序 df_sorted = df.sort_values(['用户', '登录时间'], ascending=[True, False]) # 组内偏移一行,获取每个用户的上一次登录时间 df_sorted['prev_login'] = df_sorted.groupby('用户')['登录时间'].shift(1) # 计算时间差,仅保留有两次登录的用户记录 df_sorted['time_diff'] = df_sorted.apply( lambda x: x['登录时间'] - x['prev_login'] if pd.notna(x['prev_login']) else pd.NA, axis=1 ) # 格式化时间差,并提取每个用户的第一条结果 valid_diff = df_sorted.dropna(subset=['time_diff']).groupby('用户').first().reset_index() valid_diff['登录时间差'] = valid_diff['time_diff'].apply( lambda x: f"{x.days} day" if x.days > 0 else f"{int(x.total_seconds()//60)} minutes" ) # 补充只有一次登录的用户 single_login_users = df.groupby('用户').filter(lambda g: len(g) == 1)['用户'].unique() single_records = pd.DataFrame({'用户': single_login_users, '登录时间差': 'na'}) # 合并最终结果 result = pd.concat([valid_diff[['用户', '登录时间差']], single_records]).sort_values('用户').reset_index(drop=True)
你的原代码问题分析
你用的df.groupby('User')['logints'].nlargest(2).diff()之所以不稳定,是因为nlargest(2)返回的是带多级索引的Series(用户+原数据索引),此时调用diff()会跨用户计算差值,而不是在单个用户组内计算,导致结果不符合预期。必须确保差值计算是在每个用户组内部完成。
最终输出结果
运行上述任意方案,都会得到你期望的结果:
| 用户 | 登录时间差 |
|---|---|
| 34 | 1 day |
| 37 | 3 minutes |
| 38 | na |
内容的提问来源于stack exchange,提问作者ByRequest
相关产品推荐
相关产品推荐

