Python pandas ffil和bfill基于groupby条件

Python pandas ffil和bfill基于groupby条件,python,pandas,dataframe,Python,Pandas,Dataframe,每列col1、col2和col3都需要在列col4上设置向前或向后填充条件 假设我有这样一个数据帧: df = pd.DataFrame({'col1':[1,np.nan,3, np.nan,5,np.nan], 'col2':[7, np.nan, 9, np.nan, 11, np.nan], 'col3':[13, 14, 15, 16, np.nan,18],

每列
col1
col2
col3
都需要在列
col4
上设置向前或向后填充条件

假设我有这样一个数据帧:

df = pd.DataFrame({'col1':[1,np.nan,3, np.nan,5,np.nan], 
                     'col2':[7, np.nan, 9, np.nan, 11, np.nan], 
                     'col3':[13, 14, 15, 16, np.nan,18], 
                     'col4':[2015, 2015, 2015, 2016, 2016, 2018]}) 

   col1  col2  col3  col4
0   1.0   7.0  13.0  2015
1   NaN   NaN  14.0  2015
2   3.0   9.0  15.0  2015
3   NaN   NaN  16.0  2016
4   5.0  11.0   NaN  2016
5   NaN   NaN  18.0  2018

我正试图通过groupby实现这一点

grouped = df.groupby('col4')
然后我在组上循环,如果组名满足条件,我会进行填充(向后或向前)并更新数据帧

for name, group in grouped:
       if name == 2015:
              df[df.col4==name][['col1', 'col2']] = grouped.get_group(name)[['col1', 'col2']].ffill(axis=0)
       elif name == 2016: 
              df[df.col4==name]['col1'] = grouped.get_group(name)['col1'].ffill(axis=0)
              df[df.col4==name][['col2', 'col3']] = grouped.get_group(name)[['col1', 'col2']].bfill(axis=0)
       else: 
              df[df.col4==name]['col1', 'col2', 'col3'] = grouped.get_group(name)['col1'].bfill(axis=0)



但是,这不起作用,而且看起来很长。
看起来很像


如果您有任何建议,我将不胜感激。

您的问题不清楚。例如,您没有在循环中说明2018年。我们用它做什么。如果你只需要2015年和2016年。请试一试

m=df.col4 ==2015#Boolean select
df.loc[m,'col1':'col3']=df.loc[m,'col1':'col3'].fillna(method='ffill')#Forward Fill
df.loc[~m,'col1':'col3']=df.loc[~m,'col1':'col3'].fillna(method='bfill').fillna(method='ffill')



col1  col2  col3  col4
0   1.0   7.0  13.0  2015
1   1.0   7.0  14.0  2015
2   3.0   9.0  15.0  2015
3   5.0  11.0  16.0  2016
4   5.0  11.0  18.0  2016
5   5.0  11.0  18.0  2018

根据所有建议,我解决了这个问题如下:

for name, group in grouped:
       if name == 2015:
              df.loc[df.col4==name, ['col1', 'col2']] = grouped.get_group(name)[['col1', 'col2']].ffill(axis=0)
       elif name == 2016: 
              df.loc[df.col4==name, ['col1']] = grouped.get_group(name)['col1'].ffill(axis=0)
              df.loc[df.col4==name, ['col2', 'col3']] = grouped.get_group(name)[['col1', 'col2']].bfill(axis=0)
       else: 
              df[df.col4==name, ['col1', 'col2', 'col3']] = grouped.get_group(name)['col1'].bfill(axis=0)

你能编辑你的问题并把预期的结果放在那里吗?
df[df.col4==name][[col1',col2']
是索引链接,使用
df.loc[df.col4==name,['col1',col2']
代替。谢谢!你说得对,我增加了2018年的额外声明。事实上,我在col4中有很多值,这只是一个例子。这是一项调查,观察者在某些年份只填写起始值或结束值。这应该可以解释问题的背景。您的答案几乎是正确的,如果您对不同级别的分组变量(循环?)进行了更改,我将接受它为正确的。再次感谢你的帮助!请尝试
df[['col1','col2']]=df.groupby((df.col1.notna()| df.col2.notna()).cumsum())[['col1',col2']]].fillna(method='ffill')
。那么
col3
中的情况如何,即
NaN
。你的解释似乎没有抓住这一点。