Pandas DataFrame特定行更新异常 按用户分组计算flag=1后时间差问题
问题原因分析
问题1:首次flag=1的行未返回NaN
- 根因是你第二个
assign中计算flag=1行的diff时,筛选出的子集d[d['mask'].groupby(d['user']).cumsum().eq(0)|d['mask']]包含了每个用户首次flag=1之前的所有行和所有flag=1的行,对这个子集按用户算time.diff()时,首次flag=1的行会和它前一行(flag=0的行)计算时间差,就得到了6.0、8.0这类不符合预期的值,而非你想要的NaN。 - 额外说明:原逻辑嵌套层数太多,完全可以大幅简化,不需要多层
assign和mask嵌套。
问题2:修改指定行后其他行变为NaN
- 根因是你前面的链式调用没有把计算结果赋值给
df变量,你操作的还是最开始只有user/Flag/time三列的原始DataFrame。执行df.loc[[2,6],'diff'] = 1000000000时,pandas会自动新增diff列,默认填充NaN,仅你指定的2、6行被赋值,所以其他行都是NaN。
解决方法
直接简化时间差计算逻辑,即可实现「按用户分组,每行时间减上次flag=1的时间,无上次flag=1则为NaN」的需求:
import pandas as pd df = pd.DataFrame({'user': ['x','x','x','x','x','y','y','y','y','y'], 'Flag': [0,0,1,0,1,0,1,0,1,0], 'time': [10, 34, 40, 43, 44, 12, 20, 46, 51, 71]}) # 把非flag=1的时间替换为空,按用户向前填充得到每行对应的上次flag=1的时间 df['last_flag1_time'] = df['time'].where(df['Flag']==1).groupby(df['user']).ffill() # 计算时间差 df['diff'] = df['time'] - df['last_flag1_time'] # 如果要求flag=1的行本身diff为NaN,加这行即可 df.loc[df['Flag']==1, 'diff'] = pd.NA
运行后输出结果如下:
user Flag time last_flag1_time diff 0 x 0 10 NaN NaN 1 x 0 34 NaN NaN 2 x 1 40 40.0 <NA> 3 x 0 43 40.0 3.0 4 x 1 44 44.0 <NA> 5 y 0 12 NaN NaN 6 y 1 20 20.0 <NA> 7 y 0 46 20.0 26.0 8 y 1 51 51.0 <NA> 9 y 0 71 51.0 20.0
需要修改指定行的diff值时,直接操作已完成计算的df即可,不会影响其他行数值:
df.loc[[2,6], 'diff'] = 1000000000
内容的提问来源于stack exchange,提问作者SteveS
相关产品推荐
相关产品推荐

