如何按ID累计统计DataFrame中X/Y列的变更次数(忽略NaN→NaN)
解决方案
可以通过 Pandas 的分组、移位对比和累计求和实现需求,具体步骤如下:
1. 构造示例数据
先还原你提供的 DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame({ "标识(Identification)": [123, 123, 123, 124, 124, 124], "日期(日/月/年)": ["01/01/2022", "02/01/2022", "03/01/2022", "01/01/2022", "02/01/2022", "03/01/2022"], "X": [np.nan, 200, 200, 200, np.nan, np.nan], "Y": ["abc", "acb", "ary", "abc", "abc", np.nan] })
2. 按标识分组生成变更标记
对每个分组的 X、Y 列,对比当前行与上一行的值,按规则生成变更标记(符合有效变更记为1,否则0):
def mark_change(series): prev_values = series.shift(1) # 匹配三种有效变更场景:NaN→非NaN、非NaN→NaN、非NaN之间值不同 change_mask = (~series.isna() & prev_values.isna()) | \ (series.isna() & ~prev_values.isna()) | \ (~series.isna() & ~prev_values.isna() & (series != prev_values)) # 分组首行无前置值,标记为0 change_mask.iloc[0] = 0 return change_mask.astype(int) # 分组应用函数得到变更标记 change_x = df.groupby("标识(Identification)")["X"].apply(mark_change) change_y = df.groupby("标识(Identification)")["Y"].apply(mark_change)
3. 累计求和得到变更计数
对变更标记做分组内的累计求和,得到最终的变更计数列:
df["Change X"] = change_x.groupby(df["标识(Identification)"]).cumsum() df["Change Y"] = change_y.groupby(df["标识(Identification)"]).cumsum()
最终结果
运行后得到的 DataFrame 与你期望的输出完全一致:
标识(Identification) 日期(日/月/年) X Y Change X Change Y 0 123 01/01/2022 NaN abc 0 0 1 123 02/01/2022 200.0 acb 1 1 2 123 03/01/2022 200.0 ary 1 2 3 124 01/01/2022 200.0 abc 0 0 4 124 02/01/2022 NaN abc 1 0 5 124 03/01/2022 NaN NaN 1 1
内容的提问来源于stack exchange,提问作者Mitchell
相关产品推荐
相关产品推荐

