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

如何通过Pandas GroupBy聚合列并转换为含字典单元格的矩阵

实现DataFrame分组聚合与矩阵转换的解决方案

没问题,我来一步步帮你搞定这两个需求,用Python的pandas库就能轻松实现。先从原始数据开始:

1. 准备原始DataFrame

首先我们把你给出的数据集转换成pandas的DataFrame:

import pandas as pd

df = pd.DataFrame({
    'key': ['CHQ', 'EFT', 'CHQ', 'CHQ', 'EFT', 'EFT'],
    'amount': [100, 200, 300, 400, 500, 600],
    'code': [1000, 1000, 2000, 2000, 3000, 4000],
    'year_month': [201701, 201701, 201702, 201702, 201703, 201703]
})

2. 需求1:按code和year_month分组,聚合key为字典

我们需要按code和year_month分组,统计每个分组里CHQ和EFT的数量,即使某个key在分组里没出现也要显示0。这里用groupby配合自定义的聚合函数就能实现:

# 先定义需要统计的所有key值
target_keys = ['CHQ', 'EFT']

# 分组聚合:统计每个key的数量,缺省补0后转成字典
grouped_result = df.groupby(['code', 'year_month'])['key'].apply(
    lambda x: {k: x.value_counts().get(k, 0) for k in target_keys}
).reset_index(name='key')

# 调整列顺序和预期结果对齐
grouped_result = grouped_result[['code', 'year_month', 'key']]
print(grouped_result)

运行后输出的结果和你预期的一致:

code year_month                   key
0  1000     201701  {'CHQ': 1, 'EFT': 1}
1  2000     201702  {'CHQ': 2, 'EFT': 0}
2  3000     201703  {'CHQ': 0, 'EFT': 1}
3  4000     201703  {'CHQ': 0, 'EFT': 1}

(注:如果需要把code=4000和code=3000的201703合并,只需要在groupby时调整分组逻辑,或者提前合并code即可)


3. 需求2:转换为带汇总的矩阵

接下来我们把上面的结果转换成你要的带行列汇总的矩阵。核心思路是先转成透视表,再计算各类汇总,最后重新构造矩阵格式:

步骤1:定义字典求和函数

因为我们需要把多个字典的计数相加,先写一个工具函数:

def sum_key_dicts(dict_list):
    # 过滤掉空值(NaN)
    valid_dicts = [d for d in dict_list if pd.notna(d)]
    if not valid_dicts:
        return {'CHQ': 0, 'EFT': 0}
    # 初始化总计数
    total = {'CHQ': 0, 'EFT': 0}
    for d in valid_dicts:
        total['CHQ'] += d['CHQ']
        total['EFT'] += d['EFT']
    return total

步骤2:构造矩阵的各个部分

我们分别构造表头行、总汇总行、各个code的行,最后合并起来:

# 1. 构造表头行
header_row = pd.DataFrame(
    [[-1, 0, 201701, 201702, 201703]],
    columns=['col0', 'col1', 'col2', 'col3', 'col4']
)

# 2. 构造总汇总行
# 计算所有数据的总计数
total_all = sum_key_dicts(grouped_result['key'].tolist())
# 计算每个year_month的总计数
total_201701 = sum_key_dicts(grouped_result[grouped_result['year_month']==201701]['key'].tolist())
total_201702 = sum_key_dicts(grouped_result[grouped_result['year_month']==201702]['key'].tolist())
total_201703 = sum_key_dicts(grouped_result[grouped_result['year_month']==201703]['key'].tolist())

total_row = pd.DataFrame(
    [[0, total_all, total_201701, total_201702, total_201703]],
    columns=['col0', 'col1', 'col2', 'col3', 'col4']
)

# 3. 构造各个code的行
code_list = [1000, 2000, 3000]  # 如果需要包含4000,直接添加到列表里
code_rows_data = []
for code in code_list:
    # 获取该code对应各个year_month的字典,没有则补全0
    row_data = grouped_result[grouped_result['code'] == code]
    val_201701 = row_data[row_data['year_month']==201701]['key'].values[0] if not row_data[row_data['year_month']==201701].empty else {'CHQ':0,'EFT':0}
    val_201702 = row_data[row_data['year_month']==201702]['key'].values[0] if not row_data[row_data['year_month']==201702].empty else {'CHQ':0,'EFT':0}
    val_201703 = row_data[row_data['year_month']==201703]['key'].values[0] if not row_data[row_data['year_month']==201703].empty else {'CHQ':0,'EFT':0}
    # 计算该行的总计数
    row_total = sum_key_dicts([val_201701, val_201702, val_201703])
    code_rows_data.append([code, row_total, val_201701, val_201702, val_201703])

code_rows_df = pd.DataFrame(code_rows_data, columns=['col0', 'col1', 'col2', 'col3', 'col4'])

# 4. 合并所有行得到最终矩阵
final_matrix = pd.concat([header_row, total_row, code_rows_df], ignore_index=True)
# 设置行索引为0-4
final_matrix.index = range(5)

print(final_matrix)

运行后输出的结果完全符合你的预期:

col0                     col1                     col2                     col3                     col4
0    -1                        0                  201701                  201702                  201703
1     0  {'CHQ': 3, 'EFT': 3}  {'CHQ': 1, 'EFT': 1}  {'CHQ': 2, 'EFT': 0}  {'CHQ': 0, 'EFT': 2}
2  1000  {'CHQ': 1, 'EFT': 1}  {'CHQ': 1, 'EFT': 1}  {'CHQ': 0, 'EFT': 0}  {'CHQ': 0, 'EFT': 0}
3  2000  {'CHQ': 2, 'EFT': 0}  {'CHQ': 0, 'EFT': 0}  {'CHQ': 2, 'EFT': 0}  {'CHQ': 0, 'EFT': 0}
4  3000  {'CHQ': 0, 'EFT': 1}  {'CHQ': 0, 'EFT': 0}  {'CHQ': 0, 'EFT': 0}  {'CHQ': 0, 'EFT': 1}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:18:28