如何在Pandas中按日期分组统计各技术的积分总和?
解决Pandas按日期拆分列表型技术列并求和积分的问题
嘿,我来帮你搞定这个需求!你遇到的问题核心是tech列是列表类型,而Pandas的groupby要求分组键必须是可哈希的(比如字符串、数值),列表是不可哈希的,所以直接分组会报错。咱们可以通过「拆分列表→分组求和→转成宽表」三步解决,具体看下面的步骤:
步骤1:拆分列表型的tech列
首先用explode()方法把每个列表里的技术拆成单独一行,同时保留对应的date和score值,这一步是关键:
import pandas as pd # 复现你的原始数据 data = pd.DataFrame( {'date': ['2017-01-31', '2017-02-28', '2017-02-28'], 'tech': [['c++', 'python'], ['c++', 'c', 'java'], ['java']], 'score': [1, 4, 2]} ) # 拆分tech列的列表 exploded_data = data.explode('tech')
拆分后的exploded_data长这样:
| date | tech | score |
|---|---|---|
| 2017-01-31 | c++ | 1 |
| 2017-01-31 | python | 1 |
| 2017-02-28 | c++ | 4 |
| 2017-02-28 | c | 4 |
| 2017-02-28 | java | 4 |
| 2017-02-28 | java | 2 |
步骤2:按日期和技术分组求和
现在tech列已经是单个字符串了,就可以正常分组对score求和:
summed_data = exploded_data.groupby(['date', 'tech'])['score'].sum().reset_index()
分组求和后的结果:
| date | tech | score |
|---|---|---|
| 2017-01-31 | c++ | 1 |
| 2017-01-31 | python | 1 |
| 2017-02-28 | c | 4 |
| 2017-02-28 | c++ | 4 |
| 2017-02-28 | java | 6 |
步骤3:转成你想要的宽表格式
最后用pivot()把结果转成「日期为行,技术为列」的格式,缺失的数值用0填充:
result = summed_data.pivot(index='date', columns='tech', values='score').fillna(0).astype(int)
最终结果和你期望的一致:
| date | c | c++ | java | python |
|---|---|---|---|---|
| 2017-01-31 | 0 | 1 | 0 | 1 |
| 2017-02-28 | 4 | 4 | 6 | 0 |
如果想要技术为行,日期为列的格式,只需要交换pivot的index和columns参数:
result_transposed = summed_data.pivot(index='tech', columns='date', values='score').fillna(0).astype(int)
结果如下:
| tech | 2017-01-31 | 2017-02-28 |
|---|---|---|
| c | 0 | 4 |
| c++ | 1 | 4 |
| java | 0 | 6 |
| python | 1 | 0 |
扩展:多列数值求和
如果你的数据里除了score还有其他需要求和的数值列,只需要把分组后的['score']去掉,直接用sum()即可:
# 假设新增other_score列 data['other_score'] = [2, 5, 3] exploded_data = data.explode('tech') summed_multi = exploded_data.groupby(['date', 'tech']).sum().reset_index()
这样会自动对所有数值列求和,之后再用pivot转格式就行。
内容的提问来源于stack exchange,提问作者kaksat
相关产品推荐
相关产品推荐

