Pandas的asfreq方法使用中漏掉了什么

1 投票
1 回答
1691 浏览
提问于 2025-04-18 08:56

考虑以下代码:

    r = pandas.date_range(datetime(2014,5,26),datetime(2014,6,6))
    ts = pandas.Series(np.random.randn(len(r)), index=r)
    print(ts.asfreq(pandas.DateOffset(days=5),how='end'))

我觉得我对“how”这个参数的用法理解得不太对。根据上面的代码,我本以为从最后开始,asfreq的结果会每5天返回一次。但我得到的结果是:

2014-05-26    0.456856
2014-05-31   -0.552287
2014-06-05    0.169554
Freq: <DateOffset: kwds={'days': 5}>, dtype: float64

如果我这样做:

    print(ts.asfreq(pandas.DateOffset(days=5),how='start'))

结果完全没有变化,还是得到了同样的结果。

然后我看到在pandas.Series.asfreq的文档中提到:

how : {‘start’, ‘end’}, default end
    For PeriodIndex only, see PeriodIndex.asfreq

这让我意识到我的问题在于我需要使用DatetimeIndex。

我的问题是,在我的例子中,如何正确调用才能始终返回一个系列,最后一点是2014-05-30,范围的结束日期是2014-06-06,无论我在范围中设置的开始日期是什么?asfreq似乎不适用于降序索引,所以反转索引似乎也不是一个选项……

1 个回答

1

针对你的问题,这里有几个需要注意的地方:

首先,我不太明白在这里使用 DateOffset 的意义,你可以直接用 "5D" 来替代,这样得到的结果是一样的。

其次,使用 period_range 来生成时间索引会更好。第三点后面会给出一个例子。

最后,似乎你不太明白当使用 "how" 选项时 asfreq 的作用。简单来说,当 asfreq 里的 "freq" 设置为更大的频率(或者更小的时间间隔)时,就会用到 "how" 选项。下面我用一个例子来说明:

import pandas as pd
import numpy as np
rng = pd.period_range('20140526','20140606')

如果我把频率设置为 "start":

print(rng.asfreq('H', how='start'))

结果是:

PeriodIndex(['2014-05-26 00:00', '2014-05-27 00:00', '2014-05-28 00:00',
         '2014-05-29 00:00', '2014-05-30 00:00', '2014-05-31 00:00',
         '2014-06-01 00:00', '2014-06-02 00:00', '2014-06-03 00:00',
         '2014-06-04 00:00', '2014-06-05 00:00', '2014-06-06 00:00'],
        dtype='int64', freq='H')

所有的小时都被设置为那一天的 00:00。

但是,如果 "how" 设置为 "end"

print(rng.asfreq('H', how='end'))

结果就变成:

PeriodIndex(['2014-05-26 23:00', '2014-05-27 23:00', '2014-05-28 23:00',
         '2014-05-29 23:00', '2014-05-30 23:00', '2014-05-31 23:00',
         '2014-06-01 23:00', '2014-06-02 23:00', '2014-06-03 23:00',
         '2014-06-04 23:00', '2014-06-05 23:00', '2014-06-06 23:00'],
        dtype='int64', freq='H')

所有的小时都被设置为 23:00,也就是说,每一天的最后一个小时的时间戳。

所以这里的重点是:只有当新的频率(小时)大于旧的频率(天)时,"how" 才有用。但在这种情况下,你并不是在对时间序列进行子集或重采样,而是根据新的频率给每个时间点一个新的索引。

至于如何实现你的目标,既然你已经标记了所有重要的时间点,为什么不使用这些时间点来创建一个周期索引呢:

r = pd.period_range('20140530','20140609',freq="5D")
print(r)
PeriodIndex(['2014-05-30', '2014-06-04', '2014-06-09'], dtype='int64', freq='5D')

撰写回答