水平(沿行)向前填充熊猫数据框,而不向前填充每行中的最后一个值

时间:2019-06-13 19:19:55

标签: python pandas numpy

我有一个Pandas数据框,我想水平填充前向填充,但是我不想向前填充超过每一行的最后一个条目。这是一些产品已经停产的时间序列定价数据,因此我不希望将记录的最后一个值预先填充为当前价格。

FWDFILL.apply(lambda series: series.iloc[:,series.last_valid_index()].ffill(axis=1))

^我所包含的代码可以实现我想要的功能,但它确实可以实现。这也许可以帮助人们作为起点。

>>> print(FWDFILL)

1      1     NaN     NaN     2     NaN  
2     NaN     1      NaN     5     NaN  
3     NaN     3       1     NaN    NaN  
4     NaN    NaN     NaN    NaN    NaN  
5     NaN     5      NaN    NaN     1  

所需的输出:

1      1      1      1     2     NaN  
2     NaN     1      1     5     NaN  
3     NaN     3      1    NaN    NaN  
4     NaN    NaN    NaN   NaN    NaN  
5     NaN     5      5     5      1

5 个答案:

答案 0 :(得分:3)

IIUC,您需要将applyaxis=1一起使用,因此您要应用到数据框行而不是数据框列。

df.apply(lambda x: x[:x.last_valid_index()].ffill(), axis=1)

输出:

     1    2    3    4    5
0                         
1  1.0  1.0  1.0  2.0  NaN
2  NaN  1.0  1.0  5.0  NaN
3  NaN  3.0  1.0  NaN  NaN
4  NaN  NaN  NaN  NaN  NaN
5  NaN  5.0  5.0  5.0  1.0

答案 1 :(得分:3)

您可以使用numpy查找最后一个有效索引并屏蔽ffill。这使您可以使用矢量化的ffill,然后使用矢量化的蒙版。


u = df.values
m = (~np.isnan(u)).cumsum(1).argmax(1)
df.ffill(1).mask(np.arange(df.shape[0]) > m[:, None])

     0    1    2    3    4
0  1.0  1.0  1.0  2.0  NaN
1  NaN  1.0  1.0  5.0  NaN
2  NaN  3.0  1.0  NaN  NaN
3  NaN  NaN  NaN  NaN  NaN
4  NaN  5.0  5.0  5.0  1.0

信息

>>> np.arange(df.shape[0]) > m[:, None]
array([[False, False, False, False,  True],
       [False, False, False, False,  True],
       [False, False, False,  True,  True],
       [False,  True,  True,  True,  True],
       [False, False, False, False, False]])

答案 2 :(得分:3)

bfillffill的用法

s1=df.ffill(1)
s2=df.bfill(1)
df=df.mask(s1.notnull()&s2.notnull(),s1)
df
Out[222]: 
     1    2    3    4    5
1  1.0  1.0  1.0  2.0  NaN
2  NaN  1.0  1.0  5.0  NaN
3  NaN  3.0  1.0  NaN  NaN
4  NaN  NaN  NaN  NaN  NaN
5  NaN  5.0  5.0  5.0  1.0

或者仅使用interpolate

df.mask(df.interpolate(axis=1,limit_area='inside').notnull(),df.ffill(1))
Out[226]: 
     1    2    3    4    5
1  1.0  1.0  1.0  2.0  NaN
2  NaN  1.0  1.0  5.0  NaN
3  NaN  3.0  1.0  NaN  NaN
4  NaN  NaN  NaN  NaN  NaN
5  NaN  5.0  5.0  5.0  1.0

答案 3 :(得分:1)

对-Most efficient way to forward-fill NaN values in numpy array's solution的少量修改,请在此处解决-

def ffillrows_stoplast(arr):
    # Identical to earlier solution of forward-filling
    mask = np.isnan(arr)
    idx = np.where(~mask,np.arange(mask.shape[1]),0)
    idx_acc = np.maximum.accumulate(idx,axis=1)
    out = arr[np.arange(idx.shape[0])[:,None], idx_acc]

    # Perform flipped index accumulation to get trailing NaNs mask and
    # accordingly assign NaNs there
    out[np.maximum.accumulate(idx[:,::-1],axis=1)[:,::-1]==0] = np.nan
    return out

样品运行-

In [121]: df
Out[121]: 
     A    B    C    D    E
1  1.0  NaN  NaN  2.0  NaN
2  NaN  1.0  NaN  5.0  NaN
3  NaN  3.0  1.0  NaN  NaN
4  NaN  NaN  NaN  NaN  NaN
5  NaN  5.0  NaN  NaN  1.0

In [122]: out = ffillrows_stoplast(df.to_numpy())

In [123]: pd.DataFrame(out,columns=df.columns,index=df.index)
Out[123]: 
     A    B    C    D    E
1  1.0  1.0  1.0  2.0  NaN
2  NaN  1.0  1.0  5.0  NaN
3  NaN  3.0  1.0  NaN  NaN
4  NaN  NaN  NaN  NaN  NaN
5  NaN  5.0  5.0  5.0  1.0

答案 4 :(得分:0)

我想在where上使用ffill来回退到NaN,而在bfill上被忽略的人

df.ffill(1).where(df.bfill(1).notna())    

Out[1623]:
     a    b    c    d    e
1  1.0  1.0  1.0  2.0  NaN
2  NaN  1.0  1.0  5.0  NaN
3  NaN  3.0  1.0  NaN  NaN
4  NaN  NaN  NaN  NaN  NaN
5  NaN  5.0  5.0  5.0  1.0