看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
在气候变化研究中,可以按照年份或更长时间范围对各种气象指标(如温度、降水量等)进行分组,计算每组的平均值,并与历史数据进行对比,筛选出异常值,用于分析气候变化趋势和影响。我们本例来研究一下如何利用 pandas 筛选部分列对应平均值的情况。
我们构造数据如下:
import pandas as pd
import io
data = '''
name temp number area value1 value2
A 10C 1 China 1 8
A 10C 2 China 3 10
A 20C 3 China 5 4
A 30C 4 China 7 6
B 10C 1 America 12 20
B 20C 2 America 14 22
B 30C 3 America 16 24
B 40C 4 America 18 26
'''
df = pd.read_csv(io.StringIO(data), sep=r'\s+')
df
# ...
我们期望按照 name 列分组,对于 value1 和 value2 两列,大于平均值的保留,小于平均值的舍弃,其他列不变化保留即可。
我们先看看单个列,如 value1 如何实现需求中的逻辑,然后再将它写成批量代码。
我们先对 name 进行分组,然后取分组对象的 value1 列,用 transform()
应用 mean 求得各组的平均值,然后与 value1 进行比较,得到一个布尔序列。
用 where 传入以上布尔序列就将不符合要求的值设置为 Nan 了。
仅 value1 的代码如下:
(
df.value1
.where(
df.value1 > df.groupby('name')
.value1.transform('mean')
)
)
'''
0 NaN
1 NaN
2 5.0
3 7.0
4 NaN
5 NaN
6 16.0
7 18.0
Name: value1, dtype: float64
'''
然后根据思路设计成函数,应用到每行:
def func(ser:pd.Series) -> pd.Series:
if (col:=ser.name) in ['value1', 'value2']:
ser_gb = df.groupby('name')[col]
ser_mean = ser_gb.transform('mean')
return ser.where(ser > ser_mean)
else:
return ser
df.apply(func)
'''
name temp number area value1 value2
0 A 10C 1 China NaN 8.0
1 A 10C 2 China NaN 10.0
2 A 20C 3 China 5.0 NaN
3 A 30C 4 China 7.0 NaN
4 B 10C 1 America NaN NaN
5 B 20C 2 America NaN NaN
6 B 30C 3 America 16.0 24.0
7 B 40C 4 America 18.0 26.0
'''
就完成了需求。
(完)
更新时间:2024-08-18 16:22:51 标签:pandas python 筛选 平均数