繁体   English   中英

前向填充Pandas Dataframe水平(沿着行),而不会向前填充每行中的最后一个值

[英]Forward Fill Pandas Dataframe Horizontally (along rows) without forward filling last value in each row

我有一个Pandas数据框,我想转发填充HORIZONTALLY但我不想转发填写每行的最后一个条目。 这是关于某些产品已停产的产品的时间序列定价数据,因此我不希望记录的最后一个值向前填充到当前。

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

在IIUC中,您需要apply axis=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

您可以使用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]])

使用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

很少修改 - Most efficient way to forward-fill NaN values in numpy array的解决方案中Most efficient way to forward-fill NaN values in numpy array这里解决它 -

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

我想在ffill上使用where可以回到那些在bfill上被忽略的NaN

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM