時區(qū)處理
在Python中凸克,時區(qū)信息來自第三方庫pytz柒啤,它使Python可以使用Olson數(shù)據(jù)庫(匯編了世界時區(qū)信息)官紫。
有關(guān)pytz庫的更多信息钳榨,請查閱其文檔,時區(qū)名可以在文檔中找到驼鹅,也可以通過交互的方式查看
from pandas import Series,DataFrame
import pandas as pd
import numpy as np
import pytz
pytz.common_timezones[-5:]
['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']
要從pytz中獲取時區(qū)對象微谓,使用pytz.timezone
tz=pytz.timezone('US/Eastern')
tz
<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
pandas中的方法既可以接受時區(qū)名也可以接受這種對象。建議只用時區(qū)名
本地化和轉(zhuǎn)換
默認情況下输钩,pandas中的時間序列是單純的(naive)時區(qū)
rng=pd.date_range('3/9/2017 10:30',periods=6,freq='D')
ts=Series(np.random.randn(len(rng)),index=rng)
ts
2017-03-09 10:30:00 -0.010633
2017-03-10 10:30:00 -1.026320
2017-03-11 10:30:00 0.001829
2017-03-12 10:30:00 -0.221503
2017-03-13 10:30:00 -1.658208
2017-03-14 10:30:00 0.559757
Freq: D, dtype: float64
print(ts.index.tz) #其索引的tz字段為None
None
在生成日期范圍的時候還可以加上一個時區(qū)集
pd.date_range('10/1/2017 10:30',periods=10,freq='D',tz='UTC')
DatetimeIndex(['2017-10-01 10:30:00+00:00', '2017-10-02 10:30:00+00:00',
'2017-10-03 10:30:00+00:00', '2017-10-04 10:30:00+00:00',
'2017-10-05 10:30:00+00:00', '2017-10-06 10:30:00+00:00',
'2017-10-07 10:30:00+00:00', '2017-10-08 10:30:00+00:00',
'2017-10-09 10:30:00+00:00', '2017-10-10 10:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
從單純到本地化的轉(zhuǎn)換是通過tz_localize方法處理的
ts_utc=ts.tz_localize('UTC')
ts_utc
2017-03-09 10:30:00+00:00 -0.010633
2017-03-10 10:30:00+00:00 -1.026320
2017-03-11 10:30:00+00:00 0.001829
2017-03-12 10:30:00+00:00 -0.221503
2017-03-13 10:30:00+00:00 -1.658208
2017-03-14 10:30:00+00:00 0.559757
Freq: D, dtype: float64
一旦時間序列被本地化到某個特定時區(qū)豺型,就可以用tz_convert將其轉(zhuǎn)換到別的時區(qū)了
ts_utc.tz_convert('US/Eastern')
2017-03-09 05:30:00-05:00 -0.010633
2017-03-10 05:30:00-05:00 -1.026320
2017-03-11 05:30:00-05:00 0.001829
2017-03-12 06:30:00-04:00 -0.221503
2017-03-13 06:30:00-04:00 -1.658208
2017-03-14 06:30:00-04:00 0.559757
Freq: D, dtype: float64
對于上面這種時間序列(它跨越了美國東部時區(qū)的夏令時轉(zhuǎn)變期),我們可以將其本地化到EST买乃,然后轉(zhuǎn)換為UTC或柏林時間
ts_eastern=ts_utc.tz_convert('US/Eastern')
ts_eastern.tz_convert('UTC')
2017-03-09 10:30:00+00:00 -0.010633
2017-03-10 10:30:00+00:00 -1.026320
2017-03-11 10:30:00+00:00 0.001829
2017-03-12 10:30:00+00:00 -0.221503
2017-03-13 10:30:00+00:00 -1.658208
2017-03-14 10:30:00+00:00 0.559757
Freq: D, dtype: float64
ts_eastern.tz_convert('Europe/Berlin')
2017-03-09 11:30:00+01:00 -0.010633
2017-03-10 11:30:00+01:00 -1.026320
2017-03-11 11:30:00+01:00 0.001829
2017-03-12 11:30:00+01:00 -0.221503
2017-03-13 11:30:00+01:00 -1.658208
2017-03-14 11:30:00+01:00 0.559757
Freq: D, dtype: float64
tz_localize和tz_convert也是DatetimeIndex的實例方法
ts.index.tz_localize('Asia/Shanghai')
DatetimeIndex(['2017-03-09 10:30:00+08:00', '2017-03-10 10:30:00+08:00',
'2017-03-11 10:30:00+08:00', '2017-03-12 10:30:00+08:00',
'2017-03-13 10:30:00+08:00', '2017-03-14 10:30:00+08:00'],
dtype='datetime64[ns, Asia/Shanghai]', freq='D')
警告: 對單純時間戳的本地化操作還會檢查夏令時轉(zhuǎn)變期附近容易混淆或不存在的時間姻氨。
操作時區(qū)意識型Timestamp對象
跟時間序列和日期范圍差不多,Timestamp對象也能被從單純型(naive)本地化為時區(qū)意識型(time zone-aware)剪验,并從一個時區(qū)轉(zhuǎn)換到另一個時區(qū)
stamp=pd.Timestamp('2017-06-12 06:00')
stamp_utc=stamp.tz_localize('utc')
stamp_utc
Timestamp('2017-06-12 06:00:00+0000', tz='UTC')
stamp_utc.tz_convert('US/Eastern')
Timestamp('2017-06-12 02:00:00-0400', tz='US/Eastern')
在創(chuàng)建Timestamp時肴焊,還可以傳入一個時區(qū)信息
stamp_moscow=pd.Timestamp('2017-06-29 06:30',tz='Europe/Moscow')
stamp_moscow
Timestamp('2017-06-29 06:30:00+0300', tz='Europe/Moscow')
時區(qū)意識型Timestamp對象在內(nèi)部保存了一個UTC時間戳值(自UNIX紀元(1970年1月1日)算起的納秒數(shù))。這個UTC值在時區(qū)轉(zhuǎn)換過程中是不會發(fā)生變化的
stamp_utc.value
1497247200000000000
stamp_utc.tz_convert('US/Eastern').value
1497247200000000000
當(dāng)使用pandas的DateOffset對象執(zhí)行時間算術(shù)運算時碉咆,運算過程會自動關(guān)注是否存在夏令時轉(zhuǎn)變期
from pandas.tseries.offsets import Hour
stamp=pd.Timestamp('2017-06-29 06:30',tz='US/Eastern')
stamp
Timestamp('2017-06-29 06:30:00-0400', tz='US/Eastern')
stamp+Hour() # 夏令時轉(zhuǎn)變前30分鐘
Timestamp('2017-06-29 07:30:00-0400', tz='US/Eastern')
stamp=pd.Timestamp('2017-12-05 00:30',tz='US/Eastern')
stamp
Timestamp('2017-12-05 00:30:00-0500', tz='US/Eastern')
stamp+2*Hour() # 夏令時轉(zhuǎn)變前90分鐘
Timestamp('2017-12-05 02:30:00-0500', tz='US/Eastern')
不同時區(qū)之間的運算
如果兩個時間序列的時區(qū)不同抖韩,在將它們合并到一起時,最終結(jié)果就會是UTC疫铜。由于時間戳其實是以UTC存儲的茂浮,所以這是一個很簡單的運算,并不需要發(fā)生任何轉(zhuǎn)換
rng=pd.date_range('3/9/2017 10:30',periods=10,freq='B')
ts=Series(np.random.randn(len(rng)),index=rng)
ts
2017-03-09 10:30:00 -0.221934
2017-03-10 10:30:00 -0.026261
2017-03-13 10:30:00 -0.582364
2017-03-14 10:30:00 -1.488370
2017-03-15 10:30:00 -0.766432
2017-03-16 10:30:00 -0.114979
2017-03-17 10:30:00 -0.708361
2017-03-20 10:30:00 -0.745198
2017-03-21 10:30:00 0.896473
2017-03-22 10:30:00 0.505825
Freq: B, dtype: float64
ts1=ts[:7].tz_localize('Europe/London')
ts1
2017-03-09 10:30:00+00:00 -0.221934
2017-03-10 10:30:00+00:00 -0.026261
2017-03-13 10:30:00+00:00 -0.582364
2017-03-14 10:30:00+00:00 -1.488370
2017-03-15 10:30:00+00:00 -0.766432
2017-03-16 10:30:00+00:00 -0.114979
2017-03-17 10:30:00+00:00 -0.708361
Freq: B, dtype: float64
ts2=ts[2:].tz_localize('Europe/London')
ts2
2017-03-13 10:30:00+00:00 -0.582364
2017-03-14 10:30:00+00:00 -1.488370
2017-03-15 10:30:00+00:00 -0.766432
2017-03-16 10:30:00+00:00 -0.114979
2017-03-17 10:30:00+00:00 -0.708361
2017-03-20 10:30:00+00:00 -0.745198
2017-03-21 10:30:00+00:00 0.896473
2017-03-22 10:30:00+00:00 0.505825
Freq: B, dtype: float64
result=ts1+ts2
result.index
DatetimeIndex(['2017-03-09 10:30:00+00:00', '2017-03-10 10:30:00+00:00',
'2017-03-13 10:30:00+00:00', '2017-03-14 10:30:00+00:00',
'2017-03-15 10:30:00+00:00', '2017-03-16 10:30:00+00:00',
'2017-03-17 10:30:00+00:00', '2017-03-20 10:30:00+00:00',
'2017-03-21 10:30:00+00:00', '2017-03-22 10:30:00+00:00'],
dtype='datetime64[ns, Europe/London]', freq='B')
時期及其算術(shù)運算
時期(period)表示的是時間區(qū)間,比如數(shù)日席揽、數(shù)月顽馋、數(shù)季、數(shù)年等幌羞。
Period類所表示的就是這種數(shù)據(jù)類型寸谜,其構(gòu)造函數(shù)需要用到一個字符串或整數(shù),以及表10-4中的頻率属桦。
p=pd.Period(2010,freq='A-DEC')
p
Period('2010', 'A-DEC')
這個Period對象表示的是從2010年1月1日到2010年12月31日之間的整段時間熊痴。只需對Period對象加上或減去一個整數(shù)即可達到根據(jù)其頻率進行位移的效果
p+7
Period('2017', 'A-DEC')
p-6
Period('2004', 'A-DEC')
如果兩個Period對象擁有相同的頻率,則它們的差就是它們之間的單位數(shù)量
pd.Period('2017',freq='A-DEC')-p
7
period_range函數(shù)可用于創(chuàng)建規(guī)則的時期范圍
rng=pd.period_range('2/1/2017','12/25/2017',freq='M')
rng
PeriodIndex(['2017-02', '2017-03', '2017-04', '2017-05', '2017-06', '2017-07',
'2017-08', '2017-09', '2017-10', '2017-11', '2017-12'],
dtype='period[M]', freq='M')
PeriodIndex類保存了一組Period聂宾,它可以在任何pandas數(shù)據(jù)結(jié)構(gòu)中被用作軸索引
Series(np.random.randn(11),index=rng)
2017-02 -0.319098
2017-03 -0.151707
2017-04 0.848815
2017-05 1.755160
2017-06 -2.718766
2017-07 0.921045
2017-08 -0.287053
2017-09 -0.720153
2017-10 0.827423
2017-11 -1.147326
2017-12 0.480532
Freq: M, dtype: float64
PeriodIndex類的構(gòu)造函數(shù)還允許直接使用一組字符串
values=['2010Q3','2013Q2','2016Q1']
index=pd.PeriodIndex(values,freq='Q-DEC')
index
PeriodIndex(['2010Q3', '2013Q2', '2016Q1'], dtype='period[Q-DEC]', freq='Q-DEC')
時期的頻率轉(zhuǎn)換
Period和PeriodIndex對象都可以通過其asfreq方法被轉(zhuǎn)換成別的頻率果善。假設(shè)我們有一個年度時期,希望將其轉(zhuǎn)換為當(dāng)年年初或年末的一個月度時期系谐。
p=pd.Period('2017',freq='A-DEC')
p.asfreq('M',how='start')
Period('2017-01', 'M')
p.asfreq('M',how='end')
Period('2017-12', 'M')
可以將Period('2017','A-DEC')看做一個被劃分為多個月度時期的時間段中的游標(biāo)巾陕。圖10-1對此進行了說明。對于一個不以12月結(jié)束的財政年度纪他,月度子時期的歸屬情況就不一樣了
p=pd.Period('2017',freq='A-JUN')
p.asfreq('M','start')
Period('2016-07', 'M')
p.asfreq('M','end')
Period('2017-06', 'M')
在將高頻率轉(zhuǎn)換為低頻率時鄙煤,超時期(superperiod)是由子時期(subperiod)所屬的位置決定的。例如茶袒,在A-JUN頻率中梯刚,月份“2017年8月”實際上是屬于周期“2018年”的
p=pd.Period('2017-08','M')
p.asfreq('A-JUN')
Period('2018', 'A-JUN')
PeriodIndex或TimeSeries的頻率轉(zhuǎn)換方式也是這樣
rng=pd.period_range('2010','2018',freq='A-DEC')
ts=Series(np.random.randn(len(rng)),index=rng)
ts
2010 -0.433900
2011 -0.494450
2012 0.668362
2013 -0.728913
2014 -0.062562
2015 0.764723
2016 -1.962189
2017 -2.107805
2018 2.432714
Freq: A-DEC, dtype: float64
按季度計算的時期頻率
季度型數(shù)據(jù)在會計逗威、金融等領(lǐng)域中很常見。許多季度型數(shù)據(jù)都會涉及“財年末”的概念盆色,通常是一年12個月中某月的最后一個日歷日或工作日低滩。就這一點來說,時期"2012Q4"根據(jù)財年末的不同會有不同的含義崭捍。pandas支持12種可能的季度型頻率,即Q-JAN到Q-DEC
p=pd.Period('2012Q4',freq='Q-JAN')
p
Period('2012Q4', 'Q-JAN')
在以1月結(jié)束的財年中,2012Q4是從11月到1月(將其轉(zhuǎn)換為日型頻率就明白了)植康。圖10-2對此進行了說明
p.asfreq('D','start')
Period('2011-11-01', 'D')
p.asfreq('D','end')
Period('2012-01-31', 'D')
因此,Period之間的算術(shù)運算會非常簡單展懈。例如销睁,要獲取該季度倒數(shù)第二個工作日下午4點的時間戳
p4pm=(p.asfreq('B','e')-1).asfreq('T','s')+16*60
p4pm
Period('2012-01-30 16:00', 'T')
p4pm.to_timestamp()
Timestamp('2012-01-30 16:00:00')
eriod_range還可用于生成季度型范圍。季度型范圍的算術(shù)運算也跟上面是一樣的
rng=pd.period_range('2011Q3','2012Q4',freq='Q-JAN')
ts=Series(np.arange(len(rng)),index=rng)
ts
2011Q3 0
2011Q4 1
2012Q1 2
2012Q2 3
2012Q3 4
2012Q4 5
Freq: Q-JAN, dtype: int32
new_rng=(rng.asfreq('B','e')-1).asfreq('T','s')+16*60
new_rng
PeriodIndex(['2010-10-28 16:00', '2011-01-28 16:00', '2011-04-28 16:00',
'2011-07-28 16:00', '2011-10-28 16:00', '2012-01-30 16:00'],
dtype='period[T]', freq='T')
ts.index=new_rng.to_timestamp()
ts
2010-10-28 16:00:00 0
2011-01-28 16:00:00 1
2011-04-28 16:00:00 2
2011-07-28 16:00:00 3
2011-10-28 16:00:00 4
2012-01-30 16:00:00 5
dtype: int32
將Timestamp轉(zhuǎn)換為Period(及其反向過程)
通過使用to_period方法存崖,可以將由時間戳索引的Series和DataFrame對象轉(zhuǎn)換為以時期索引
rng=pd.date_range('1/1/2017',periods=3,freq='M')
rng
DatetimeIndex(['2017-01-31', '2017-02-28', '2017-03-31'], dtype='datetime64[ns]', freq='M')
ts=Series(np.random.randn(3),index=rng)
ts
2017-01-31 -0.126709
2017-02-28 0.477945
2017-03-31 -1.665440
Freq: M, dtype: float64
由于時期指的是非重疊時間區(qū)間冻记,因此對于給定的頻率,一個時間戳只能屬于一個時期来惧。新PeriodIndex的頻率默認是從時間戳推斷而來的冗栗,你也可以指定任何別的頻率。結(jié)果中允許存在重復(fù)時期
rng=pd.date_range('1/29/2010',periods=6,freq='D')
ts2=Series(np.random.randn(6),index=rng)
ts2.to_period('M')
2010-01 0.453939
2010-01 -0.116637
2010-01 0.211619
2010-02 1.552368
2010-02 0.583840
2010-02 0.219376
Freq: M, dtype: float64
要轉(zhuǎn)換為時間戳,使用to_timestamp即可
pts=ts.to_period()
pts
2017-01 -0.126709
2017-02 0.477945
2017-03 -1.665440
Freq: M, dtype: float64
通過數(shù)組創(chuàng)建PeriodIndex
固定頻率的數(shù)據(jù)集通常會將時間信息分開存放在多個列中隅居。例如钠至,在下面這個宏觀經(jīng)濟數(shù)據(jù)集中,年度和季度就分別存放在不同的列中
data=pd.read_csv('pydata_book/ch08//macrodata.csv')
data[:8]
data.year
0 1959.0
1 1959.0
2 1959.0
3 1959.0
...
199 2008.0
200 2009.0
201 2009.0
202 2009.0
Name: year, Length: 203, dtype: float64
data.quarter
0 1.0
1 2.0
2 3.0
3 4.0
...
199 4.0
200 1.0
201 2.0
202 3.0
Name: quarter, Length: 203, dtype: float64
將這兩個數(shù)組以及一個頻率傳入PeriodIndex胎源,就可以將它們合并成DataFrame的一個索引
index=pd.PeriodIndex(year=data.year,quarter=data.quarter,freq='Q-DEC')
index
PeriodIndex(['1959Q1', '1959Q2', '1959Q3', '1959Q4', '1960Q1', '1960Q2',
'1960Q3', '1960Q4', '1961Q1', '1961Q2',
...
'2007Q2', '2007Q3', '2007Q4', '2008Q1', '2008Q2', '2008Q3',
'2008Q4', '2009Q1', '2009Q2', '2009Q3'],
dtype='period[Q-DEC]', length=203, freq='Q-DEC')
data.index=index
data.infl
1959Q1 0.00
1959Q2 2.34
1959Q3 2.74
1959Q4 0.27
1960Q1 2.31
1960Q2 0.14
1960Q3 2.70
...
2008Q2 8.53
2008Q3 -3.16
2008Q4 -8.79
2009Q1 0.94
2009Q2 3.37
2009Q3 3.56
Freq: Q-DEC, Name: infl, Length: 203, dtype: float64
重采樣及頻率轉(zhuǎn)換
重采樣(resampling)指的是將時間序列從一個頻率轉(zhuǎn)換到另一個頻率的處理過程棉钧。將高頻率數(shù)據(jù)聚合到低頻率稱為降采樣(downsampling),而將低頻率數(shù)據(jù)轉(zhuǎn)換到高頻率則稱為升采樣(upsampling)涕蚤。并不是所有的重采樣都能被劃分到這兩個大類中宪卿。例如,將W-WED(每周三)轉(zhuǎn)換為W-FRI既不是降采樣也不是升采樣万栅。
pandas對象都帶有一個resample方法愧捕,它是各種頻率轉(zhuǎn)換工作的主力函數(shù)
rng=pd.date_range('1/1/2017',periods=100,freq='D')
ts=Series(np.random.randn(len(rng)),index=rng)
ts.resample('M',how='mean')
e:\python\lib\site-packages\ipykernel_launcher.py:3: FutureWarning: how in .resample() is deprecated
the new syntax is .resample(...).mean()
This is separate from the ipykernel package so we can avoid doing imports until
2017-01-31 0.256096
2017-02-28 0.206771
2017-03-31 -0.103452
2017-04-30 -0.105697
Freq: M, dtype: float64
ts.resample('M').mean()
2017-01-31 0.256096
2017-02-28 0.206771
2017-03-31 -0.103452
2017-04-30 -0.105697
Freq: M, dtype: float64
ts.resample('M',kind='period').mean()
2017-01 0.256096
2017-02 0.206771
2017-03 -0.103452
2017-04 -0.105697
Freq: M, dtype: float64
resample是一個靈活高效的方法,可用于處理非常大的時間序列申钩。
降采樣
將數(shù)據(jù)聚合到規(guī)整的低頻率是一件非常普通的時間序列處理任務(wù)次绘。待聚合的數(shù)據(jù)不必擁有固定的頻率,期望的頻率會自動定義聚合的面元邊界撒遣,這些面元用于將時間序列拆分為多個片段邮偎。例如,要轉(zhuǎn)換到月度頻率('M'或'BM')义黎,數(shù)據(jù)需要被劃分到多個單月時間段中禾进。各時間段都是半開放的。一個數(shù)據(jù)點只能屬于一個時間段廉涕,所有時間段的并集必須能組成整個時間幀泻云。在用resample對數(shù)據(jù)進行降采樣時,需要考慮兩樣?xùn)|西:
·各區(qū)間哪邊是閉合的狐蜕。
如何標(biāo)記各個聚合面元宠纯,用區(qū)間的開頭還是末尾。
首先层释,我們來看一些“1分鐘”數(shù)據(jù)
rng=pd.date_range('1/1/2017',periods=12,freq='T')
ts=Series(np.arange(12),index=rng)
ts
2017-01-01 00:00:00 0
2017-01-01 00:01:00 1
2017-01-01 00:02:00 2
2017-01-01 00:03:00 3
2017-01-01 00:04:00 4
2017-01-01 00:05:00 5
2017-01-01 00:06:00 6
2017-01-01 00:07:00 7
2017-01-01 00:08:00 8
2017-01-01 00:09:00 9
2017-01-01 00:10:00 10
2017-01-01 00:11:00 11
Freq: T, dtype: int32
如果你想要通過求和的方式將這些數(shù)據(jù)聚合到“5分鐘”塊中
注意:這里與書本的代碼結(jié)果不同婆瓜。
ts.resample('5min').sum()
2017-01-01 00:00:00 10
2017-01-01 00:05:00 35
2017-01-01 00:10:00 21
Freq: 5T, dtype: int32
傳入的頻率將會以“5分鐘”的增量定義面元邊界。默認情況下贡羔,面元的右邊界是包含的廉白,因此00:00到00:05的區(qū)間中是包含00:05的注1。傳入closed='left'會讓區(qū)間以左邊界閉合
這里可能版本不同乖寒,上面的那個與書上結(jié)果不同的猴蹂。
ts.resample('5min',closed='left').sum()
2017-01-01 00:00:00 10
2017-01-01 00:05:00 35
2017-01-01 00:10:00 21
Freq: 5T, dtype: int32
ts.resample('5min',closed='left',label='left').sum()
2017-01-01 00:00:00 10
2017-01-01 00:05:00 35
2017-01-01 00:10:00 21
Freq: 5T, dtype: int32
最終的時間序列是以各面元右邊界的時間戳進行標(biāo)記的。傳入label='left'即可用面元的左邊界對其進行標(biāo)記
圖10-3說明了“1分鐘”數(shù)據(jù)被轉(zhuǎn)換為“5分鐘”數(shù)據(jù)的處理過程楣嘁。
圖10-3:各種closed磅轻、label約定的“5分鐘”重采樣演示
比如從右邊界減去一秒以便更容易明白該時間戳到底表示的是哪個區(qū)間覆获。只需通過loffset設(shè)置一個字符串或日期偏移量即可實現(xiàn)這個目的
ts.resample('5min',loffset='-1s').sum()
2016-12-31 23:59:59 10
2017-01-01 00:04:59 35
2017-01-01 00:09:59 21
Freq: 5T, dtype: int32
也可以通過調(diào)用結(jié)果對象的shift方法來實現(xiàn)該目的,這樣就不需要設(shè)置loffset了
OHLC重采樣
金融領(lǐng)域中有一種無所不在的時間序列聚合方式瓢省,即計算各面元的四個值:第一個值(open弄息,開盤)、最后一個值(close勤婚,收盤)摹量、最大值(high,最高)以及最小值(low馒胆,最低)缨称。
傳入how='ohlc'即可得到一個含有這四種聚合值的DataFrame。整個過程很高效祝迂,只需一次掃描即可計算出結(jié)果
ts.resample('5min').ohlc()
通過groupby進行重采樣
另一種降采樣的辦法是使用pandas的groupby功能睦尽。例如,你打算根據(jù)月份或星期幾進行分組型雳,只需傳入一個能夠訪問時間序列的索引上的這些字段的函數(shù)即可
rng=pd.date_range('1/1/2017',periods=100,freq='D')
ts=Series(np.arange(100),index=rng)
ts.groupby(lambda x: x.month).mean()
2017-01-01 0
2017-01-02 1
2017-01-03 2
2017-01-04 3
2017-01-05 4
2017-01-06 5
Freq: D, dtype: int32
ts.groupby(lambda x: x.weekday).mean()
0 50.0
1 47.5
2 48.5
3 49.5
4 50.5
5 51.5
6 49.0
dtype: float64
升采樣和插值
在將數(shù)據(jù)從低頻率轉(zhuǎn)換到高頻率時当凡,就不需要聚合了
frame=DataFrame(np.random.randn(2,4),
index=pd.date_range('1/1/2017',periods=2,freq='W-WED'),
columns=['Colorado','Texas','New York','Ohio'])
frame[:5]
將其重采樣到日頻率,默認會引入缺失值(與書上結(jié)果不同)
df_daily=frame.resample('D')
df_daily
DatetimeIndexResampler [freq=<Day>, axis=0, closed=left, label=left, convention=start, base=0]
假設(shè)你想要用前面的周型值填充“非星期三”纠俭。resampling的填充和插值方式跟fillna和reindex的一樣
frame.resample('D',fill_method='ffill')
e:\python\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: fill_method is deprecated to .resample()
the new syntax is .resample(...).ffill()
"""Entry point for launching an IPython kernel.
這里也可以只填充指定的時期數(shù)(目的是限制前面的觀測值的持續(xù)使用距離)
frame.resample('D').ffill(limit=2)
注意沿量,新的日期索引完全沒必要跟舊的相交
frame.resample('W-THU').ffill()
通過時期進行重采樣
對那些使用時期索引的數(shù)據(jù)進行重采樣是件非常簡單的事情
frame=DataFrame(np.random.randn(12,4),
index=pd.period_range('1-2017','12-2017',freq='M'),
columns=['Colorado','Texas','New York','Ohio'])
frame[:5]
annual_frame=frame.resample('A-DEC').mean()
annual_frame
升采樣要稍微麻煩一些,因為你必須決定在新頻率中各區(qū)間的哪端用于放置原來的值冤荆,就像asfreq方法那樣朴则。convention參數(shù)默認為'end',可設(shè)置為'start'
annual_frame.resample('Q-DEC').ffill() # Q-DEC: 季度型(每年以12月結(jié)束)
annual_frame.resample('Q-DEC',convention='start').ffill()
由于時期指的是時間區(qū)間钓简,所以升采樣和降采樣的規(guī)則就比較嚴格:
1.在降采樣中乌妒,目標(biāo)頻率必須是源頻率的子時期(subperiod)。
2.在升采樣中外邓,目標(biāo)頻率必須是源頻率的超時期(superperiod)撤蚊。
如果不滿足這些條件,就會引發(fā)異常坐榆。這主要影響的是按季拴魄、年、周計算的頻率席镀。例如,由Q-MAR定義的時間區(qū)間只能升采樣為A-MAR夏漱、A-JUN豪诲、A-SEP、A-DEC等
annual_frame.resample('Q-MAR').ffill()
在本章節(jié)有些函數(shù)舍棄了挂绰,比如:resample() is deprecated屎篱,the new syntax is .resample(...).mean()服赎。這里使用的是Python3以上的版本練習(xí)的。