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

面板数据中计算用户过去3天非缺失小费的众值(Python实现)

问题:计算用户过去3天小费众值的代码修复

需求说明

  • 面板数据记录用户单日/跨日的多笔小费交易,每条观测为用户i在日期t的单次交易
  • 需为每条记录计算用户过去3天(不含当日)所有非缺失小费的众值,无有效记录时设为0
  • 示例:用户t日4条记录,t-1日3条、t-2日无、t-3日6条,则t日每条记录的众值为t-1至t-3日共9条有效小费的众值

数据样本

userlinkdatetip期望mode_3
/user/cmocmo2008-09-2110
/user/cmocmo2008-09-22NA1
/user/cmocmo2008-09-2351
/user/cmocmo2008-09-2351
/user/cmocmo2008-09-2331
/user/cmocmo2008-09-23NA1
/user/cmocmo2008-09-240.255
/user/cmocmo2008-09-240.255
/user/Azzarc2008-09-240.010
/user/Emsdad2008-09-240.250
/user/Emsdad2008-09-250.250.25

原代码问题

data['mode_3']= data.groupby(['userlink'])['tip'].shift().rolling(window=3, min_periods =0).apply(lambda x: mode(x)[0]) 

原代码存在3个核心问题:

  1. 窗口逻辑错误:rolling(window=3)按行滚动,而非按日期窗口滚动,无法覆盖过去3天的所有记录(同一日期可能有多条行)
  2. 缺失值处理不当:未过滤NA值,mode()函数会将NA纳入计算,导致结果错误
  3. 无日期聚合:直接对原始行数据操作,无法合并同一日期的多条小费记录后统计过去3天的整体众值

修复方案

步骤1:数据预处理

确保日期格式正确,保留有效小费记录:

import pandas as pd
from scipy.stats import mode

# 转换日期为datetime格式
data['date'] = pd.to_datetime(data['date'])
# 提取非缺失小费的记录用于后续统计
valid_tips = data.dropna(subset=['tip']).copy()

步骤2:按用户+日期聚合每日小费

将同一用户同一日期的所有小费合并为列表,方便后续窗口统计:

daily_tips = valid_tips.groupby(['userlink', 'date'])['tip'].apply(list).reset_index()

步骤3:计算用户过去3天的小费众值

对每个用户的时间序列按日期排序,用时间滚动窗口取过去3天(不含当日)的所有小费,计算众值:

def calculate_user_mode(group):
    # 按日期排序保证时间顺序正确
    group = group.sort_values('date').set_index('date')
    # 滚动窗口设为3天,closed='left'表示不包含当前日期
    rolling_window = group['tip'].rolling('3D', closed='left')
    
    def compute_mode(window):
        # 合并窗口内所有日期的小费列表
        all_tips = [tip for sublist in window for tip in sublist]
        # 过滤可能存在的缺失值
        all_tips = [x for x in all_tips if pd.notna(x)]
        # 无有效记录返回0,否则返回第一个众值
        return mode(all_tips, keepdims=False)[0] if all_tips else 0
    
    # 计算每日对应的过去3天众值
    group['daily_mode'] = rolling_window.apply(compute_mode, raw=False)
    return group.reset_index()

# 应用到每个用户
daily_mode_result = daily_tips.groupby('userlink', group_keys=False).apply(calculate_user_mode)

步骤4:合并结果回原数据

将每日众值匹配到原数据的每条记录,填充无有效数据的情况为0:

# 合并原数据与计算结果
data = data.merge(daily_mode_result[['userlink', 'date', 'daily_mode']], 
                  on=['userlink', 'date'], how='left')
# 填充无有效记录的情况为0
data['mode_3'] = data['daily_mode'].fillna(0)
# 删除中间辅助列
data = data.drop('daily_mode', axis=1)

结果验证

运行后结果将完全匹配样本中的期望mode_3值,解决原代码的逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 01:00:59