Pandas 基礎 (18) - Period and PeriodIndex

Rachel發表於2019-04-28

這節依然是時間相關的知識, 前面是側重於時間點的一些方法, 這節要介紹的是關於時間段的相關知識.

建立一個 period 物件:

import pandas as pd
y = pd.Period('2016')
y

輸出:

Period('2016', 'A-DEC')

A 代表 Annual | 年度的
DEC 代表 December | 12月
整體表示已經建立了一個 2016年的時間段物件, 並賦值給變數 y, 現在就可以呼叫這個物件的方法:

求2016年的起始時間:

y.start_time

輸出:

Timestamp('2016-01-01 00:00:00')

2016年的結束時間:

y.end_time

輸出:

Timestamp('2016-12-31 23:59:59.999999999')

建立 2019年1月的時間段物件, 注意, 這裡具體到月份了:

m = pd.Period('2019-01')
m

輸出:

Period('2019-01', 'M')

求 2019年1月的起始時間:

m.start_time

輸出:

Timestamp('2019-01-01 00:00:00')

2019年1月的結束時間:

m.end_time

輸出:

Timestamp('2019-01-31 23:59:59.999999999')

還可以對月份做加減操作:

m + 1

輸出:

Period('2019-02', 'M')

從2019年1月往後推12個月:

m + 12  

輸出:

Period('2020-01', 'M')

從輸出可以看出 Pandas 對日曆的精準掌握.

建立以天為單位的時間段物件:

d = pd.Period('2019-2-12')
d

輸出:

Period('2019-02-12', 'D')

檢視起始時間:

d.start_time

輸出:

Timestamp('2019-02-12 00:00:00')

檢視結束時間:

d.end_time

輸出:

Timestamp('2019-02-12 23:59:59.999999999')

對天進行加運算:

d + 3

輸出:

Period('2019-02-15', 'D')

建立以小時為單位的時間段物件:

h = pd.Period('2019-2-12 23')
h

輸出:

Period('2019-02-12 23:00', 'H')

這裡插播一條意外, 如果我按照如下格式寫時間:

h = pd.Period('2019-2-12 23:09:7')
h

得到的就是以秒為單位的時間段物件:

Period('2019-02-12 23:09:07', 'S')

那麼如果我固執地還想要以小時為單位的時間段物件呢? 那麼就可以用引數 freq 的值加以限制:

h = pd.Period('2019-2-12 23:09:7', freq='H')
h

這樣就得到了以小時為單位的時間段物件:

Period('2019-02-12 23:00', 'H')

同樣可以進行加減運算:

h+3

輸出:

Period('2019-02-13 02:00', 'H')

也可以用這種方式推移時間, 得到效果跟加運算是一樣的:

h+pd.offsets.Hour(3)

輸出:

Period('2019-02-13 02:00', 'H')

我們在做資料分析的時候還經常遇到以季度為時間節點的分析需求, 我們可以這樣建立以季度為單位的時間段物件:

q = pd.Period('2019Q1')
q

輸出:

Period('2019Q1', 'Q-DEC')

同樣可以進行加減運算:

q+1

輸出:

Period('2019Q2', 'Q-DEC')

檢視起始時間:

q.start_time

輸出:

Timestamp('2019-01-01 00:00:00')

檢視結束時間:

q.end_time

輸出:

Timestamp('2019-03-31 23:59:59.999999999')

透過上面的方式檢視的起始時間和結束時間都是精確到秒的, 但是從實際的角度出發, 通常我們如果需要按季度做一些分析, 應該只要精確到月就可以了, 可以透過如下方式做轉換:

q.asfreq('M', how='start')

輸出:

Period('2019-01', 'M')

以及精確到月的結束時間:

q.asfreq('M', how='end')

輸出:

Period('2019-03', 'M')

以季度為單位建立時間段物件:

idx = pd.period_range('2011', '2018', freq='Q')
idx

輸出:

PeriodIndex(['2011Q1', '2011Q2', '2011Q3', '2011Q4', '2012Q1', '2012Q2',
             '2012Q3', '2012Q4', '2013Q1', '2013Q2', '2013Q3', '2013Q4',
             '2014Q1', '2014Q2', '2014Q3', '2014Q4', '2015Q1', '2015Q2',
             '2015Q3', '2015Q4', '2016Q1', '2016Q2', '2016Q3', '2016Q4',
             '2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1'],
            dtype='period[Q-DEC]', freq='Q-DEC')

這樣活得的就是一個 list, 其中的每個元素都是一個 period 物件, 因此都可以呼叫我們之前所講到的方法, 比如起始時間:

idx[0].start_time

輸出:

Timestamp('2011-01-01 00:00:00')

以及結束時間:

idx[0].end_time

輸出:

Timestamp('2011-03-31 23:59:59.999999999')

period_range() 函式還可以透過如下方式傳參, 以設定取值範圍:

idx = pd.period_range('2011', periods=10, freq='Q')
idx

輸出:

PeriodIndex(['2011Q1', '2011Q2', '2011Q3', '2011Q4', '2012Q1', '2012Q2',
             '2012Q3', '2012Q4', '2013Q1', '2013Q2'],
            dtype='period[Q-DEC]', freq='Q-DEC')

