看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
今天的这个需求比较复杂,会给定一段样本数据,然后将数据集中符合这些样本的数据全部筛选出来。这将与以往我们筛选连续性的数据不同,会给我们带来挑战。
本案例在 pandas 2.2 下通过。
数据集如下:
import pandas as pd
import io
col = '''
col
3
4
7
3
6
3
4
7
3
5
7
3
4
7
'''
# 样本数据
data = [3,4,7]
# 读入数据
df = pd.read_csv(io.StringIO(col))
df
'''
col
0 3
1 4
2 7
3 3
4 6
5 3
6 4
7 7
8 3
9 5
10 7
11 3
12 4
13 7
'''
上边给出了数据集和样本数据,现在需要将数据集中的符合样本,数据的内容全部筛选出来。这与我们之前传统的数据筛选,有所不同之前是看每个个体是否满足某种条件,现在需要相邻的一段数据与样本数据相同。
我看观察看到,满足样本 data 的数据中的片段有索引0-2、5-7、11-13。
由于查询样本是一个整体,我们没办法使用简单的条件语句进行筛选,因此我们需要想别的办法。 我们发现,样本的长度为三。这时,我们可以想到用移动窗口的形式来检测,每个窗口是否与样本数据相同?如果全部相同,则返回 True,最后通过这些片段的点找到存在的样本。
首先应用窗口函数:
# 窗口的大小就是样本的长度,这里是3
df.col.rolling(window=len(data))
# Rolling [window=3,center=False,axis=0]
它返回了一个移动窗口对象, 接着我们应用函数对每个窗口的内容判断是否与样本相同:
(
df.col
.rolling(window=len(data))
.apply(lambda x: (x==data).all())
)
'''
0 NaN
1 NaN
2 1.0
3 0.0
4 0.0
5 0.0
6 0.0
7 1.0
8 0.0
9 0.0
10 0.0
11 0.0
12 0.0
13 1.0
Name: col, dtype: float64
'''
我们发现移动窗口应用函数时会返回一个数字类型。他将布尔转化为数字类型是真值转换为1,假值转化为0,同时,只落在满足条件的窗口点处。
唯一的窗口点给我们提供了非常有价值的信息,这些点是样本片段的结尾,包括自己向前的三个值为样本整体。我们将这些点筛选出来,并且去它们的索引:
rng = (
df.col
.rolling(window=len(data))
.apply(lambda x: (x==data).all())
.loc[lambda x: x==1]
.index
)
rng
# Int64Index([2, 7, 13], dtype='int64')
由于样本节点有多个,我们通过这些节点推算出样本的范围,并将它们合并在一个序列里,这时我们基本上就得到了答案:
# 定一个空的序列
s = []
# 根据样本点推断, 将数据追加到序列中
for i in rng:
s_temp = df.col.loc[i-len(data)+1: i]
s.extend(s_temp.index)
s
# [1, 2, 3, 6, 7, 8, 12, 13, 14]
还可以通过它对 df 进行筛选。
df.loc[s]
'''
col
0 3
1 4
2 7
5 3
6 4
7 7
11 3
12 4
13 7
'''
(完)
更新时间:2024-08-18 15:40:59 标签:pandas python 筛选 样本