根据另一行向前或向后填充

时间:2017-02-02 14:27:20

标签: python pandas

我有一个如下数据框:

 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中是否有更有效的方法来执行此操作?

2 个答案:

答案 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