如何在Pandas DataFrame中筛选含至少3个符合条件连续行的列
问题:筛选存在至少3个连续符合条件行的Pandas列
需求:在Pandas DataFrame中筛选出**存在至少3个连续行满足“值非负、非NaN且不大于0.5”**的列(非针对单列),且因数据有2000列,需避免使用循环。
示例DataFrame代码
from random import uniform import pandas as pd import numpy as np idx = pd.date_range("2018-01-01", periods=10, freq="M") df = pd.DataFrame( { 'A':[0, 0.4, 0.5, 0.3, 0,0,0,0,0,0], 'B':[0, 0.6, 0.8,0, 0.3, 0.3, 0.9, 0.7,0,0], 'C':[0,0,0.5, 0.4, 0.4, 0.2,0,0,0,0], 'D':[0.4,0, 0.6, 0.5, 0.7, 0.2,0, 0.9, 0.8,0], 'E':[0.4, 0.3, 0.2, 0.7, 0.7, 0.8,0,0,0,0], 'F':[0,0,0.6, 0.7,0.8, 0.3, 0.4, 0.1,0,0] }, index=idx ) df = df.replace({0:np.nan})
预期输出
移除不满足条件的列(如B、D列),得到如下结果:
A C E F 2018-01-31 NaN NaN 0.4 NaN 2018-02-28 0.4 NaN 0.3 NaN 2018-03-31 0.5 0.5 0.2 0.6 2018-04-30 0.3 0.4 0.7 0.7 2018-05-31 NaN 0.4 0.7 0.8 2018-06-30 NaN 0.2 0.8 0.3 2018-07-31 NaN NaN NaN 0.4 2018-08-31 NaN NaN NaN 0.1 2018-09-30 NaN NaN NaN NaN 2018-10-31 NaN NaN NaN NaN
尝试的代码(未得到预期结果)
def consecutive_values_in_range(s, min, max): return s.between(left=min, right=max) min, max = 0, 0.5 df.apply(lambda col: consecutive_values_in_range(col, min, max), axis=0) print(df)
解决方案
利用Pandas向量化操作实现,无需循环,步骤如下:
- 标记每个单元格是否符合条件:非NaN、值在[0, 0.5]区间内
- 对每列使用滚动窗口(窗口大小3)计算连续符合条件的行数,当窗口内求和等于3时,说明存在连续3个符合条件的行
- 筛选出至少出现一次上述情况的列
完整代码:
import pandas as pd import numpy as np # 1. 标记符合条件的单元格 mask = df.notna() & df.between(0, 0.5) # 2. 计算每列是否存在至少3个连续符合条件的行 has_consecutive = mask.rolling(window=3, min_periods=3).sum().ge(3).any(axis=0) # 3. 筛选符合条件的列 result_df = df.loc[:, has_consecutive] print(result_df)
代码解释
mask = df.notna() & df.between(0, 0.5):生成布尔矩阵,True表示单元格满足“非NaN、0≤值≤0.5”mask.rolling(window=3, min_periods=3).sum():对每列做窗口大小为3的滚动求和,仅当窗口内3个值都存在时才计算,求和结果为3意味着窗口内3个单元格都符合条件.ge(3).any(axis=0):判断每列是否存在至少一次连续3个符合条件的情况,返回布尔Seriesdf.loc[:, has_consecutive]:根据布尔Series筛选出符合要求的列
内容的提问来源于stack exchange,提问作者ArthurK
相关产品推荐
相关产品推荐

