繁体   English   中英

Pandas:在给定时间(例如每一天)对插值时间序列数据进行采样的更简单方法

[英]Pandas: easier way to sample interpolated time series data at given times (e.g. every full day)

我经常遇到的问题是我有时间序列数据,我想在给定时间进行插值和重新采样。 我有一个解决方案,但感觉就像“劳动密集型”,例如我想应该有一个更简单的方法。 Have a look for how I currently do it here: https://gist.github.com/cs224/012f393d5ced6931ae223e6ddc4fe6b2 (or the nicer version via nbviewer here: https://nbviewer.org/gist/cs224/012f393d5ced6931ae223e6ddc4fe6b2 )

也许是一个鼓舞人心的例子:我大约每两周给我的车加满油。 我有每个笔芯的成本数据。 现在我想知道每天的累积总和,其中日值是在午夜并插值。

目前,我创建了一个新的空数据框,其中包含我想要重新采样的值的时间点:

df_sampling = pd.DataFrame(index=pd.date_range(start, end, freq=freq))

然后要么使用pd.merge

ldf = pd.merge(df_in, df_sampling, left_index=True, right_index=True, how='outer')

pd.concat

ldf = pd.concat([df_in, df_sampling], axis=1)

创建在索引中具有附加时间点的组合时间序列。 基于此,我可以使用pd.interpolate然后子选择 df_sampling 给出的所有索引值。 有关详细信息,请参阅要点。

这一切都感觉太麻烦了,我想应该有更好的方法来做到这一点。

我不会在 function generate_interpolated_time_series中使用mergeconcat ,而是依赖df.reindex 像这样的东西:

def f(df_in, freq='T', start=None):
    if start is None:
        start = df_in.index[0].floor('T')
        # refactored: df_in.index[0].replace(second=0,microsecond=0,nanosecond=0)
    end = df_in.index[-1]
    idx = pd.date_range(start=start, end=end, freq=freq)
    ldf = df_in.reindex(df_in.index.union(idx)).interpolate().bfill()
    ldf = ldf[~ldf.index.isin(df_in.index.difference(idx))]
    return ldf

测试样品:

from pandas import Timestamp

d = {Timestamp('2022-10-07 11:06:09.957000'): 21.9,
 Timestamp('2022-11-19 04:53:18.532000'): 47.5,
 Timestamp('2022-11-19 16:30:04.564000'): 66.9,
 Timestamp('2022-11-21 04:17:57.832000'): 96.9,
 Timestamp('2022-12-05 22:26:48.354000'): 118.6}

df = pd.DataFrame.from_dict(d, orient='index', columns=['values'])

print(df)

                         values
2022-10-07 11:06:09.957    21.9
2022-11-19 04:53:18.532    47.5
2022-11-19 16:30:04.564    66.9
2022-11-21 04:17:57.832    96.9
2022-12-05 22:26:48.354   118.6

检查相等性:

merge = generate_interpolated_time_series(df, freq='D', method='merge')
concat = generate_interpolated_time_series(df, freq='D', method='concat')
reindex = f(df, freq='D')

print(all([merge.equals(concat),merge.equals(reindex)]))
# True

额外的奖励将是一些性能提升。 在这里,您可以看到针对不同频率( ['D','H','T','S'] )的 3 种方法(应用%timeit )的比较结果。 绿色的reindex对于每个都是最快的。

比较


另外:在您的 function 中, raise Exception('Method unknown: ' + metnhod)包含一个错字; 应该是method

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM