我在熊猫数据框中有一组计算的OHLCVA每日证券数据,如下所示:
>>> type(data_dy)
>>> data_dy
Open High Low Close Volume Adj Close
Date
2012-12-28 140.64 141.42 139.87 140.03 148806700 134.63
2012-12-31 139.66 142.56 139.54 142.41 243935200 136.92
2013-01-02 145.11 146.15 144.73 146.06 192059000 140.43
2013-01-03 145.99 146.37 145.34 145.73 144761800 140.11
2013-01-04 145.97 146.61 145.67 146.37 116817700 140.72
[5 rows x 6 columns]
我正在使用以下字典和pandas resample函数将数据框转换为每月数据:
>>> ohlc_dict = {'Open':'first','High':'max','Low':'min','Close': 'last','Volume': 'sum','Adj Close': 'last'}
>>> data_dy.resample('M', how=ohlc_dict, closed='right', label='right')
Volume Adj Close High Low Close Open
Date
2012-12-31 392741900 136.92 142.56 139.54 142.41 140.64
2013-01-31 453638500 140.72 146.61 144.73 146.37 145.11
[2 rows x 6 columns]
这样可以正确进行计算,但是我想使用Yahoo! 日期约定,用于使用该时段的第一个交易日而不是熊猫使用的时段的最后一个日历日。
所以我希望答案是:
Volume Adj Close High Low Close Open
Date
2012-12-28 392741900 136.92 142.56 139.54 142.41 140.64
2013-01-02 453638500 140.72 146.61 144.73 146.37 145.11
我可以通过将每日数据转换为python列表,处理数据并将数据返回到数据框来做到这一点,但是如何用熊猫来做到这一点呢?
代替M,您可以传递MS作为重采样规则:
df =pd.DataFrame( range(72), index = pd.date_range('1/1/2011', periods=72, freq='D'))
#df.resample('MS', how = 'mean') # pandas <0.18
df.resample('MS').mean() # pandas >= 0.18
更新为使用尊重美国联邦假日的月份的第一个工作日:
df =pd.DataFrame( range(200), index = pd.date_range('12/1/2012', periods=200, freq='D'))
from pandas.tseries.offsets import CustomBusinessMonthBegin
from pandas.tseries.holiday import USFederalHolidayCalendar
bmth_us = CustomBusinessMonthBegin(calendar=USFederalHolidayCalendar())
df.resample(bmth_us).mean()
如果您想使用数据中的最小月份自定义月份的开始时间,请尝试此操作。 (它不是很漂亮,但是应该可以)。
month_index =df.index.to_period('M')
min_day_in_month_index = pd.to_datetime(df.set_index(new_index, append=True).reset_index(level=0).groupby(level=0)['level_0'].min())
custom_month_starts =CustomBusinessMonthBegin(calendar = min_day_in_month_index)
将custom_start_months传递给resample的第一参数
谢谢,我没有意识到此选项。但是,这将导致月份开始日期,而不是数据中该月份的最早日期。参见此处:>>> data_dy.resample(MS,how = ohlc_dict)数量调整收盘价高收盘价开盘价2012-12-01 392741900 136.92 142.56 139.54 142.41 140.64 2013-01-01 453638500 140.72 146.61 144.73 146.37 145.11 [2行x 6列]
我还在这里找到了示例重采样选项的列表:stackoverflow.com/questions/17001389/。
尝试BMS选项会产生:>>> data_dy.resample(BMS,how = ohlc_dict)成交量收盘高低低开盘日期2012-12-03 392741900 136.92 142.56 139.54 142.41 140.64 2013-01-01 453638500 140.72 146.61 144.73 146.37 145.11仍然不完全是我想要的。
我不清楚2012-12-28代表什么?哪个时期的第一天?
最初的问题似乎要求该月的第一个交易日。它是否正确?您的评论使我不这么认为。
不好意思,对不起。在我的示例中,我仅列出了被截断的数据,但是在被截断的数据集中,这意味着2012年12月的第一个交易日(显然不是真实情况)。我已经计算了非美国市场的数据,因此每个月的第一个交易日因市场而异,具体取决于当地的假期。如果返回的日期是每个月中第一个数据行的日期,并对其他列使用字典规则,则将是最灵活的。
如果您按月创建数据中第一个日期的时间序列索引,并将它们传递给CustomBusinessMonthBegin中的calendar参数,则此方法应该起作用。
@J_Bradley感谢您的耐心和专业知识。我将尝试此解决方案。
@ user2766344不客气。更新以使用索引中的最小日期创建时间序列索引。可能有一种更优雅的方式来执行此操作,但我不知道。
谢谢J Bradley,您的解决方案效果很好。我确实必须从其官方网站升级我的熊猫版本,因为通过pip安装的版本在pandas.tseries.offsets中没有CustomBusinessMonthBegin。我的最终代码是:
#----- imports -----
import pandas as pd
from pandas.tseries.offsets import CustomBusinessMonthBegin
import pandas.io.data as web
#----- get sample data -----
df = web.get_data_yahoo('SPY', '2012-12-01', '2013-12-31')
#----- build custom calendar -----
month_index =df.index.to_period('M')
min_day_in_month_index = pd.to_datetime(df.set_index(month_index, append=True).reset_index(level=0).groupby(level=0)['Open'].min())
custom_month_starts = CustomBusinessMonthBegin(calendar = min_day_in_month_index)
#----- convert daily data to monthly data -----
ohlc_dict = {'Open':'first','High':'max','Low':'min','Close': 'last','Volume': 'sum','Adj Close': 'last'}
mthly_ohlcva = df.resample(custom_month_starts, how=ohlc_dict)
这产生了以下内容:
>>> mthly_ohlcva
Volume Adj Close High Low Close Open
Date
2012-12-03 2889875900 136.92 145.58 139.54 142.41 142.80
2013-01-01 2587140200 143.92 150.94 144.73 149.70 145.11
2013-02-01 2581459300 145.76 153.28 148.73 151.61 150.65
2013-03-01 2330972300 151.30 156.85 150.41 156.67 151.09
2013-04-01 2907035000 154.20 159.72 153.55 159.68 156.59
2013-05-01 2781596000 157.84 169.07 158.10 163.45 159.33
2013-06-03 3533321800 155.74 165.99 155.73 160.42 163.83
2013-07-01 2330904500 163.78 169.86 160.22 168.71 161.26
2013-08-01 2283131700 158.87 170.97 163.05 163.65 169.99
2013-09-02 2226749600 163.90 173.60 163.70 168.01 165.23
2013-10-01 2901739000 171.49 177.51 164.53 175.79 168.14
2013-11-01 1930952900 176.57 181.75 174.76 181.00 176.02
2013-12-02 2232775900 181.15 184.69 177.32 184.69 181.09
AttributeError: Index object has no attribute to_period-有什么解决办法吗?
我已经在上一版的熊猫中看到,可以使用时间偏移别名" BMS"(代表"工作月开始频率")或" BM"(代表"工作月结束频率")。
第一种情况下的代码如下所示
data_dy.resample('BMS', closed='right', label='right').apply(ohlc_dict)
或者,在第二种情况下,
data_dy.resample('BM', closed='right', label='right').apply(ohlc_dict)
听起来不错,但即使使用df.index = pd.to_datetime(df.index, format=%Y-%m-%d, errors=ignore),也会出现错误:TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, but got an instance of Index。也许有人有解决方案?