熊猫通过缺少的日期*定义*组填充零



问题:使用熊猫 - 如何有效地用零值填充缺失的日期,每月(例如最后一天索引(频率,相对于每组的最小/最大日期值?

编辑不要假定输入日期对应于其月份的最后一天。 要解决此问题,请在下面的建议答案中添加以下行:

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')))

也:

熊猫填充组中缺少的日期和值

上述链接的答案似乎不是相对于每个组,而是整个数据集的最小/最大日期值。

我会使用groupbyresampleasfreq(编辑:当您在非月末日期更新问题时。我按照您的建议添加了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

最新更新