微信公衆號:「Python讀財」
如有問題或建議,請公衆號留言
進行金融數據分析或量化研究時,總避免不了時間序列數據的處理,時間序列是指在一定時間內按時間順序測量的某個變量的取值序列。常見的時間序列數據有一天內隨着時間變化的溫度序列,又或者交易時間內不斷波動的股票價格序列。Pandas也因其強大的時序處理能力而被廣泛應用於金融數據分析,這篇文章爲大家介紹一下Pandas中的時間序列處理,所使用的數據是上證指數2019年的行情數據。
時間相關的數據類型
Pandas時序處理中最常見的兩種數據類型爲datetime
和timedelta
。一個datetime
可以如下圖所示:
datetime
顧名思義就是既有日期date
也有時間time
,表示一個具體的時間點(時間戳)。timedelta
則表示兩個時間點之間的差,比如2020-01-01
和2020-01-02
之間的timedelta
即爲一天,相信並不難理解。
將時間列轉換爲時間格式
大多數時候,我們是從csv
文件中導入數據,此時Dataframe
中對應的時間列是字符串的形式,如下:
In [5]: data.trade_date.head()
Out[5]:
0 20190102
1 20190103
2 20190104
3 20190107
4 20190108
Name: trade_date, dtype: object
運用pd.to_datetime()
,可以將對應的列轉換爲Pandas中的datetime64
類型,便於後期的處理
In [11]: data["trade_date"] = pd.to_datetime(data.trade_date)
In [12]: data.trade_date.head()
Out[12]:
0 2019-01-02
1 2019-01-03
2 2019-01-04
3 2019-01-07
4 2019-01-08
Name: trade_date, dtype: datetime64[ns]
時間序列的索引
時間序列中索引和Pandas普通的索引類似,大多時候調用.loc[index,columns]
進行相應的索引,直接上代碼看看
In [20]: data1 = data.set_index("trade_date")
# 2019年6月的數據
In [21]: data1.loc["2019-06"].head()
Out[21]:
close open high low
trade_date
2019-06-03 2890.0809 2901.7424 2920.8292 2875.9019
2019-06-04 2862.2803 2887.6405 2888.3861 2851.9728
2019-06-05 2861.4181 2882.9369 2888.7676 2858.5719
2019-06-06 2827.7978 2862.3327 2862.3327 2822.1853
2019-06-10 2852.1302 2833.0145 2861.1310 2824.3554
# 2019年6月-2019年8月的數據
In [22]: data1.loc["2019-06":"2019-08"].tail()
Out[22]:
close open high low
trade_date
2019-08-26 2863.5673 2851.0158 2870.4939 2849.2381
2019-08-27 2902.1932 2879.5154 2919.6444 2879.4060
2019-08-28 2893.7564 2901.6267 2905.4354 2887.0115
2019-08-29 2890.9192 2895.9991 2898.6046 2878.5878
2019-08-30 2886.2365 2907.3825 2914.5767 2874.1028
提取出時間/日期的屬性
在時序數據處理過程中,經常需要實現下述需求:
- 求某個日期對應的星期數(2019-06-05是第幾周)
- 判斷一個日期是周幾(2020-01-01是周幾)
- 判斷某一日期是第幾季度(2019-07-08屬於哪個季度)
……
當你數據中的時間列(本數據中爲trade_date
列)已經轉換爲datetime64
格式時,僅需調用.dt
接口,即可快速求得想要的結果,下表中列出了.dt
接口所提供的常見屬性:
具體演示一下(下面僅顯示2019-01-02的信息):
# 一年中的第幾天
In [13]: data.trade_date.dt.dayofweek[0]
Out[13]: 2
# 返回對應日期
In [14]: data.trade_date.dt.date[0]
Out[14]: datetime.date(2019, 1, 2)
# 返回週數
In [15]: data.trade_date.dt.weekofyear[0]
Out[15]: 1
# 返回周幾
In [16]: data.trade_date.dt.weekday_name[0]
Out[16]: 'Wednesday'
resample
resample
翻譯過來是重採樣的意思,官方文檔中是這麼描述resample
的
resample()
is a time-based groupby
翻譯過來就是基於時間的groupby
操作,我個人認爲這是Pandas時間序列處理中最重要的功能,也是本文的重中之重。
根據採樣是從低頻到高頻還是從高頻到低頻可以分爲升採樣和降採樣兩種方式,先來看看降採樣是啥
- 降採樣
以一個實例來引入,我們使用的數據是上證指數2019年的日級別數據,如果現在想求每季度的平均收盤價,應該怎麼操作呢?
從日級別數據求季度級別數據,是從高頻到低頻的聚合操作,其實就類似於groupby
按季度進行操作,用resample
來寫是這樣子
In [32]: data.resample('Q',on='trade_date')["close"].mean()
Out[32]:
trade_date
2019-03-31 2792.941622
2019-06-30 3010.354672
2019-09-30 2923.136748
2019-12-31 2946.752270
Freq: Q-DEC, Name: close, dtype: float64
其中'Q'
是以季度爲頻率進行採樣,on
指定datetime列
(如果索引爲Datetimeindex
,則on
不需要指定,默認依據索引進行降採樣)。整個過程圖解如下:
整個過程其實就是一個groupby
過程:
- 對原有的數據按照指定的頻率進行切分,分到不同的
group
中 - 對不同的
group
執行操作 - 整合操作結果
其中,切分的頻率可以爲任何時間頻率,可以爲季度Q
、月度M
、星期W
、N天ND
,也可以爲時H
、分T
,當然,如果切分後的頻率小於原有的時間頻率,就是我們下面要講的升採樣。
- 升採樣
當採樣的頻率低於原有的頻率時,即爲升採樣。升採樣是對原有的時間粒度更爲細粒度的劃分,所以升採樣時會產生缺失值。下面取2019-01-02
至2019-01-03
的數據按照6H
的頻率演示一下:
In [24]: example
Out[24]:
close
trade_date
2019-01-02 2465.2910
2019-01-03 2464.3628
In [25]: example.resample('6H').asfreq()
Out[25]:
close
trade_date
2019-01-02 00:00:00 2465.2910
2019-01-02 06:00:00 NaN
2019-01-02 12:00:00 NaN
2019-01-02 18:00:00 NaN
2019-01-03 00:00:00 2464.3628
對resample
後的結果應用.asfreq()
會返回新頻率下的結果。可以看到升採樣後產生了缺失值。如果想要填充缺失值可以採用向後填充.bfill()
或向前填充.ffill()
的方式:
# 向前填充,缺失值取2465.2910進行填充
In [29]: example.resample('6H').ffill()
Out[29]:
close
trade_date
2019-01-02 00:00:00 2465.2910
2019-01-02 06:00:00 2465.2910
2019-01-02 12:00:00 2465.2910
2019-01-02 18:00:00 2465.2910
2019-01-03 00:00:00 2464.3628
# 向後填充,缺失值取2464.3628進行填充
In [30]: example.resample('6H').bfill()
Out[30]:
close
trade_date
2019-01-02 00:00:00 2465.2910
2019-01-02 06:00:00 2464.3628
2019-01-02 12:00:00 2464.3628
2019-01-02 18:00:00 2464.3628
2019-01-03 00:00:00 2464.3628
總結一下resample
,resample
可以對原有的時間序列進行任何頻率freq
的採樣,如果從低頻到高頻爲升採樣,高頻到低頻爲降採樣。整個操作過程和groupby
基本一致,所以也可以對resample
後的對象進行apply
和transform
等操作,具體操作和原理這裏就不多解釋了,類比於groupby
即可,參看這篇文章Pandas數據分析——超好用的Groupby詳解
。
掃碼關注公衆號 「Python讀財」,第一時間獲取乾貨!