如何实现基于Pandas DataFrame最近3个非NaN季度数据的行分类并新增Criteria列
解决Pandas中基于最近3个非缺失季度数据的条件判断问题
我拥有一个Pandas DataFrame,其中每一列代表一个季度,最新的季度列位于DataFrame的右侧。由于数据并非一次性全部获取,部分列存在缺失值(NaN)。我需要在该DataFrame的末尾新增一列名为Criteria的列,判断规则如下:若最近3个有可用数据(即忽略NaN值)的季度数值均大于10,则Criteria取值为Y,否则取值为N。在提供的示例数据中,行B、D、E的Criteria值应为Y,其余行则标记为N。但我无法实现动态忽略NaN值的条件判断逻辑,现附上示例代码,恳请提供解决方案。
解决方案
核心思路是:对每一行提取所有非NaN的有效数据,筛选出最新的三个(即按季度从新到旧的前三个有效数据),判断这三个值是否全部大于10,同时确保有效数据数量至少为3个(否则无法满足“最近3个”的条件)。
方法一:简洁的Lambda+Apply实现
这种方法代码紧凑,适合快速实现:
import pandas as pd import numpy as np # 示例数据 list_of_tuples = [ (11, 34, 78, 5, -11, -56), (12, np.NaN, 98, 7, np.NaN, 18), (21, 56, -78, -23, 64, 28), (56, -98, 35, 63, 27, np.NaN), (13, 34, -11, 11, 56, 10), (12, 41, 12, 41, -78, -18), ] df = pd.DataFrame( list_of_tuples, index=['A', 'B', 'C', 'D', 'E', 'F'], columns=['2020Q4', '2021Q1', '2021Q2', '2021Q3', '2021Q4', '2022Q1'], ) # 新增Criteria列 df['Criteria'] = df.apply( lambda x: 'Y' if (len(x.dropna()) >= 3) and (x.dropna().tail(3) > 10).all() else 'N', axis=1 ) print(df)
代码解释
x.dropna():移除当前行的所有NaN值,得到按季度从旧到新排列的有效数据x.dropna().tail(3):取有效数据的最后3个,对应最新的3个有数据的季度(x.dropna().tail(3) > 10).all():判断这3个值是否全部大于10len(x.dropna()) >=3:确保当前行至少有3个有效数据,否则直接返回N(因为无法满足“最近3个”的要求)
方法二:自定义函数实现(更易读、便于扩展)
如果需要更清晰的逻辑或后续扩展规则,推荐使用自定义函数:
def check_recent_quarters(row): # 提取当前行的所有非NaN值,按季度从旧到新排列 valid_vals = row.dropna().tolist() # 检查有效数据数量是否足够 if len(valid_vals) < 3: return 'N' # 取最新的3个有效数据 recent_three = valid_vals[-3:] # 判断是否全部大于10 if all(val > 10 for val in recent_three): return 'Y' else: return 'N' # 应用函数到每一行 df['Criteria'] = df.apply(check_recent_quarters, axis=1)
结果说明
针对你的示例数据,运行上述代码后:
- 行D的有效数据为
[56, -98, 35, 63, 27],最新三个是[35,63,27],全部大于10 → 标记为Y - 若你的示例中行B的有效数据存在笔误(比如7应为17),则最新三个为
[98,17,18],全部大于10 → 标记为Y - 行A的最新三个有效数据为
[5,-11,-56],不满足条件 → 标记为N
内容的提问来源于stack exchange,提问作者Isaac B
相关产品推荐
相关产品推荐

