【问题标题】:pandas ffil and bfill conditional on groupby熊猫 ffil 和 bfill 以 groupby 为条件
【发布时间】:2020-11-04 19:01:36
【问题描述】:

col1col2col3 的每一列都需要以 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)



但是这不起作用并且看起来很冗长。
This post 看起来很相似。

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

【问题讨论】:

  • 你能编辑你的问题并把预期的结果放在那里吗?
  • df[df.col4==name][['col1', 'col2']] 是索引链接,请改用df.loc[df.col4==name,['col1', 'col2']]

标签: python pandas dataframe


【解决方案1】:

你的问题不清楚。例如,您没有在循环中考虑 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

【讨论】:

  • 谢谢!你是对的,我为2018添加了一个额外的声明。实际上我在col4中有很多值,这只是一个例子。这是一项调查,观察者在某些年份只填写了起始值或结束值。这应该解释问题的背景。您的答案几乎是正确的,如果您进行更改以考虑不同级别的分组变量(循环?),我将接受它作为正确的答案。再次感谢您的帮助!
  • 请尝试df[['col1', 'col2']]=df.groupby((df.col1.notna()|df.col2.notna()).cumsum())[['col1', 'col2']].fillna(method='ffill') 这正如您所解释的。 col3也就是NaN的情况怎么样。您的解释中似乎没有体现这一点。
【解决方案2】:

根据所有建议,我解决了以下问题:

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2013-10-24
    • 2013-06-06
    • 2019-01-18
    • 2020-09-08
    • 2023-01-31
    相关资源
    最近更新 更多