(pandas) 根据 groupby 和 column 条件填充 NaN

Posted

技术标签:

【中文标题】(pandas) 根据 groupby 和 column 条件填充 NaN【英文标题】:(pandas) Fill NaN based on groupby and column condition 【发布时间】: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 应该是填充值。 【参考方案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 知道什么会导致这种情况吗?我试图通过添加具有相同“日期”值的新行来重新创建示例中的错误,但它仍然可以正常工作。

以上是关于(pandas) 根据 groupby 和 column 条件填充 NaN的主要内容,如果未能解决你的问题,请参考以下文章

Pandas - dataframe groupby - 如何获得多列的总和

Pandas 的 [df.groupby(...)['col_name'].shift(1)] 的 SQL 等效项

pyspark 相当于 pandas groupby('col1').col2.head()

在groupby之后访问pandas中的分层列

Pandas Groupby 列并获得频率为 0

pandas groupby对象中n和n + 1行之间的平均值?