Python中如何通过迭代实现Pandas DataFrame多条件筛选并解决KeyError问题?
解决Pandas中迭代构建连续行筛选条件的问题
你遇到的核心问题是把字符串表达式直接传给了df.loc[]——loc需要的是布尔值数组(或者布尔条件),而不是字符串形式的代码。直接传字符串会被当成列名去查找,自然就抛出KeyError了。下面给你两种实用的解决方案:
方案一:迭代构建布尔条件(不拼接字符串)
不用把条件拼成字符串,而是直接在循环中组合布尔Series,这样就能生成loc需要的布尔掩码:
import pandas as pd # 示例数据(还原你给出的测试场景) data = { 'A': [15.1252, 13.1251, 1.3125, 1.5625, 39.5625, 45.6875, 11.0000, 11.0000, 1.8125, 1.8125, 1.4375, 1.4375, 1.5000, 1.5000, 1.5000, 1.5000, 1.4375, 1.4375, 1.5000] } df = pd.DataFrame(data, index=[329,330,331,332,333,346,347,348,354,355,358,359,360,361,362,363,364,365,366]) # 定义参数:(shift步数, 阈值) parameters = [[0, 1.7], [1, 1.7], [2, 1.7], [3, 1.7], [4, 1.7], [5, 1.7]] # 初始化条件为全True,之后逐个与新条件做"且"运算 condition = pd.Series([True]*len(df), index=df.index) for shift_step, threshold in parameters: condition &= df['A'].shift(-shift_step).lt(threshold) # 执行筛选 result = df.loc[condition] print(result)
运行这段代码就能得到你想要的结果,完全避开了字符串解析的坑。
方案二:用Rolling窗口更简洁实现
其实你的需求是找出当前行及后续5行(共6行)都满足A<1.7的行,用Pandas的rolling窗口可以更优雅地实现,不用手动处理多次shift:
# 反向滚动窗口:先倒序数据,让rolling(6)覆盖原数据的当前行+后续5行 rolling_mask = df['A'].iloc[::-1].rolling(window=6, min_periods=6).apply(lambda x: all(x < 1.7)).iloc[::-1].astype(bool) # 筛选结果 result = df.loc[rolling_mask] print(result)
这里的逻辑是:
- 先把数据倒序,这样
rolling(6)的窗口就对应原数据中当前行及之后的5行 - 用
apply检查窗口内所有值是否都小于1.7 - 再把结果倒序回来,得到和原数据索引匹配的布尔掩码
这种方法扩展性更强——如果之后需要调整连续检测的行数,只需要修改window参数即可,不用改动其他逻辑。
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

