我有一个如下数据框:
loc status ID
0 LA NaN NaN
1 CHC NaN NaN
2 NYC ARR 32
3 CHC DEP 45
4 SEA NaN NaN
我正在尝试根据状态列填充ID列中的缺失值。如果状态栏是" ARR":我想倒退,如果状态栏是" DEP":我想填写前进,所以我的最终数据框看起来像:
loc status ID
0 LA NaN 32
1 CHC NaN 32
2 NYC ARR 32
3 CHC DEP 45
4 SEA NaN 45
我一直试图通过使用2个循环来遍历两个列来实现这一点,但我想知道在Pandas中是否有更有效的方法来执行此操作?
答案 0 :(得分:1)
这应该有效
dt.ID.fillna(method='bfill').fillna(method='ffill')
它将使用前面的非NA值填充NA值(先反向然后反向)
编辑:
也许这就是你要找的东西(基于评论)
dt.ID.fillna(method='ffill').where(dt.ID.notnull() | (dt.status.shift(1) == 'DEP'), dt.ID.fillna(method='bfill').where(dt.ID.notnull() | (dt.status.shift(-1) == 'ARR')))
它不是很易读,但应该给出一个大致的想法
答案 1 :(得分:0)
您可以根据您是要转发填充还是向后填充这些行来划分数据框df
来解决此问题:
创建你的df的两个副本,一个向前填充所有内容,另一个回填所有内容
fill_forward = df.status.fillna(method='ffill')
fill_backward = df.status.fillna(method='bfill')
获取前向填充导致行填充'DEP'
的行的索引以及返回填充导致行填充'ARR'
的索引(即您的两个条件)
forward_index = df.index[(df.status != fill_forward) & (fill_forward == 'DEP')]
backward_index = df.index[(df.status != fill_backward) & (fill_backward == 'ARR')]
更新这些索引,使它们包括前面的行(在向前填充时使用)或直接在后面的行(在向后填充时使用)。
forward_rows = sorted(list({ind for f in forward_index for ind in [f,f-1]}))
backward_rows = sorted(list({ind for b in backward_index for ind in [b,b+1]}))
为每个索引列表填充(使用适当的方法)并将更新的值分配给原始df。请注意,通过首先进行前向填充,当指数重叠时,您优先考虑前向填充。
df.ID.iloc[forward_rows] = df.ID.iloc[forward_rows].fillna(method='ffill')
df.ID.iloc[backward_rows] = df.ID.iloc[backward_rows].fillna(method='bfill')
print(df)
loc status ID
0 LA NaN 32.0
1 CHC NaN 32.0
2 NYC ARR 32.0
3 CHC DEP 45.0
4 SEA NaN 45.0