如何用Pandas标记满足前3行颜色及数值范围条件的数据行?
Pandas实现基于前3行条件的标记需求
原始数据
| color | down | top | |
|---|---|---|---|
| 0 | 1 | 5 | |
| 1 | 2 | 5 | |
| 2 | blue | 7 | 11 |
| 3 | 5 | 8 | |
| 4 | 9 | 10 | |
| 5 | 9 | 10 | |
| 6 | orange | 5 | 9 |
| 7 | 4 | 7 | |
| 8 | 5 | 10 | |
| 9 | 5 | 6 | |
| 10 | 3 | 7 |
需求说明
- blue_condition:当前行的前3行中存在
color为blue的行,且当前行的top值处于该行的down与top之间 - orange_condition:当前行的前3行中存在
color为orange的行,且当前行的top值处于该行的down与top之间
预期输出
| color | down | top | blue_condition | orange_condition | |
|---|---|---|---|---|---|
| 0 | 1 | 5 | |||
| 1 | 2 | 5 | |||
| 2 | blue | 7 | 11 | ||
| 3 | 5 | 8 | 1 | ||
| 4 | 9 | 10 | 1 | ||
| 5 | 9 | 10 | 1 | ||
| 6 | orange | 5 | 9 | ||
| 7 | 4 | 7 | 1 | ||
| 8 | 5 | 10 | |||
| 9 | 5 | 6 | 1 | ||
| 10 | 3 | 7 |
用户尝试代码
df = pd.DataFrame({"color": [None, None, 'blue', None, None, None, 'orange', None, None, None, None], 'down': [1, 2, 7, 5, 9, 9, 5, 4, 5, 5, 3], 'top': [5, 5, 11, 8, 10, 10, 9, 7, 10, 6, 7]}) # get latest 3 records df['blue_condition'] = df.tail(3) # assign using lambda df['blue_condition'].assign(blue_condition=lambda x: (x.tail(3).query(top < top.tail(3))))
可行实现方案
通过滑动窗口结合自定义函数实现,核心是逐行检查前3行窗口内的条件:
import pandas as pd df = pd.DataFrame({"color": [None, None, 'blue', None, None, None, 'orange', None, None, None, None], 'down': [1, 2, 7, 5, 9, 9, 5, 4, 5, 5, 3], 'top': [5, 5, 11, 8, 10, 10, 9, 7, 10, 6, 7]}) def check_blue_condition(window): current_top = window['top'].iloc[-1] # 取窗口内除当前行外的blue行 blue_rows = window[window['color'] == 'blue'].iloc[:-1] if len(blue_rows) == 0: return 0 # 判断当前top是否落在任意blue行的区间内 return 1 if any((blue_rows['down'] <= current_top) & (current_top <= blue_rows['top'])) else 0 def check_orange_condition(window): current_top = window['top'].iloc[-1] orange_rows = window[window['color'] == 'orange'].iloc[:-1] if len(orange_rows) == 0: return 0 return 1 if any((orange_rows['down'] <= current_top) & (current_top <= orange_rows['top'])) else 0 # 滑动窗口包含当前行+前3行,逐行应用函数 df['blue_condition'] = df.rolling(window=4, min_periods=1).apply(check_blue_condition, raw=False).astype(int) df['orange_condition'] = df.rolling(window=4, min_periods=1).apply(check_orange_condition, raw=False).astype(int) # 匹配预期输出,将无意义的初始值设为空 df.loc[:2, 'blue_condition'] = '' df.loc[:5, 'orange_condition'] = '' print(df.to_markdown(index=True))
代码说明
- 滑动窗口配置:
window=4覆盖当前行及前3行,min_periods=1保证首行可正常处理 - 自定义条件函数:提取当前行
top值,筛选窗口内目标颜色的历史行,判断区间包含关系 - 结果格式化:根据预期输出,将无需标记的初始行设为空字符串,最终输出Markdown格式表格
内容的提问来源于stack exchange,提问作者Florian
相关产品推荐
相关产品推荐

