看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
pandas 在做数据分组聚合时一般会在明确的列上进行,今天我们看到案例虽然指定了要分组的列,但却不能按列上的原值进行分组,需要行进行一些处理。
我们有数据如下:
from io import StringIO
import pandas as pd
data = '''
工程内容,数量
电线,10
电缆,10
1号配电柜,1
2号配电柜,1
3号配电柜,1
桥架,10
'''
df = pd.read_csv(StringIO(data))
df
'''
工程内容 数量
0 电线 10
1 电缆 10
2 1号配电柜 1
3 2号配电柜 1
4 3号配电柜 1
5 桥架 10
'''
数据中有两个列,我们要分组的列是工程内容,聚合的列自然就是数量了。但对于工程内容列 分组时我们不能直接进行分组,我们看到此列有三个关于“电柜”的数值, 需求期望将包含柜字的分到一起,分组名为“配电柜”,然后将组内的数量相加。
在分组前,需要先对工程内容列的数据进行修改,将包含“柜”字的值进行修改,修改可以使用 assign(),指定一个同名的列。然后再分组,最后将数量列按组相加。
先修改工程内容列,我们这里用 mask() 方法:
(
df.assign(工程内容=df.工程内容.mask(df.工程内容.str.contains('柜'), '配电柜'))
)
'''
工程内容 数量
0 电线 10
1 电缆 10
2 配电柜 1
3 配电柜 1
4 配电柜 1
5 桥架 10
'''
此外,我们还可以使用 if 语句直接判断,让代码更加清晰,就用到 map() 或者 apply() 方法:
(
df.assign(工程内容=df.工程内容.map(lambda x: '配电柜' if '柜' in x else x))
# 方法相同
.assign(工程内容=df.工程内容.apply(lambda x: '配电柜' if '柜' in x else x))
)
最后再分组、聚合:
(
df.assign(工程内容=df.工程内容.map(lambda x: '配电柜' if '柜' in x else x))
# .assign(工程内容=df.工程内容.apply(lambda x: '配电柜' if '柜' in x else x))
# .assign(工程内容=df.工程内容.mask(df.工程内容.str.contains('柜'), '配电柜'))
.groupby('工程内容', sort=False, as_index=False)
.sum()
)
'''
工程内容 数量
0 电线 10
1 电缆 10
2 配电柜 3
3 桥架 10
'''
groupby() 分组是,我们传入了两个额外的参数:
sort=False
,不重新排序,让分组保持原来第一次出现的顺序as_index=False
,不将分组名设置为索引,让得到数据与原数据一样使用自然数字索引这样我们就完成了需求。
(完)
更新时间:2024-08-18 15:59:50 标签:pandas python 分组 字符