轉換的思路是這樣的,以日曆中的周進行聚合,如 '20180702'-'20180708',取該周期內,日線開盤價的第一個值作為周開盤價,日線最高價的最大值作為周最高價,日線最低價的最小值作為周最低價,日線收盤價的最後一個值作為周最收盤價,日線最高價的最大值作為周最高價,日線成交量的求和作為周成交量(手),如下圖黃色方框所示。
我們可以通過 .resample()【4】方法實現上述操作,對 DataFrame 和 Series 都適用。其中,參數 rule 設置需要轉換成的頻率,'1W' 是一周。
具體轉換的代碼如下,日期默認為本周的星期日,如果周期內數據不全,如 '20180722' 這周只有 3 行數據,也會按照上述方法進行轉換。
freq = '1W'
df_weekly = df[['open']].resample(rule=freq).first()
df_weekly['high'] = df['high'].resample(rule=freq).max()
df_weekly['low'] = df['low'].resample(rule=freq).min()
df_weekly['close'] = df['close'].resample(rule=freq).last()
df_weekly['vol'] = df['vol'].resample(rule=freq).sum()
df_weekly
Out[33]:
open high low close vol
trade_date
2018-07-08 9.05 9.05 8.45 8.66 5125563.53
2018-07-15 8.69 9.03 8.58 8.88 4901983.84
2018-07-22 8.85 8.90 8.66 8.70 1590354.68
升採樣:以周線數據轉換日線數據為例。繼續使用上面剛剛轉換好的周線數據,我們再試著把它轉換成日線數據。先通過 .resample('D').asfreq()【5】方法,將周線數據的頻率轉換成日線,效果如下。
df_daily = df_weekly.resample('D').asfreq()
print(df_daily)
Out[52]:
open high low close vol
trade_date
2018-07-08 9.05 9.05 8.45 8.66 5125563.53
2018-07-09 NaN NaN NaN NaN NaN
2018-07-10 NaN NaN NaN NaN NaN
2018-07-11 NaN NaN NaN NaN NaN
2018-07-12 NaN NaN NaN NaN NaN
2018-07-13 NaN NaN NaN NaN NaN
2018-07-14 NaN NaN NaN NaN NaN
2018-07-15 8.69 9.03 8.58 8.88 4901983.84
2018-07-16 NaN NaN NaN NaN NaN
2018-07-17 NaN NaN NaN NaN NaN
2018-07-18 NaN NaN NaN NaN NaN
2018-07-19 NaN NaN NaN NaN NaN
2018-07-20 NaN NaN NaN NaN NaN
2018-07-21 NaN NaN NaN NaN NaN
2018-07-22 8.85 8.90 8.66 8.70 1590354.68
結果中出現了很多空值,需要我們按照一定的方法進行填充,可以通過添加 .ffill() 或者 .bfill() 實現。
其中,.ffill() 代表用前值進行填充,也就是用前面的非空值對後面的 NaN 值進行填充,如 '20180709'-20180714' 的 NaN 值都等於 '20180708' 這一行的非空值,效果如下。
df_daily = df_weekly.resample('D').ffill()
df_daily
Out[54]:
open high low close vol
trade_date
2018-07-08 9.05 9.05 8.45 8.66 5125563.53
2018-07-09 9.05 9.05 8.45 8.66 5125563.53
2018-07-10 9.05 9.05 8.45 8.66 5125563.53
2018-07-11 9.05 9.05 8.45 8.66 5125563.53
2018-07-12 9.05 9.05 8.45 8.66 5125563.53
2018-07-13 9.05 9.05 8.45 8.66 5125563.53
2018-07-14 9.05 9.05 8.45 8.66 5125563.53
2018-07-15 8.69 9.03 8.58 8.88 4901983.84
2018-07-16 8.69 9.03 8.58 8.88 4901983.84
2018-07-17 8.69 9.03 8.58 8.88 4901983.84
2018-07-18 8.69 9.03 8.58 8.88 4901983.84
2018-07-19 8.69 9.03 8.58 8.88 4901983.84
2018-07-20 8.69 9.03 8.58 8.88 4901983.84
2018-07-21 8.69 9.03 8.58 8.88 4901983.84
2018-07-22 8.85 8.90 8.66 8.70 1590354.68
同理,.bfill() 代表用後值對空值進行填充,效果如下。
df_daily = df_weekly.resample('D').bfill()
df_daily
Out[55]:
open high low close vol
trade_date
2018-07-08 9.05 9.05 8.45 8.66 5125563.53
2018-07-09 8.69 9.03 8.58 8.88 4901983.84
2018-07-10 8.69 9.03 8.58 8.88 4901983.84
2018-07-11 8.69 9.03 8.58 8.88 4901983.84
2018-07-12 8.69 9.03 8.58 8.88 4901983.84
2018-07-13 8.69 9.03 8.58 8.88 4901983.84
2018-07-14 8.69 9.03 8.58 8.88 4901983.84
2018-07-15 8.69 9.03 8.58 8.88 4901983.84
2018-07-16 8.85 8.90 8.66 8.70 1590354.68
2018-07-17 8.85 8.90 8.66 8.70 1590354.68
2018-07-18 8.85 8.90 8.66 8.70 1590354.68
2018-07-19 8.85 8.90 8.66 8.70 1590354.68
2018-07-20 8.85 8.90 8.66 8.70 1590354.68
2018-07-21 8.85 8.90 8.66 8.70 1590354.68
2018-07-22 8.85 8.90 8.66 8.70 1590354.68
03
時間窗口函數
當我們想要比較數據在相同時間窗口的不同特徵和變化時,可以藉助窗口函數 rolling【6】進行計算。
看一個實例:計算股票收盤價的移動平均值。
df = df[['ts_code', 'close']]
df
Out[58]:
ts_code close
trade_date
2018-07-02 000001.SZ 8.61
2018-07-03 000001.SZ 8.67
2018-07-04 000001.SZ 8.61
2018-07-05 000001.SZ 8.60
2018-07-06 000001.SZ 8.66
2018-07-09 000001.SZ 9.03
2018-07-10 000001.SZ 8.98
2018-07-11 000001.SZ 8.78
2018-07-12 000001.SZ 8.88
2018-07-13 000001.SZ 8.88
2018-07-16 000001.SZ 8.73
2018-07-17 000001.SZ 8.72
2018-07-18 000001.SZ 8.70
調用 rolling 函數,通過設置參數 window 的值規定窗口大小,這裡設置為 3,並且調用 .mean() 方法計算窗口期為 3 天的均值,結果如下。
其中,'20180704' 當天的平均值等於 '20180702'-'20180704' 三天的收盤價取平均的結果,'20180705' 當天的平均值等於 '20180703'-'20180705' 三天的收盤價取平均的結果,以此類推。
df['MA3'] = df['close'].rolling(3).mean()
df
Out[76]:
ts_code close MA3
trade_date
2018-07-02 000001.SZ 8.61 NaN
2018-07-03 000001.SZ 8.67 NaN
2018-07-04 000001.SZ 8.61 8.630000
2018-07-05 000001.SZ 8.60 8.626667
2018-07-06 000001.SZ 8.66 8.623333
2018-07-09 000001.SZ 9.03 8.763333
2018-07-10 000001.SZ 8.98 8.890000
2018-07-11 000001.SZ 8.78 8.930000
2018-07-12 000001.SZ 8.88 8.880000
2018-07-13 000001.SZ 8.88 8.846667
2018-07-16 000001.SZ 8.73 8.830000
2018-07-17 000001.SZ 8.72 8.776667
2018-07-18 000001.SZ 8.70 8.716667
還有一個常用的窗口函數是 expanding,每增加一行數據,窗口會相應的增大。比如,我們想計算某隻股票每天的累計漲跌幅,就可以調用此函數。
df = df[['ts_code', 'pct_chg']] # 列pct_chg單位是(%)
Out[71]:
ts_code pct_chg
trade_date
2018-07-02 000001.SZ -5.28
2018-07-03 000001.SZ 0.70
2018-07-04 000001.SZ -0.69
2018-07-05 000001.SZ -0.12
2018-07-06 000001.SZ 0.70
2018-07-09 000001.SZ 4.27
2018-07-10 000001.SZ -0.55
2018-07-11 000001.SZ -2.23
2018-07-12 000001.SZ 2.78
2018-07-13 000001.SZ 0.00
2018-07-16 000001.SZ -1.69
2018-07-17 000001.SZ -0.11
2018-07-18 000001.SZ -0.23
對列 'pct_chg' 調用窗口函數 expanding,再調用 .sum() 方法求累計值。
df['cum_pct_chg'] = df['pct_chg'].expanding().sum()
df
Out[78]:
ts_code pct_chg cum_pct_chg
trade_date
2018-07-02 000001.SZ -5.28 -5.28
2018-07-03 000001.SZ 0.70 -4.58
2018-07-04 000001.SZ -0.69 -5.27
2018-07-05 000001.SZ -0.12 -5.39
2018-07-06 000001.SZ 0.70 -4.69
2018-07-09 000001.SZ 4.27 -0.42
2018-07-10 000001.SZ -0.55 -0.97
2018-07-11 000001.SZ -2.23 -3.20
2018-07-12 000001.SZ 2.78 -0.42
2018-07-13 000001.SZ 0.00 -0.42
2018-07-16 000001.SZ -1.69 -2.11
2018-07-17 000001.SZ -0.11 -2.22
2018-07-18 000001.SZ -0.23 -2.45
04
總結
本文介紹了 Pandas 庫中處理時間序列數據的幾種常用方法。
在時間格式轉換部分,介紹了兩種將時間轉化成日期類型的方法,分別是通過設置參數 parse_dates 和調用方法 pd.to_datetime() 。
接著,介紹了時間周期的轉換,通過調用 .resample() 方法實現,包括降採樣和升採樣。
最後,介紹兩個常用的窗口函數 rolling 和 expanding 。
希望大家能靈活掌握本文中提到的方法,並應用到實際工作和學習中去!
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html【1】
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html【2】
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.set_index.html【3】
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.resample.html【4】
http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.asfreq.html【5】
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rolling.html【6】
http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.expanding.html【7】
https://www.datacamp.com/courses/manipulating-time-series-data-in-python【Datacamp】
----End----
Python數據之道
據說學Python的只有10%的人關注了這個號,
還有很大潛力
今日主題:時序數據處理,聊聊遇到的坑~
留言格式:暱稱 + day xx + 留言內容(字數不少於15字)
歡迎各位同學加入公眾號讀者分享交流群,在公眾號後臺回復 「微信群」 即可。
同學們,支持就請右下角點!