【问题标题】:(pandas) Fill NaN based on groupby and column condition(pandas) 根据 groupby 和 column 条件填充 NaN
【发布时间】:2017-06-29 11:15:42
【问题描述】:

在 groupby 元素上使用 'bfill' 或 'ffill' 很简单,但是如果您需要根据第三列中的条件在第二列中用特定值填充 na 怎么办?

例如:

>>> df=pd.DataFrame({'date':['01/10/2017', '02/09/2017', '02/10/2016','01/10/2017', '01/11/2017', '02/10/2016'], 'a':[1,1,1,2,2,2], 'b':[4,np.nan,6, 5, np.nan, 7]})
>>> df
   a    b        date
0  1  4.0  01/10/2017
1  1  NaN  02/09/2017
2  1  6.0  02/10/2016
3  2  5.0  01/10/2017
4  2  NaN  01/11/2017
5  2  7.0  02/10/2016

我需要按“a”列分组,并用“b”列值填充 NaN,其中该行的日期最接近 NaN 行中的日期。

所以输出应该是这样的:

   a    b        date
0  1  4.0  01/10/2017
1  1  6.0  02/09/2017
2  1  6.0  02/10/2016
3  2  5.0  01/10/2017
4  2  5.0  01/11/2017
5  2  7.0  02/10/2016

假设有一个最接近日期() 函数,它获取 NaN 日期和该组中其他日期的列表,并返回最接近的日期。

我正在尝试找到一个无需遍历行的干净解决方案,理想情况下能够将 apply() 与 lambdas 一起使用。有什么想法吗?

【问题讨论】:

  • 您的数据似乎不正确。对于a == 1 组,您选择了6 来填写nan。但是,01/10/2017 似乎更接近 02/09/2017,这意味着 4 应该是填充值。

标签: python pandas group-by


【解决方案1】:

这应该可行:

df['closest_date_by_a'] = df.groupby('a')['date'].apply(closest_date)
df['b'] = df.groupby(['a', 'closest_date_by_a'])['b'].ffill().bfill()

给定一个函数 (closest_date()),您需要按组应用该函数,以便计算每个组中行的最接近日期。然后您可以按主分组列 (a) 和最近的日期列 (closest_date_by_a) 进行分组并执行填充。

【讨论】:

    【解决方案2】:

    确保您的 date 列实际上是日期。

    df = pd.DataFrame(
        {'date': ['01/10/2017', '02/09/2017', '02/10/2016','01/10/2017', '01/11/2017', '02/10/2016'],
         'a':[1,1,1,2,2,2], 'b':[4,np.nan,6, 5, np.nan, 7]})
    df.date = pd.to_datetime(df.date)
    
    print(df)
    
       a    b       date
    0  1  4.0 2017-01-10
    1  1  NaN 2017-02-09
    2  1  6.0 2016-02-10
    3  2  5.0 2017-01-10
    4  2  NaN 2017-01-11
    5  2  7.0 2016-02-10
    

    在拥有dropna() 之后使用reindexmethod='nearest'

    def fill_with_nearest(df):
        s = df.set_index('date').b
        s = s.dropna().reindex(s.index, method='nearest')
        s.index = df.index
        return s
    
    df.loc[df.b.isnull(), 'b'] = df.groupby('a').apply(fill_with_nearest).reset_index(0, drop=True)
    
    print(df)
    
       a    b       date
    0  1  4.0 2017-01-10
    1  1  4.0 2017-02-09
    2  1  6.0 2016-02-10
    3  2  5.0 2017-01-10
    4  2  5.0 2017-01-11
    5  2  7.0 2016-02-10
    

    【讨论】:

    • 感谢您的回答。我不知道“最近的”填充方法,这很整洁。我正在对我的数据尝试这种方法,它适用于几次迭代然后给出一个错误:ValueError: cannot reindex a non-unique index with a method or limit 知道什么会导致这种情况吗?我试图通过添加具有相同“日期”值的新行来重新创建示例中的错误,但它仍然可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多