如何在"熊猫""系列"中做"weighted upsampling"?



我在python中有一个函数,用于在上采样时分配值。例如,为了将我的车从每月行驶的距离增加到每天行驶的距离:

def distribute(df, freq:str):
# if there's an easier way please do comment
df_new = df.resample(freq).asfreq().fillna(0)
return df_new.groupby(pd.Grouper(freq=df.index.freq)).transform(np.mean)
import pandas as pd
import numpy as np
distances = pd.Series([300, 300], pd.period_range('2020-02', freq='M', periods=2))
distribute(distances, 'D')
2020-02-01    10.344828
2020-02-02    10.344828
2020-02-03    10.344828
2020-02-04    10.344828
...                 ...
2020-03-28     9.677419
2020-03-29     9.677419
2020-03-30     9.677419
2020-03-31     9.677419
Freq: D, dtype: float64

函数将每个月的值平均除以该月的天数,这将导致2020-02值除以29,2020-03值除以31,在这种情况下,根据需要。


然而,当上采样到周期具有非均匀持续时间的频率时,这会给我带来不想要的结果。具有此属性的两种情况:

  1. 年环比:
distances2 = pd.Series([366], pd.PeriodIndex(['2020'], freq='Y'))
distribute(distances2, 'M')
2020-01    30.5
2020-02    30.5
...         ...
2020-11    30.5
2020-12    30.5
Freq: M, dtype: float64

我想要的是将一年的价值除以几个月,每个月都会收到与其持续时间成比例的分数。即,我希望年份值在几个月内拆分为31/366 * x29/366 * x等:

2020-01    31
2020-02    29
...
2020-11    30
2020-12    31
Freq: M, dtype: float64

有办法做到这一点吗

  1. 夏令时

第二种情况是在DST转换中,它实际上已经在我的初始示例中显示了。2020-03-29比我所在时区的其他三月天短1小时,因此它实际上应该比其他日子收到的三月值的一小部分。

尽管这与情况1是同一类问题,但我怀疑它将更难解决。


EDIT:我找到了解决情况1的方法,但没有解决情况2;请看我在这个问题下面的回答。帮助仍然感谢改进我的回答,也包括第二种情况。


如果我们找到一种稳健的方法来做到这一点,并且有点细致,那么我可能会请求它(或者尝试通过pull请求自己添加它(,因为它似乎是一个很好的添加。因此,除了.ffill()sum().mean()等方法之外,扩展PeriodIndexResamplerapi以允许具有此功能的.distribute()方法。

作为部分的答案,为了解决问题1,我发现我可以首先向上采样到具有统一持续时间的较高频率周期,例如"D",然后向下采样到所需频率:

def distribute(df, freq:str):
# now it's really wild
df_D = df.resample('D').asfreq().fillna(0)
df_D_spread = df_D.groupby(pd.Grouper(freq=df.index.freq)).transform(np.mean)
return df_D_spread.groupby(pd.Grouper(freq=freq)).sum()
distances2 = pd.Series([366], pd.PeriodIndex(['2020'], freq='Y'))
distribute(distances2, 'M')
2020-01    31.0
2020-02    29.0
...         ...
2020-11    30.0
2020-12    31.0
Freq: M, dtype: float64

然而/备注:

  • 这本书很复杂,很难阅读。而且还浪费了大量的内存空间,将一年扩展到366或365行。一定有更好的方法吗?

  • 它没有解决第二个问题
    事实上,我选择了'D'而不是'H',因为时段不支持时区。事实上,并非所有的日子都是等长的,每当我们找到包含这一事实的方法时,我们可能需要更改代码以将采样提升到'H'(对于分数时区,甚至是'15T'(。

相关内容

  • 没有找到相关文章

最新更新