第十七篇,數據分析之pandas的時間操作其二

時間索引

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月份下面的所有數據,默認頻率是日。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章