一、生成日期范圍的時序數據
pd.date_range()可用於生成指定長度的日期索引,默認產生按天計算的時間點(即日期范圍)。其參數可以是:
- 起始結束日期
- 或者是僅有一個起始或結束日期,加上一個時間段參數
以下三種方法結果一致:
- pd.date_range('20200801','20200810')
- pd.date_range(start='20200801',periods=10)
- pd.date_range(end='20200810',periods=10)
結果:
DatetimeIndex(['2020-08-01', '2020-08-02', '2020-08-03', '2020-08-04',
'2020-08-05', '2020-08-06', '2020-08-07', '2020-08-08',
'2020-08-09', '2020-08-10'],
dtype='datetime64[ns]', freq='D')
注意:此處的freq參數表示時間序列數據的頻率,其值為D,表示是以天為頻率;
所以,若想生成一個特殊頻率的日期索引,若一個由每月最后一個工作日組成的日期索引,直接加上參數freq='BM'(BM表示business end of month)
>>> pd.date_range('2020-01-01','2020-12-31',freq='BM')
DatetimeIndex(['2020-01-31', '2020-02-28', '2020-03-31', '2020-04-30',
'2020-05-29', '2020-06-30', '2020-07-31', '2020-08-31',
'2020-09-30', '2020-10-30', '2020-11-30', '2020-12-31'],
dtype='datetime64[ns]', freq='BM')
二、日期頻率
pandas中的頻率是由一個基礎頻率和一個乘數組成。基礎頻率通常以一個字符串別名表示,如'M','H'。
| 別名 | 偏移量類型 | 說明 |
| D | Day | 每日歷日 |
| B | BusinessDay | 每工作日 |
| H | Hour | 每小時 |
| T或min | Minute | 每分 |
| M | MonthEnd | 每月最后一個日歷日 |
| BM | BusinessMonthEnd | 每月最后一個工作日 |
| WOM-1MON | WeekOfMonth | 產生每月第一、第二、第四周的星期幾,如WOM-3FRI表示每月第3個周五 |
| Q-JAN | QuarterEnd | 對於指定月份(JAN、FEB、MAR...DEC)結束的年度,每季度最后一個月的最后一個日歷日 |
| A-JAN | YearEnd | 對於指定年份的最后一個日歷日 |
例:從2020年1月至2020年3月以'3M'的頻率生成一個時間范圍
>>> pd.date_range('2020-01-01','2020-12-31',freq='3M')
DatetimeIndex(['2020-01-31', '2020-04-30', '2020-07-31', '2020-10-31'], dtype='datetime64[ns]', freq='3M')
>>> pd.date_range('2020-01-01','2020-12-31',freq='WOM-3FRI')
DatetimeIndex(['2020-01-17', '2020-02-21', '2020-03-20', '2020-04-17',
'2020-05-15', '2020-06-19', '2020-07-17', '2020-08-21',
'2020-09-18', '2020-10-16', '2020-11-20', '2020-12-18'],
dtype='datetime64[ns]', freq='WOM-3FRI')
>>> pd.date_range('2020-01-01',periods=3,freq='2H30T')
DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 02:30:00',
'2020-01-01 05:00:00'],
dtype='datetime64[ns]', freq='150T')
對於每個基礎頻率,都有一個日期偏移量(date offset)對象與之對應。可以通過實例化日期偏移量來創建某種頻率:
>>> from pandas.tseries.offsets import Hour,Minute >>> hour = Hour() >>> hour <Hour> >>> four_hours = Hour(4) >>> four_hours <4 * Hours>
大部分偏移量對象可以通過加法進行連接:
>>> Hour(3)+Minute(20) <200 * Minutes>
有些頻率所描述的時間點並不是均勻分隔的。例如'M'和'BM'就取決於每月的天數,對於后者,還要考慮月末是否是周末,將這些成為錨點偏移量。
三、移動(超前或之后)數據
(1)移動(Shifting)指的是沿着時間軸將數據向前或向后移動,保持索引不變。
thift()方法默認表示索引不變數據后移;若提供freq參數,則此時將移動index,數據將保持不變
#創建一個時序數據
>>> ts = pd.Series(np.random.randint(0,10,5))
>>> ts.index = pd.date_range('2020-1-1',periods=5,freq='M')
>>> ts
2020-01-31 8
2020-02-29 5
2020-03-31 3
2020-04-30 9
2020-05-31 4
Freq: M, dtype: int32
#索引不變,數據向后移2個單位
>>> ts.shift(2)
2020-01-31 NaN
2020-02-29 NaN
2020-03-31 8.0
2020-04-30 5.0
2020-05-31 3.0
Freq: M, dtype: float64
#索引不變,數據向前移2個單位
>>> ts.shift(-2)
2020-01-31 3.0
2020-02-29 9.0
2020-03-31 4.0
2020-04-30 NaN
2020-05-31 NaN
Freq: M, dtype: float64
#將時間索引向后移2個月,數據保持不變
>>> ts.shift(2,freq='M')
2020-03-31 8
2020-04-30 5
2020-05-31 3
2020-06-30 9
2020-07-31 4
Freq: M, dtype: int32
#將時間索引向前移2個月,數據保持不變
>>> ts.shift(-2,freq='M')
2019-11-30 8
2019-12-31 5
2020-01-31 3
2020-02-29 9
2020-03-31 4
(2)如何通過偏移量對日期進行位移?
在時間后直接加上一個實例化的日期偏移量即可。
>>> from pandas.tseries.offsets import Day,MonthEnd
>>> from datetime import datetime
>>> t = datetime(2020,8,8)
>>> t + 10*Day()
Timestamp('2020-08-18 00:00:00')
#第一次位移量沒有一個月那么長,則位移就在當月,所以此時進行2個位移的結果是9月
>>> t + 2*MonthEnd()
Timestamp('2020-09-30 00:00:00')
(3)結合錨點偏移量,使用rollforward()和rollback()方法,可以將日期向前或向后滾動
>>> from pandas.tseries.offsets import MonthEnd,YearEnd,QuarterEnd
>>> offset = MonthEnd()
>>> t
datetime.datetime(2020, 8, 8, 0, 0)
#向前滾動
>>> offset.rollforward(t)
Timestamp('2020-08-31 00:00:00')
#向后滾動
>>> offset.rollback(t)
Timestamp('2020-07-31 00:00:00')
>>> offset1 = YearEnd()
>>> offset1.rollback(t)
Timestamp('2019-12-31 00:00:00')
>>> offset1.rollforward(t)
Timestamp('2020-12-31 00:00:00')
>>> offset2 = QuarterEnd()
>>> offset2.rollforward(t)
Timestamp('2020-09-30 00:00:00')
四、例子
若有以下時間序列,如何在每月月末顯示該月數據的均值?
>>> import pandas as pd >>> import numpy as np >>> ts = pd.Series(np.random.randint(0,10,10)) >>> ts.index = pd.date_range(start='2020-1-15',periods=10,freq='10D') >>> ts 2020-01-15 7 2020-01-25 1 2020-02-04 8 2020-02-14 7 2020-02-24 1 2020-03-05 3 2020-03-15 6 2020-03-25 8 2020-04-04 6 2020-04-14 1 Freq: 10D, dtype: int32
解法步驟:
- 先將時間序列使用rollforward()向前滾動,這樣將日期索引都設置為當前月的最后一天;
- 使用groupby()對時間索引進行分組聚合,求其均值
>>> from pandas.tseries.offsets import MonthEnd >>> offset = MonthEnd() #方法一:使用列表推導式將時間序列向后滾動至當前月的最后一天,再將生成的列表轉換成DatetimeIndex >>> ts.index = pd.to_datetime([offset.rollforward(index) for index in ts.index]) >>> ts 2020-01-31 7 2020-01-31 1 2020-02-29 8 2020-02-29 7 2020-02-29 1 2020-03-31 3 2020-03-31 6 2020-03-31 8 2020-04-30 6 2020-04-30 1 dtype: int32 #使用Groupby()聚合分組 >>> ts.groupby(ts.index).mean() 2020-01-31 4.000000 2020-02-29 5.333333 2020-03-31 5.666667 2020-04-30 3.500000 dtype: float64 #方法二:以下結果與上述結果一致 >>> ts.groupby(offset.rollforward).mean() 2020-01-31 4.000000 2020-02-29 5.333333 2020-03-31 5.666667 2020-04-30 3.500000 dtype: float64
上述兩種方法的區別是方法一改變了ts,方法二沒有;若在使用過程中,若想使用方法一又不想改變ts的值,可以先復制一個ts,然后對復制后的ts進行操作即可。
