Pandas 为缺失的日期填零 *由 * 组定义

Posted

技术标签:

【中文标题】Pandas 为缺失的日期填零 *由 * 组定义【英文标题】:Pandas fill-in-zero for by missing dates *defined by* group 【发布时间】:2020-01-26 05:05:06 【问题描述】:

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

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

df.date = df.date + pd.offsets.MonthEnd(0) 

如果不进行此修复,使用 freq='M' 填充的值可能会导致 NA ......!

注意: 熊猫版本 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')))

还有:

Pandas filling missing dates and values within group

上述链接的答案似乎与每个组无关,而是与整个数据集的最小/最大日期值有关。

【问题讨论】:

【参考方案1】:

一个快速修复:

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

【讨论】:

似乎使用“interpolate”有时会(在大型数据集上)导致最终输出具有所有 NA——将“interpolate”更改为“max”似乎可以解决这个问题。 为了安全地使用“resample('M')”,添加以下行:df.date = df.date + pd.offsets.MonthEnd(0)【参考方案2】:

我会使用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

【讨论】:

为了安全地使用“resample('M')”,添加以下行:df.date = df.date + pd.offsets.MonthEnd(0) @Quetzalcoatl:啊,我明白你的意思了。您想处理 df.date 中的某些值不是月末日期的异常情况 :) @Quetzalcoatl:我添加了pd.offsets.MonthEnd,因为您建议完成答案:) @AndyL.:您如何为每个组添加相同的日期范围?我的意思是每个组都有相同的范围(即 2020 年 1 月到 2020 年 12 月)。你会怎么做?

以上是关于Pandas 为缺失的日期填零 *由 * 组定义的主要内容,如果未能解决你的问题,请参考以下文章

将 pandas 列转换为 datetime64,包括缺失值

pandas使用reindex函数为日期索引中有缺失日期的dataframe进行索引重置(所有日期都连续)并使用fill_value参数为行进行默认填充

pandas使用read_csv函数读取文件并解析日期数据列(parse dates)pandas使用read_csv函数读取文件并将缺失值转化为空字符串

填补 MultiIndex Pandas Dataframe 中的日期空白

Python:为每个组填充缺失的日期

根据 max 和 min 填写缺失的日期 pandas