我知道如何将groupby方法与ffill或bfill一起使用以估算缺少的值。但是我的问题是,我需要首先在“日期”列中找到与“得分”列中的空值最接近的日期,如果分数列中的值不为空,则用该值进行插补。如果该值为空,则需要搜索另一个最近的日期。我可以遍历行并执行此操作,但是速度非常慢。
这是数据的示例:
df = pd.DataFrame(
{'cn': [1, 1, 1, 1, 2, 2, 2],
'date': ['01/10/2017', '02/09/2016', '02/10/2016','01/20/2017', '05/15/2019', '02/10/2016', '02/10/2017'],
'score': [np.nan, np.nan, 6, 5, 4, np.nan, 8]})
cn date score
0 1 01/10/2017 NaN
1 1 02/09/2016 NaN
2 1 02/10/2016 6
3 1 01/20/2017 5
4 2 05/15/2019 4
5 2 02/10/2016 NaN
6 2 02/10/2017 8.0
输出应为
cn date score
0 1 01/10/2017 5
1 1 02/09/2016 6
2 1 02/10/2016 6
3 1 01/20/2017 5
4 2 05/15/2017 4
5 2 02/10/2016 8
6 2 02/10/2018 8
如何使用groupby方法和apply函数来做到这一点?
答案 0 :(得分:5)
使用pd.merge_asof
获得最接近的系列,然后仅.fillna
。有一些操作可以确保最后对齐索引。
import pandas as pd
df['date'] = pd.to_datetime(df.date)
s = (pd.merge_asof(
df.sort_values('date').reset_index(), # Full Data Frame
df.sort_values('date').dropna(subset=['score']), # Subset with valid scores
by='cn', # Only within `'cn'` group
on='date', direction='nearest' # Match closest date
)
.set_index('index')
.score_y)
df['score'] = df.score.fillna(s, downcast='infer')
df
cn date score
0 1 2017-01-10 5
1 1 2016-02-09 6
2 1 2016-02-10 6
3 1 2017-01-20 5
4 2 2019-05-15 4
5 2 2016-02-10 8
6 2 2017-02-10 8