python - 如何在`pandas``Series`中进行“加权上采样”?
问题描述
我在 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。
但是,当上采样到周期具有不均匀持续时间的频率时,这会给我带来不想要的结果。此属性的两种情况:
- 逐月:
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
我想要的是将一年的价值划分为几个月,每个月都会收到与其 duration 成比例的分数。31/366 * x
即,我希望将年份值拆分为,29/366 * x
等月份:
2020-01 31
2020-02 29
...
2020-11 30
2020-12 31
Freq: M, dtype: float64
有没有办法做到这一点?
- 夏令时
第二种情况是在 DST 转换中,它实际上已经在我的初始示例中显示。2020-03-29
比我的时区中的其他三月天短 1 小时,因此它实际上应该比其他天收到更小的三月值。
尽管它与情况 1 是同一类型的问题,但我怀疑它会更难解决。
编辑:我找到了解决情况 1 的方法,但不是情况 2;在这个问题下面看到我的答案。在改进我的答案以及包括第二种情况方面仍然感谢帮助。
如果我们找到了一种稳健的方法来做这件事,但它有点详细,我可能是一个很好的请求功能(或者尝试通过拉取请求自己添加它),因为它似乎是一个很好的补充。因此,扩展PeriodIndexResampler
api 以允许.distribute()
具有此功能的方法,除了.ffill()
,sum()
等.mean()
方法。
解决方案
作为部分答案,为了解决问题 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'
对于分数时区)。
推荐阅读
- c++ - Nested template class method syntax
- javascript - 如何在创建新元素时更新变量的内容
- r - 逆回归后的模型拟合和残差的逐步前向拟合
- micronaut - 运行 MicronautTest 时如何将应用程序上下文加载到 MicronautLambdaContainerHandler 中?
- php - 选择电子邮件并在返回的电子邮件数量上插入新行另一个表 PHP MYSQL
- python - 从 Angular 项目向 Python 服务器发送 POST 或 GET 请求
- api - 试图让 NoteResultSpec 示例工作
- mysql - 我的 sql order by - 错误代码:1064。您的 SQL 语法有错误;
- javascript - 如何在reactjs中重置模态状态
- html - 如何将html样式标签提取到css中