按多键分组聚合2n个字典列表,实现values值求和合并
按多键分组并求和字典列表中的values值
原始数据
my_list = [ {'metric': {'account': '1', 'email_domain': 'gmail.com', 'version': 'a'}, 'values': [[1671256800, '100'], [1671260400, '100']]}, {'metric': {'account': '1', 'email_domain': 'gmail.com', 'version': 'a'}, 'values': [[1671256800, '100'], [1671260400, '100']]}, {'metric': {'account': '1', 'email_domain': 'gmail.com', 'version': 'b'}, 'values': [[1671256800, '300'], [1671260400, '300']]}, {'metric': {'account': '1', 'email_domain': 'gmail.com', 'version': 'b'}, 'values': [[1671256800, '300'], [1671260400, '300']]}]
需求说明
需要按account、email_domain和version三个字段分组,对每组内values中同一时间戳对应的数值求和(数值为字符串类型,求和需先转换为数值类型),最终将结果整理回原字典列表格式。
期望输出
my_list = [ {'metric': {'account': '1', 'email_domain': 'gmail.com', 'version': 'a'}, 'values': [[1671256800, '200'], [1671260400, '200']]}, {'metric': {'account': '1', 'email_domain': 'gmail.com', 'version': 'b'}, 'values': [[1671256800, '600'], [1671260400, '600']]}]
尝试过的错误代码
曾尝试用Pandas处理,但语法有误:
d = (pd.DataFrame(my_list)).groupby(['metric']['ebs_account'], ['metric']['version']).values.
解决方案
方法一:纯Python实现(无需第三方库)
利用collections.defaultdict进行分组累加,最后重构结果:
from collections import defaultdict # 初始化分组容器,键为(account, email_domain, version),值为时间戳到累计值的映射 grouped = defaultdict(lambda: defaultdict(int)) for item in my_list: metric = item['metric'] # 生成唯一分组键 group_key = (metric['account'], metric['email_domain'], metric['version']) # 遍历当前项的values,累加对应时间戳的数值 for timestamp, val_str in item['values']: grouped[group_key][timestamp] += int(val_str) # 转换为目标格式的列表 my_list = [] for (account, email_domain, version), ts_total in grouped.items(): # 按时间戳排序,保证顺序与原数据一致 sorted_values = sorted([[ts, str(total)] for ts, total in ts_total.items()], key=lambda x: x[0]) my_list.append({ 'metric': { 'account': account, 'email_domain': email_domain, 'version': version }, 'values': sorted_values })
方法二:Pandas实现
通过数据展开、分组求和、重构格式三个步骤完成:
import pandas as pd # 1. 将原始列表转为DataFrame,并提取metric中的字段 df = pd.DataFrame(my_list) df[['account', 'email_domain', 'version']] = df['metric'].apply( lambda x: pd.Series([x['account'], x['email_domain'], x['version']]) ) # 2. 展开values列,拆分时间戳和数值并转换类型 df = df.explode('values') df[['timestamp', 'value']] = df['values'].apply(pd.Series) df['value'] = df['value'].astype(int) # 3. 分组求和 grouped_df = df.groupby(['account', 'email_domain', 'version', 'timestamp'])['value'].sum().reset_index() # 4. 重构为目标格式 result = [] for (account, email_domain, version), group in grouped_df.groupby(['account', 'email_domain', 'version']): values = group[['timestamp', 'value']].apply(lambda x: [x['timestamp'], str(x['value'])], axis=1).tolist() result.append({ 'metric': { 'account': account, 'email_domain': email_domain, 'version': version }, 'values': values }) my_list = result
内容的提问来源于stack exchange,提问作者Aviv Litman
相关产品推荐
相关产品推荐

