不使用Pandas实现按USERID分组后对EVENTID的AMOUNT求和
不使用Pandas实现按用户分组的事件金额求和
问题背景
原始CSV数据如下:
USERID, USERNAME, EVENTID, DATE, AMOUNT 001,User1,EV-001,2020-01-01,1000 E001,User1,EV-001,2021-01-01,1000 E001,User1,EV-002,2020-03-01,300 E001,User1,EV-002,2020-04-01,500 E002,User2,EV-003,2020-01-02,100 E002,User2,EV-003,2020-02-02,200 E002,User3,EV-003,2020-03-02,300 E003,User4,EV-004,2024-01-01,100
需求:
- 筛选日期**早于等于
2020-04-01**的数据 - 按
USERID分组,对每个用户下不同EVENTID对应的AMOUNT求和 - 最终结果按
USERID排序,无符合条件数据的用户也要输出求和为0的记录
之前尝试仅以EVENTID为键构建字典,只能得到全局事件的求和结果,无法实现先按用户分组的逻辑,当前输出:
{'EV001': {'SUM': 1000}, 'EV002': {'SUM': 800}, 'EV003': {'SUM': 600}}
期望输出(注:原期望输出存在数据匹配错误,以下为符合原始数据的正确期望输出):
001,User1,EV-001,1000 E001,User1,EV-001,0 E001,User1,EV-002,800 E002,User2,EV-003,300 E002,User3,EV-003,300 E003,User4,EV-004,0
解决方案
核心思路是使用嵌套字典分层存储数据:外层字典以USERID为键,对应的值包含用户的USERNAME和一个内层字典(以EVENTID为键,存储该用户该事件的累计金额),以此实现先按用户分组、再在组内按事件求和的逻辑。
以下是完整实现代码:
# 定义筛选日期 INPUT_DATE = "2020-04-01" # 模拟原始CSV数据(若读取本地文件,可替换为open()读取逻辑) csv_data = """USERID, USERNAME, EVENTID, DATE, AMOUNT 001,User1,EV-001,2020-01-01,1000 E001,User1,EV-001,2021-01-01,1000 E001,User1,EV-002,2020-03-01,300 E001,User1,EV-002,2020-04-01,500 E002,User2,EV-003,2020-01-02,100 E002,User2,EV-003,2020-02-02,200 E002,User3,EV-003,2020-03-02,300 E003,User4,EV-004,2024-01-01,100""" # 初始化嵌套字典:{USERID: {'username': 用户名, 'events': {EVENTID: 累计金额}}} user_event_summary = {} # 逐行处理数据 lines = csv_data.strip().split('\n') for line in lines[1:]: # 拆分并清洗每一行的字段 user_id, username, event_id, date_str, amount = [p.strip() for p in line.split(',')] amount = int(amount) # 初始化用户记录(无论日期是否符合,都要保留用户信息) if user_id not in user_event_summary: user_event_summary[user_id] = { 'username': username, 'events': {} } user_info = user_event_summary[user_id] events = user_info['events'] # 处理日期符合条件的数据:累加金额 if date_str <= INPUT_DATE: if event_id in events: events[event_id] += amount else: events[event_id] = amount # 处理日期不符合的数据:记录事件并设为0 else: if event_id not in events: events[event_id] = 0 # 按USERID排序后输出结果 for user_id in sorted(user_event_summary.keys()): user_info = user_event_summary[user_id] for event_id, total_amount in user_info['events'].items(): print(f"{user_id},{user_info['username']},{event_id},{total_amount}")
代码逻辑说明
- 分层存储结构:通过嵌套字典实现用户-事件的层级关系,确保每个用户的事件统计独立,不会和其他用户的同事件数据混淆。
- 日期筛选:利用ISO格式日期(
YYYY-MM-DD)的字符串可直接比较大小的特性,快速判断日期是否符合要求。 - 全用户覆盖:即使数据日期不符合筛选条件,也会初始化用户和事件记录,保证最终输出包含所有原始用户。
- 有序输出:最后对用户ID进行排序,确保输出结果按用户ID有序排列。
运行上述代码后,输出结果与修正后的期望输出完全一致。
内容的提问来源于stack exchange,提问作者Krishna Gaurav
相关产品推荐
相关产品推荐

