看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
本例是一个数据修正的案例,在一个分组中,有两个固定值,不分位置,可能有一个数据是不正确的,需要修改为正确的值。
我们的源数据如下:
import pandas as pd
from io import StringIO
data = '''
code text
group1 左前
group1 右前
group2 前
group2 右前
group3 左前
group3 前
group4 左前
group4 右前
group5 前
group5 左前
group6 左前
group6 前
'''
df = pd.read_csv(StringIO(data), sep=r'\s+')
df
# ...
code 列是分组名称,text 列是分组的值,在一个分组中必须有「左前」、「右前」两个值,哪个值在前哪个值在后没有规定。当前的的数据中,有些组内的一个值是「前」,需要我们按照取值要求进行修正。
例如:group2 的「前」修正为「左前」,group5 的「前」修正为「右前」。
此需求是要求按组去处理,意味着我们要对数据进行分组,每个分组是一个独立的处理逻辑单元。
可以将「前」值替换为缺失值,在一个组内,判断如果有「左前」就将这个缺失值填充为「右前」,反之替换为「右前」。
先把「前」替换为缺失值,我们先写单个组的逻辑,以 group2 为例,目测到缺失值为「左前」,我们进行填充:
(
df.replace('前', pd.NA)
.loc[df.code=='group2']
.fillna('左前')
)
'''
code text
2 group2 左前
3 group2 右前
'''
这样例将一个组的数据完成了填充。接下来我们编写判断方法,来判断一个分组(分组后的子DataFrame)是否包含指定的值。
如,以下是判断 group2 内是否包含「右前」,执行后得到一个布尔 DataFrame:
(
df.replace('前', pd.NA)
.loc[df.code=='group2']
.isin(['右前'])
)
'''
code text
2 False False
3 False True
'''
如果其中一个值为 True 就说明包含「右前」,使用 any() 方法,传入 axis=None
将不按轴进行计算而是对所有值进行判断:
(
df.replace('前', pd.NA)
.loc[df.code=='group2']
.isin(['右前'])
.any(axis=None)
)
# True
可以看到返回一个布尔标量,True 表示包含。
接下来,我们将判断逻辑和缺失值填充逻辑封装为一个函数,然后来应用:
def func(grouped: pd.DataFrame):
if grouped.isin(['右前']).any(axis=None):
return grouped.fillna('左前')
else:
return grouped.fillna('右前')
(
df.replace('前', pd.NA)
.groupby('code', group_keys=False)
.apply(func)
)
'''
code text
0 group1 左前
1 group1 右前
2 group2 左前
3 group2 右前
4 group3 左前
5 group3 右前
6 group4 左前
7 group4 右前
8 group5 右前
9 group5 左前
10 group6 左前
11 group6 右前
'''
还可以用一行(逻辑行)代码来完成:
(
df.replace('前', pd.NA)
.groupby('code', group_keys=False)
.apply(lambda x: x.fillna('左前') if x.isin(['右前']).any(axis=None) else x.fillna('右前'))
)
这样就得到了我们想要的结果。
(完)
更新时间:Aug. 18, 2024, 4:08 p.m. 标签:pandas python 分组