【问题标题】:Center datetimes of resampled time series重采样时间序列的中心日期时间
【发布时间】:2022-02-04 21:55:29
【问题描述】:

当我重新采样 Pandas 时间序列以减少数据点的数量时,每个结果数据点的时间戳位于每个重新采样箱的开头。当使用不同的重采样率对图形进行重叠绘制时,这会导致数据明显偏移。无论重采样率如何,如何将重采样数据的时间戳“居中”在其 bin 中?

我现在得到的是(重新采样到一小时时):

In [12]: d_r.head()
Out[12]: 
2017-01-01 00:00:00    0.330567
2017-01-01 01:00:00    0.846968
2017-01-01 02:00:00    0.965027
2017-01-01 03:00:00    0.629218
2017-01-01 04:00:00   -0.002522
Freq: H, dtype: float64

我想要的是:

In [12]: d_r.head()
Out[12]: 
2017-01-01 00:30:00    0.330567
2017-01-01 01:30:00    0.846968
2017-01-01 02:30:00    0.965027
2017-01-01 03:30:00    0.629218
2017-01-01 04:30:00   -0.002522
Freq: H, dtype: float64

MWE 显示明显偏移:

#!/usr/bin/env python3
Minimal working example:

import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
import seaborn
seaborn.set()

plt.ion()

# sample data
t = pd.date_range('2017-01-01 00:00', '2017-01-01 10:00', freq='1min')
d = pd.Series(np.sin(np.linspace(0, 7, len(t))), index=t)


d_r = d.resample('1h').mean()

d.plot()
d_r.plot()

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我一般不知道如何使用中点。有label 参数,但只有rightleft 选项。但是,在具体情况下,您可以使用loffset-参数显式偏移重新采样的时间戳:

    d.resample('1h', loffset='30min').mean()
    

    (编辑:使用30min 而不是30T,因为这样更具可读性:http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases

    【讨论】:

    • loffset 可以工作,但这并不理想,因为我将重新采样到几个不同的比例(每分钟、每小时、每天),并且我必须手动指定每个偏移量。
    【解决方案2】:

    loffset 关键字参数似乎很快就会被弃用。

    在我看来,我所知道的最好的方法如下:

    d_r = d.shift(0.5, freq='1h').resample('1h').mean()
    

    与使用 loffset 关键字相比,它的优点是生成的时间戳是完整的时间。

    【讨论】:

      【解决方案3】:

      将 30 分钟与 timedelta 添加到索引中怎么样?

      df.index = df.index + datetime.timedelta(minutes=30)
      

      【讨论】:

        【解决方案4】:

        matthme 的解决方案是一个很好的解决方案,但它并不能解决 resample 的主要问题,即时间标签始终由选择用于重采样的 rule 分隔(在您的情况下为 1 小时),而这如果持续时间不是rule 的整数倍,可能会导致时间序列开始和/或结束时出现错误的时间标签。

        您可以做的最好的事情是平均您的时间序列并将结果用作时间标签(即您的 DataFrame 的索引)。不幸的是,resample 方法无法对datetime 对象进行操作,因此您必须将其转换为timestamp,将平均值应用于重新采样的DataFrame,并将timestamp 转换回datetime。这将自动将时间标签置于您的时间分箱间隔内,并在时间序列的开始和结束时调整标签。在这种情况下无需换档。

        一个工作示例:

        import pandas as pd
        from matplotlib import pyplot as plt
        import numpy as np
        
        
        t = pd.date_range('2017-01-01 00:00', '2017-01-01 10:00', freq='1min')
        timestamp = t.astype('int64') // 10**9  # covert datetime to timestamp in seconds
        d = pd.DataFrame({'datetime': t,
                          'timestamp': timestamp,
                          'd': np.sin(np.linspace(0, 7, len(t)))}, 
                         index=t)
        t_avg = '1h'
        
        d_r = d.shift(0.5, freq=t_avg).resample(t_avg).mean()
        
        d_r2 = d.resample(t_avg).mean()
        d_r2.index = pd.to_datetime(d_r2['timestamp'], unit='s')
        
        
        fig, ax = plt.subplots()
        ax.plot(d['datetime'], d['d'], label='unsampled')
        ax.plot(d_r.index, d_r['d'], 'o', label='shifted resample')
        ax.plot(d_r2.index, d_r2['d'], 'D', label='time average resample')
        plt.legend()
        fig.autofmt_xdate()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-26
          • 2021-12-31
          • 2014-07-24
          • 2013-01-09
          • 2017-02-20
          • 2020-12-28
          • 1970-01-01
          相关资源
          最近更新 更多