繼續, 看下面這個例子:

import numpy as np
ps = pd.Series(np.random.randn(len(idx)), idx)
ps

結構稍顯複雜, 解釋一下, 首先利用 numpy 的 random.randn()函式生成一些隨機浮點數, 在這裡是傳入了 idx 的長度作為引數, 所以就會生成 10個隨機的浮點數, 並且是以陣列的形式返回. 然後是用 Pandas 的 Series()函式給這個陣列加上索引, (按照我前面講過的方法, 按下 shift+tab 就可以檢視任意函式的用法, 這裡 Series() 函式的第一個引數剛好是陣列, 第二個引數就是索引), 索引的值, 就是我們上面生成的 period 物件:

2011Q1   -0.108024
2011Q2   -0.535832
2011Q3    1.258304
2011Q4   -0.490206
2012Q1   -1.517975
2012Q2    0.329804
2012Q3   -0.017833
2012Q4   -1.739612
2013Q1   -0.349370
2013Q2    0.341614
Freq: Q-DEC, dtype: float64

檢視陣列的索引:

ps.index

輸出:

PeriodIndex(['2011Q1', '2011Q2', '2011Q3', '2011Q4', '2012Q1', '2012Q2',
             '2012Q3', '2012Q4', '2013Q1', '2013Q2'],
            dtype='period[Q-DEC]', freq='Q-DEC')

按年份檢視資料:

ps['2011']

輸出:

2011Q1   -0.108024
2011Q2   -0.535832
2011Q3    1.258304
2011Q4   -0.490206
Freq: Q-DEC, dtype: float64

跨年檢視資料:

ps['2011':'2013']

輸出:

2011Q1   -0.108024
2011Q2   -0.535832
2011Q3    1.258304
2011Q4   -0.490206
2012Q1   -1.517975
2012Q2    0.329804
2012Q3   -0.017833
2012Q4   -1.739612
2013Q1   -0.349370
2013Q2    0.341614
Freq: Q-DEC, dtype: float64

如果覺得 Q1, Q2 這種形式不符合人的閱讀習慣, 還可以將其轉為正常的日期格式:

pst = ps.to_timestamp()
pst

輸出:

2011-01-01   -0.108024
2011-04-01   -0.535832
2011-07-01    1.258304
2011-10-01   -0.490206
2012-01-01   -1.517975
2012-04-01    0.329804
2012-07-01   -0.017833
2012-10-01   -1.739612
2013-01-01   -0.349370
2013-04-01    0.341614
Freq: QS-OCT, dtype: float64

再開檢視一下改變後的索引:

pst.index

輸出:

DatetimeIndex(['2011-01-01', '2011-04-01', '2011-07-01', '2011-10-01',
               '2012-01-01', '2012-04-01', '2012-07-01', '2012-10-01',
               '2013-01-01', '2013-04-01'],
              dtype='datetime64[ns]', freq='QS-OCT')

當然, 還可以再轉回去:

pst.to_period()

輸出:

2011Q1   -0.108024
2011Q2   -0.535832
2011Q3    1.258304
2011Q4   -0.490206
2012Q1   -1.517975
2012Q2    0.329804
2012Q3   -0.017833
2012Q4   -1.739612
2013Q1   -0.349370
2013Q2    0.341614
Freq: Q-DEC, dtype: float64

再來舉一個現實的例子, 請看下圖, 上面是我們從 csv 檔案直接導過來的資料格式, 但是我們希望轉換成下面的格式, 首先是讓季度時間段作為索引列, 並且加上每個季度的起始時間和結束時間:

Pandas 基礎(18) - Period and PeriodIndex

首先我把 csv 檔案的截圖放在這裡, 大家需要手動敲一下:

Pandas 基礎(18) - Period and PeriodIndex

引入檔案:

import pandas as pd
df = pd.read_csv('/Users/rachel/Sites/pandas/py/pandas/18_ts_period/wmt.csv')
df

輸出:

Pandas 基礎(18) - Period and PeriodIndex

設定索引列:

df.set_index('Line Item', inplace=True)
df

輸出:

Pandas 基礎(18) - Period and PeriodIndex

轉換索引列:

df = df.T
df

輸出:

Pandas 基礎(18) - Period and PeriodIndex

獲取這個資料表的索引 list:

df.index

輸出:

Index(['2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1'], dtype='object')

利用 Pandas 的 PeriodIndex()函式, 索引 list 的資料格式改為 period 物件的 list:

df.index = pd.PeriodIndex(df.index, freq = 'Q')
df.index

輸出:

PeriodIndex(['2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1'], dtype='period[Q-DEC]', freq='Q-DEC')

轉換為 period 物件就是為了可以呼叫 start_time()和 end_time()函式.
接下來就是為 df 增加兩個欄位:

df['start time'] = df.index.map(lambda x: x.start_time)
df

輸出:

Pandas 基礎(18) - Period and PeriodIndex

df['end time'] = df.index.map(lambda x: x.end_time)
df

輸出:

Pandas 基礎(18) - Period and PeriodIndex

以上, 就是這一節的全部內容, 方法零零碎碎的看著有點多, 我覺得也不用一下都記到吧, 主要就是先照著敲一遍, 大概有個印象.

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章