看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
pandas 在数据筛选中,连续数据的判断一直是一个难点,在本案例中,我们来通过一些技巧来完成连续条件的数据选取。本需求是要求,连续三天气温10度以上,我们就将其第一天认为是春季的开始。
为了简化讲解,我们模拟了以下部分数据。先读取到 pandas:
import pandas as pd
from io import StringIO
data = '''
date,temperature
2021-02-20,8.4
2021-02-21,7.2
2021-02-22,9.4
2021-02-23,10.5
2021-02-24,9.8
2021-02-25,10.1
2021-02-26,10.4
2021-02-27,10.2
2021-02-28,9.5
2021-03-01,9.9
2021-03-02,10.8
2021-03-03,10.9
2021-03-04,11.6
2021-03-05,11.7
2021-03-06,12.9
'''
df = pd.read_csv(StringIO(data))
df
# ...
数据一列是日期,一列为当日气温,顺序是按日期排序的,我们无需进行额外处理。
根据需求,我们重点放在气温列的处理上判断,这里数据从上倒下,如果第一次出现连续大于 10 时,就交这个连续部分中的第一行数据的日期取出。
首先,我们得想办法将温度列所有连续大于 10 的值标识出来,不同连续区域标识为不同值,方便后续进行分组处理。
如果成功标识,我们做分组操作,筛选出这所有值大于 10 及其数量大于等于3的组,然后去第一行数据即可。
接下来我们重点分析, 如何将特定条件的连续只标示出来。
我们根据温度列,是否大于10, 得到一个布尔序列,并对这个布尔序列求位差再累和,便可标识出这种连续性。
增加辅助列,先判断当前值是否大于10。
df.assign(foo=df.temperature.gt(10))
'''
date temperature foo
0 2021-02-20 8.4 False
1 2021-02-21 7.2 False
2 2021-02-22 9.4 False
3 2021-02-23 10.5 True
4 2021-02-24 9.8 False
5 2021-02-25 10.1 True
6 2021-02-26 10.4 True
7 2021-02-27 10.2 True
8 2021-02-28 9.5 False
9 2021-03-01 9.9 False
10 2021-03-02 10.8 True
11 2021-03-03 10.9 True
12 2021-03-04 11.6 True
13 2021-03-05 11.7 True
14 2021-03-06 12.9 True
'''
接下来我们利用布尔值求差的性质将不同的区分出来,方便后边使用累和标识:
True - True # 0 False 都大于10,只保留第一个 不区分
True - False # 1 True 将不同的区分出来
False - False # 0 False 都小于10,不区分
bool(False - True) # True 区分
求位差:
df.assign(foo=df.temperature.gt(10).diff())
'''
date temperature foo
0 2021-02-20 8.4 NaN
1 2021-02-21 7.2 False
2 2021-02-22 9.4 False
3 2021-02-23 10.5 True
4 2021-02-24 9.8 True
5 2021-02-25 10.1 True
6 2021-02-26 10.4 False
7 2021-02-27 10.2 False
8 2021-02-28 9.5 True
9 2021-03-01 9.9 False
10 2021-03-02 10.8 True
11 2021-03-03 10.9 False
12 2021-03-04 11.6 False
13 2021-03-05 11.7 False
14 2021-03-06 12.9 False
'''
求累和,布尔值求和时,True 按 1,False 按 0:
df.assign(foo=df.temperature.gt(10).diff().cumsum())
'''
date temperature foo
0 2021-02-20 8.4 NaN
1 2021-02-21 7.2 0.0
2 2021-02-22 9.4 0.0
3 2021-02-23 10.5 1.0
4 2021-02-24 9.8 2.0
5 2021-02-25 10.1 3.0
6 2021-02-26 10.4 3.0
7 2021-02-27 10.2 3.0
8 2021-02-28 9.5 4.0
9 2021-03-01 9.9 4.0
10 2021-03-02 10.8 5.0
11 2021-03-03 10.9 5.0
12 2021-03-04 11.6 5.0
13 2021-03-05 11.7 5.0
14 2021-03-06 12.9 5.0
'''
我们看到,按照我们给定的条件,这种连续性被标识了出来。
接下来我们对这个标识地进行分组,并按我们想要的条件符合的所有组。
(
df.assign(foo=df.temperature.gt(10).diff().cumsum())
.fillna(0)
.groupby('foo')
.filter(lambda x: len(x)>=3 and x.temperature.max()>10)
)
'''
date temperature foo
5 2021-02-25 10.1 3.0
6 2021-02-26 10.4 3.0
7 2021-02-27 10.2 3.0
10 2021-03-02 10.8 5.0
11 2021-03-03 10.9 5.0
12 2021-03-04 11.6 5.0
13 2021-03-05 11.7 5.0
14 2021-03-06 12.9 5.0
'''
最后取结果的第一行数据中的 date 列值,就是我们最终的代码。
# 计算春季开始的日期: 连续 3 天大于 10 的第一天
(
df.assign(foo=df.temperature.gt(10).diff().cumsum())
.fillna(0)
.groupby('foo')
.filter(lambda x: len(x)>=3 and x.temperature.max()>10)
.head(1)
.squeeze()
.date
)
# '2021-02-25'
这样就巧妙地完成了需求。
(完)
更新时间:2024-08-18 15:56:40 标签:pandas python 连续 气温