问题:使用熊猫 - 如何有效地用零值填充缺失的日期,每月(例如最后一天索引(频率,相对于每组的最小/最大日期值?
编辑不要假定输入日期对应于其月份的最后一天。 要解决此问题,请在下面的建议答案中添加以下行:
df.date = df.date + pd.offsets.MonthEnd(0)
如果没有此修复,用 freq='M' 填充值可能会导致 NA's...!
注意: 熊猫版本 0.24.2
示例输入:
data = [{'name': 'A', 'date': '2019-01-01', 'val': 10},
{'name': 'A', 'date': '2019-04-30', 'val': 2},
{'name': 'B', 'date': '2019-02-15', 'val': 6},
{'name': 'B', 'date': '2019-05-01', 'val': 5}]
df = pd.DataFrame(data)
date name val
0 2019-01-01 A 10
1 2019-04-30 A 2
2 2019-02-15 B 6
3 2019-05-01 B 5
请注意,输入中的日期不一定是其相应月份的第一天或最后一天。
所需输出示例
date name val
0 2019-01-31 A 10
1 2019-02-28 A 0
2 2019-03-31 A 0
3 2019-04-30 A 2
4 2019-02-28 B 6
5 2019-03-31 B 0
6 2019-04-30 B 0
7 2019-05-31 B 5
尝试:
以下内容在索引级别工作,但用 NA 填充所有内容:
df['date'] = pd.to_datetime(df['date'])
dg = df.groupby('name').apply(lambda x: x.reindex(pd.date_range(min(x.date), max(x.date), freq='M')))
也:
熊猫填充组中缺少的日期和值
上述链接的答案似乎不是相对于每个组,而是整个数据集的最小/最大日期值。
我会使用groupby
,resample
和asfreq
(编辑:当您在非月末日期更新问题时。我按照您的建议添加了pd.offsets.MonthEnd
(
df.date = df.date + pd.offsets.MonthEnd(0)
(df.set_index('date').groupby('name').resample('M')
.asfreq(fill_value=0).drop('name',1)
.reset_index())
Out[550]:
name date val
0 A 2019-01-31 10
1 A 2019-02-28 0
2 A 2019-03-31 0
3 A 2019-04-30 2
4 B 2019-02-28 6
5 B 2019-03-31 0
6 B 2019-04-30 0
7 B 2019-05-31 5
一个快速修复:
df.date = pd.to_datetime(df.date)
new_df = (df.set_index('date')
.groupby('name', as_index=False)
.apply(lambda x: x.resample('M').interpolate())
.reset_index(0, drop=True)
)
s = new_df['name'].isna()
new_df.loc[s, 'val'] = 0
new_df['name'] = new_df['name'].ffill()
输出:
name val
date
2019-01-31 A 10.0
2019-02-28 A 0.0
2019-03-31 A 0.0
2019-04-30 A 2.0
2019-02-28 B 6.0
2019-03-31 B 0.0
2019-04-30 B 0.0
2019-05-31 B 5.0