1. 程式人生 > >(資料科學學習手札99)掌握pandas中的時序資料分組運算

(資料科學學習手札99)掌握pandas中的時序資料分組運算

> 本文示例程式碼及檔案已上傳至我的`Github`倉庫[https://github.com/CNFeffery/DataScienceStudyNotes](https://github.com/CNFeffery/DataScienceStudyNotes) # 1 簡介   我們在使用`pandas`分析處理時間序列資料時,經常需要對原始時間粒度下的資料,按照不同的時間粒度進行分組聚合運算,譬如基於每個交易日的股票收盤價,計算每個月的最低和最高收盤價。   而在`pandas`中,針對不同的應用場景,我們可以使用`resample()`、`groupby()`以及`Grouper()`來非常高效快捷地完成此類任務。
圖1
# 2 在pandas中進行時間分組聚合   在`pandas`中根據具體任務場景的不同,對時間序列進行分組聚合可通過以下兩類方式實現: ## 2.1 利用resample()對時序資料進行分組聚合   `resample`原始的意思是**重取樣**,可分為**上取樣**與**下采樣**,而我們通常情況下使用的都是**下采樣**,也就是從高頻的資料中按照一定規則計算出更低頻的資料,就像我們一開始說的對每日資料按月彙總那樣。   如果你熟悉`pandas`中的`groupby()`分組運算,那麼你就可以很快地理解`resample()`的使用方式,它本質上就是在對時間序列資料進行“分組”,最基礎的引數為`rule`,用於設定按照何種方式進行重取樣,就像下面的例子那樣: ```Python import pandas as pd # 記錄了2013-02-08到2018-02-07之間每個交易日蘋果公司的股價 AAPL = pd.read_csv('AAPL.csv', parse_dates=['date']) # 以月為統計視窗計算每月股票最高收盤價 ( AAPL .set_index('date') # 設定date為index .resample('M') # 以月為單位 .agg({ 'close': ['max', 'min'] }) ) ```
圖2
  可以看到,在上面的例子中,我們對index為日期時間型別的`DataFrame`應用`resample()`方法,傳入的引數`'M'`是`resample`第一個位置上的引數`rule`,用於確定時間視窗的規則,譬如這裡的字串`'M'`就代表**月且聚合結果中顯示對應月的最後一天**,常用的固化的時間視窗規則如下表所示: | 規則 | 說明 | | :----: | :----------------------: | | W | 星期 | | M | 月,顯示為當月最後一天 | | MS | 月,顯示為當月第一天 | | Q | 季度,顯示為當季最後一天 | | QS | 季度,顯示為當季第一天 | | A | 年,顯示為當年最後一天 | | AS | 年,顯示為當年第一天 | | D | 日 | | H | 小時T | | T或min | 分鐘 | | S | 秒 | | L或 ms | 毫秒 |   且這些規則都可以在前面新增數字實現倍數效果: ```Python # 以6個月為統計視窗計算每月股票平均收盤價且顯示為當月第一天 ( AAPL .set_index('date') # 設定date為index .resample('6MS') # 以6個月為單位 .agg({ 'close': 'mean' }) ) ```
圖3
  且`resample()`非常貼心之處在於它會自動幫你對齊到規整的時間單位上,譬如我們這裡只有交易日才會有記錄,如果我們設定的時間單位下無對應記錄,也會為你保留帶有缺失值記錄的時間點: ```Python ( AAPL .set_index('date') # 設定date為index .resample('1D') # 以1日為單位 .agg({ 'close': 'mean' }) ) ```
圖4
  而通過引數`closed`我們可以為細粒度的時間單位設定區間閉合方式,譬如我們以2日為單位,將`closed`設定為`'right'`時,從第一行記錄開始計算所落入的時間視窗時,其對應為時間視窗的右邊界,從而影響後續所有時間單元的劃分方式: ```Python ( AAPL .set_index('date') # 設定date為index .resample('2D', closed='right') .agg({ 'close': 'mean' }) ) ```
圖5
  而即使你的資料框`index`不是日期時間型別,也可以使用引數`on`來傳入日期時間列名實現同樣的效果。 ## 2.2 利用groupby()+Grouper()實現混合分組   有些情況下,我們不僅僅需要利用時間型別列來分組,也可能需要包含時間型別在內的多個列共同進行分組,這種情況下我們就可以使用到`Grouper()`。   它通過引數`freq`傳入等價於`resample()`中`rule`的引數,並利用引數`key`指定對應的時間型別列名稱,但是可以幫助我們建立分組規則後傳入`groupby()`中: ```Python # 分別對蘋果與微軟每月平均收盤價進行統計 ( pd .read_csv('AAPL&MSFT.csv', parse_dates=['date']) .groupby(['Name', pd.Grouper(freq='MS', key='date')]) .agg({ 'close': 'mean' }) ) ```
圖6
  且在此種混合分組模式下,我們可以非常方便的配合`apply`、`transform`等操作,這裡就不再贅述。 ---   以上就是本文的全部內容,歡迎在評論區與我進