時間索引
data = pd.to_datetime(['2019-11-12','2019.11.13','2019-11-14'])
print(data)
DatetimeIndex(['2019-11-12', '2019-11-13', '2019-11-14'], dtype='datetime64[ns]', freq=None)
在pd.to_datetime()中傳入一個表示時間日期的對象,則生成Timestamp對象,如果傳入時刻數據組成的序列,則生成DatetimeIndex類型的索引對象。那週期的數據類型Period對象組成的序列是不是PeriodIndex類型的索引對象呢:
data = [pd.Period('2019-11'),pd.Period('2019-12'),pd.Period('2020-1')]
data1 = pd.Series(np.linspace(100,200,3),index=data)
print(data1.index)
PeriodIndex(['2019-11', '2019-12', '2020-01'], dtype='period[M]', freq='M')
不僅如此,Pandas還提供了一個將DatetimeIndex索引對象轉換爲PeriodIndex索引對象的方法:
data = pd.to_datetime(['2019-11-12','2019.11.13','2019-11-14'])
period_index = data.to_period('D') #D(day)表示天的意思
print(data)
print(period_index)
DatetimeIndex(['2019-11-12', '2019-11-13', '2019-11-14'], dtype='datetime64[ns]', freq=None)
PeriodIndex(['2019-11-12', '2019-11-13', '2019-11-14'], dtype='period[D]', freq='D')
通過to.period()方法,並且在參數中聲明freq週期的單位,就可以轉換爲PeriodIndex索引對象。
那就可以看看時間間隔Timedelta有沒有對應的索引對象。
data = pd.to_datetime(['2019-11-12','2019.11.13','2019-11-14'])
data1 = data[0]
delte_index = data - data1
print(delte_index)
TimedeltaIndex(['0 days', '1 days', '2 days'], dtype='timedelta64[ns]', freq=None)
也是可以的。
總結:
時刻在Pandas中用Timestamp對象表示,可以構建DatetimeIndex索引對象。
週期用Period表示,可以構建PeriodIndex索引對象。
時間間隔用Timedelta,可以構建TimedeltaIndex索引對象。
很多時候需要一串連續的時間,類似於np.arange(),這裏我們可以使用pd.date_range(),pd.period_range(),pd.timedelta_range生成三種索引對象。
print(pd.date_range('2019-1','2019-11'))
print(pd.period_range('2019-1','2019-11'))
print(pd.timedelta_range('2019-1','2019-11'))
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
'2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
'2019-01-09', '2019-01-10',
...
'2019-10-23', '2019-10-24', '2019-10-25', '2019-10-26',
'2019-10-27', '2019-10-28', '2019-10-29', '2019-10-30',
'2019-10-31', '2019-11-01'],
dtype='datetime64[ns]', length=305, freq='D')
PeriodIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
'2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08',
'2019-01-09', '2019-01-10',
...
'2019-10-23', '2019-10-24', '2019-10-25', '2019-10-26',
'2019-10-27', '2019-10-28', '2019-10-29', '2019-10-30',
'2019-10-31', '2019-11-01'],
dtype='period[D]', length=305, freq='D')
TimedeltaIndex(['-1 days +23:59:59.999979'], dtype='timedelta64[ns]', freq='D')
爲什麼顯示輸出的是按照日單位輸出的呢,這裏可以查看幫助文檔:
date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None, **kwargs)
表面上看這freq=None實際上它是默認爲D的也就是天爲單位,如果要改爲月的話如下:
print(pd.date_range('2019-1','2019-11',freq='M'))
DatetimeIndex(['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30',
'2019-05-31', '2019-06-30', '2019-07-31', '2019-08-31',
'2019-09-30', '2019-10-31'],
dtype='datetime64[ns]', freq='M')
這個就是按照月單位輸出,而且是月底,再觀察一下參數中的periods,它的作用就是設置即將生成的DatetimeIndex對象的時刻數量,可不是之前那個PeriodIndex對象:
print(pd.date_range('2019-1',freq='M',periods=6))
DatetimeIndex(['2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30',
'2019-05-31', '2019-06-30'],
dtype='datetime64[ns]', freq='M')
之後具體的pdperiod_range()和pd.timedelta_range()的使用方法其實是差不多的參考幫助文檔:
period_range(start=None, end=None, periods=None, freq=None, name=None)
timedelta_range(start=None, end=None, periods=None, freq=None, name=None, closed=None)
print(pd.period_range('2019-1',freq='M',periods=6))
PeriodIndex(['2019-01', '2019-02', '2019-03', '2019-04', '2019-05', '2019-06'], dtype='period[M]', freq='M')
print(pd.timedelta_range('2019-1',periods=6))
TimedeltaIndex(['-1 days +23:59:59.999979', '0 days 23:59:59.999979',
'1 days 23:59:59.999979', '2 days 23:59:59.999979',
'3 days 23:59:59.999979', '4 days 23:59:59.999979'],
dtype='timedelta64[ns]', freq='D')
frep這個參數表示的是週期單位,下面來幾個仔細一點的案例:
print(pd.timedelta_range('2019-1',periods=6,freq='1H20T'))
TimedeltaIndex(['-1 days +23:59:59.999979', '01:19:59.999979',
'02:39:59.999979', '03:59:59.999979',
'05:19:59.999979', '06:39:59.999979'],
dtype='timedelta64[ns]', freq='80T')
上面那個freq傳入的參數的意思就是每次增加1個小時20分鐘,注意上面freq不能傳W,M不然會報錯。
重採樣
採樣的意思就是從大量數據中獲取一部分的數據,在這裏面就有個resample(),這個方法的基本功能就是重採樣,這個是Series與DataFrame對象的方法。
a = pd.date_range('2019-1',periods=100,freq='D')
b = pd.Series(np.random.randn(len(a)),index=a)
print(b.resample('M').mean())
2019-01-31 -0.129872
2019-02-28 -0.031885
2019-03-31 -0.261258
2019-04-30 -0.056611
Freq: M, dtype: float64
上面的操作中通過index=a這個方法將b這個Series對象的索引變爲a,範圍就是2019-1-31往後100天之內,a設定了它的頻率爲日(’D‘),也可以到時候改爲月(‘M’),後面因爲每個月數據量還是很多的,所以可以通過帶mean()方法,計算出每個月數據的平均值。
就上面那個單位從日變成月這種情況稱爲“降採樣”。
print(b.resample('30min',closed='right').sum())
2018-12-31 23:30:00 0.615650
2019-01-01 00:00:00 0.000000
2019-01-01 00:30:00 0.000000
2019-01-01 01:00:00 0.000000
2019-01-01 01:30:00 0.000000
...
2019-04-09 21:30:00 0.000000
2019-04-09 22:00:00 0.000000
2019-04-09 22:30:00 0.000000
2019-04-09 23:00:00 0.000000
2019-04-09 23:30:00 -1.239885
Freq: 30T, Length: 4753, dtype: float64
類似於完成resample()功能的實現頻率轉換的函數還有一個名爲asfreq().
print(b.asfreq('30min'))
2019-01-01 00:00:00 -0.169004
2019-01-01 00:30:00 NaN
2019-01-01 01:00:00 NaN
2019-01-01 01:30:00 NaN
2019-01-01 02:00:00 NaN
...
2019-04-09 22:00:00 NaN
2019-04-09 22:30:00 NaN
2019-04-09 23:00:00 NaN
2019-04-09 23:30:00 NaN
2019-04-10 00:00:00 -1.913855
Freq: 30T, Length: 4753, dtype: float64
雖然同樣是降採樣,但resample()和asfreq()還是有區別的,asfreq返回的是30min末那個時刻的值,對於默認的空缺數據都爲NaN,或者method聲明填充,或者使用fill_value參數指定填充數據,當然能降採樣也就可以升採樣:
print(b.asfreq('S',method='ffill'))
2019-01-01 00:00:00 1.168980
2019-01-01 00:00:01 1.168980
2019-01-01 00:00:02 1.168980
2019-01-01 00:00:03 1.168980
2019-01-01 00:00:04 1.168980
...
2019-04-09 23:59:56 -0.180871
2019-04-09 23:59:57 -0.180871
2019-04-09 23:59:58 -0.180871
2019-04-09 23:59:59 -0.180871
2019-04-10 00:00:00 1.441474
Freq: S, Length: 8553601, dtype: float64
從索引爲DatetimeIndex,PeriodIndex,TimedeltaIndex的數據獲取數據可以使用下標也能實現採樣。
a = pd.date_range('2019-1',periods=100,freq='D')
b = pd.Series(np.random.randn(len(a)),index=a)
print(b['2019-1'])
2019-01-01 0.623807
2019-01-02 -0.511889
2019-01-03 -0.378565
2019-01-04 -0.317178
2019-01-05 -0.714012
2019-01-06 1.095417
2019-01-07 1.280104
2019-01-08 0.068315
2019-01-09 1.021579
2019-01-10 0.477118
2019-01-11 -0.431397
2019-01-12 2.097705
2019-01-13 0.552863
2019-01-14 -0.547947
2019-01-15 1.037093
2019-01-16 -2.157402
2019-01-17 -0.554347
2019-01-18 2.437107
2019-01-19 0.408907
2019-01-20 -0.870582
2019-01-21 -0.135417
2019-01-22 -0.941027
2019-01-23 1.123345
2019-01-24 -0.011016
2019-01-25 0.877092
2019-01-26 -1.545505
2019-01-27 0.586665
2019-01-28 0.399278
2019-01-29 -0.818369
2019-01-30 -1.076719
2019-01-31 -1.349502
Freq: D, dtype: float64
這樣就可以獲取到下標爲2019-1月份下面的所有數據,默認頻率是日。