没有重采样的时间序列的 Pandas 子集
Posted
技术标签:
【中文标题】没有重采样的时间序列的 Pandas 子集【英文标题】:Pandas Subset of a Time Series Without Resampling 【发布时间】:2018-06-15 17:25:27 【问题描述】:我有一个 pandas 数据系列,其中包含一个系列的每日累积回报:
Date CumReturn
3/31/2017 1
4/3/2017 .99
4/4/2017 .992
... ...
4/28/2017 1.012
5/1/2017 1.011
... ...
5/31/2017 1.022
... ...
6/30/2017 1.033
... ...
我只想要月末值。
Date CumReturn
4/28/2017 1.012
5/31/2017 1.022
6/30/2017 1.033
因为我只想要月末值,所以重采样不起作用,因为它聚合了中间值。
仅获取原始数据框中显示的月末值的最简单方法是什么?
【问题讨论】:
可以使用 pandas.tseries.offsets.MonthEnd 吗? 我该怎么做?我对时间序列的操作有点犹豫。 这里有很好的记录:pandas.pydata.org/pandas-docs/stable/timeseries.html 类似这样的东西:from pandas.tseries.offsets import MonthEnd df['EndOfMonth'] = pd.to_datetime(df['Date'], format="%m/%d/%Y") + MonthEnd(1)
其中 MonthEnd(1) 指定在下一个月末日期递增一
感谢您参考文档。在发布问题之前我确实看过它,但它似乎没有回答我的问题。如果我正确理解您的评论,我会使用偏移量得出一个或一系列月末值,然后使用它来获取数据框的子集?
执行上述操作将为您获取每个日期的 EndOfMonth,因此您需要进行子集化以仅保留 Date=EndOfMonth 的记录
【参考方案1】:
使用.dt
date accessor 的is_month_end
组件:
# Ensure the date column is a Timestamp
df['Date'] = pd.to_datetime(df['Date'])
# Filter to end of the month only
df = df[df['Date'].dt.is_month_end]
将此应用于您提供的数据:
Date CumReturn
0 2017-03-31 1.000
5 2017-05-31 1.022
6 2017-06-30 1.033
编辑
要获得营业月结,请使用BMonthEnd(0)
进行比较:
from pandas.tseries.offsets import BMonthEnd
# Ensure the date column is a Timestamp
df['Date'] = pd.to_datetime(df['Date'])
# Filter to end of the month only
df = df[df['Date'] == df['Date'] + BMonthEnd(0)]
将此应用于您提供的数据:
Date CumReturn
0 2017-03-31 1.000
3 2017-04-28 1.012
5 2017-05-31 1.022
6 2017-06-30 1.033
【讨论】:
谢谢。你能提供一个文件参考吗?我在搜索中没有遇到这种情况。 @Windstorm1981:请参阅我的答案中的链接。如果你想要 business 月底,is_month_end
将不起作用。
是的,这可能有问题。我真正需要的是某种方法来对数据框进行子集化,每月获取最大日期。那是因为这是业务数据,一些月末日期在周末。我可以按月对数据框进行子集化并循环获取最大值,但似乎应该有一种更简单的方法。我刚刚看到第二个答案(下)。虽然不太优雅,但它可能是解决我的特定问题的更好方法。
我添加了一个解决方案来获得业务月结。如果您真正关心的是每个月的 max 日期,无论是月末、营业月末还是两者都不是,请使用@Evan 的解决方案。请在以后更准确地表述您的问题。
这真是太好了。我将删除我的答案; pandas 的行为值得注意,但解决方案不正确。【参考方案2】:
df.sort_values('Date').groupby([df.Date.dt.year,df.Date.dt.month]).last()
Out[197]:
Date CumReturn
Date Date
2017 3 2017-03-31 1.000
4 2017-04-28 1.012
5 2017-05-31 1.022
6 2017-06-30 1.033
【讨论】:
这真是太好了。我将删除我的答案; pandas 的行为值得注意,但解决方案不正确。【参考方案3】:假设数据框已经按“日期”排序,并且该列中的值是 Pandas 时间戳,您可以将它们转换为 YYYY-mm 字符串值进行分组并取最后一个值:
df.groupby(df['Date'].dt.strftime('%Y-%m'))['CumReturn'].last()
# Example output:
# 2017-01 0.127002
# 2017-02 0.046894
# 2017-03 0.005560
# 2017-04 0.150368
【讨论】:
以上是关于没有重采样的时间序列的 Pandas 子集的主要内容,如果未能解决你的问题,请参考以下文章
Python 之 Pandas 生成时间戳范围Pandas 的时期函数 Period() 和时间序列 - 重采样 resample