Python Pandas 插值:在缺失的日期范围内重新分配值

Python Pandas interpolation: redistribute value forwards over missing date range

我有关于设施流量的时间趋势数据(随着时间的推移进入和释放设施),有差距。由于此数据的结构,当出现间隙时,间隙前一天的“释放”被人为地高(占间隙期间释放的所有看不见的个体),而后一天的“入场”差距被人为地拉高(出于同样的原因:任何在差距期间入院并留在设施中的人都将在该日期显示为“入院”)。

这是一个涉及此类数据差距的示例 Pandas 系列(零表示 2020-01-04 至 2020-01-07 的数据缺失):

date(index)    releases    admissions
2020-01-01     15          23
2020-01-02     8           20
2020-01-03     50          14
2020-01-04     0           0
2020-01-05     0           0
2020-01-06     0           0
2020-01-07     0           0
2020-01-08     8           100
2020-01-09     11          19
2020-01-10     9           17

此可视化(忽略对缺失总人口的单独线性插值)如下所示:

我想对这些数据进行平滑处理,但我不确定使用什么插值方法。我想要完成的是在日期 gap(0)-1 上重新分配“发布”,在日期 gap(n)+1 上重新分配“录取”。例如,如果间隔为 4 天,并且在 gap(n)+1 天有 100 个入场,我想重新分配这样,在间隔的每一天,有 20 个入场,在 gap(n) 天+1 录取修改为显示 20.

使用上面的示例系列,重新分配如下所示:

date(index)    releases    admissions
2020-01-01     15          23
2020-01-02     8           20
2020-01-03     10          14
2020-01-04     10          20
2020-01-05     10          20
2020-01-06     10          20
2020-01-07     10          20
2020-01-08     8           20
2020-01-09     11          19
2020-01-10     9           17

您可以创建具有连续零的组 + releases 之前的一个值和 admissions 之后的一个值,然后使用 transform('mean') 计算每个组的平均值:

# releases
df['releases'] = df.groupby(
    df['releases'].replace(0, np.nan).notna().cumsum()
)['releases'].transform('mean')

# admissions
df['admissions'] = df.groupby(
    df['admissions'].replace(0, np.nan).notna().iloc[::-1].cumsum().iloc[::-1]
)['admissions'].transform('mean')

输出:

            releases  admissions
date                            
2020-01-01        15          23
2020-01-02         8          20
2020-01-03        10          14
2020-01-04        10          20
2020-01-05        10          20
2020-01-06        10          20
2020-01-07        10          20
2020-01-08         8          20
2020-01-09        11          19
2020-01-10         9          17


更新: 为了保持现有的 NA 值:

# releases
df['releases_i'] = df.groupby(
    df['releases'].ne(0).cumsum()
)['releases'].transform('mean')

# admissions
df['admissions_i'] = df.groupby(
    df['admissions'].ne(0).iloc[::-1].cumsum().iloc[::-1]
)['admissions'].transform('mean')