《利用Python進行數(shù)據(jù)分析》第10章 時區(qū)處理筆記

時區(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
圖10-1:Period頻率轉(zhuǎn)換示例

按季度計算的時期頻率

季度型數(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')
圖10-2:不同季度型頻率之間的轉(zhuǎn)換

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í)的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末交播,一起剝皮案震驚了整個濱河市重虑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秦士,老刑警劉巖缺厉,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異隧土,居然都是意外死亡提针,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門曹傀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辐脖,“玉大人,你說我怎么就攤上這事皆愉∈燃郏” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵幕庐,是天一觀的道長炭剪。 經(jīng)常有香客問我,道長翔脱,這世上最難降的妖魔是什么奴拦? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮届吁,結(jié)果婚禮上错妖,老公的妹妹穿的比我還像新娘。我一直安慰自己疚沐,他們只是感情好暂氯,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亮蛔,像睡著了一般痴施。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上究流,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天辣吃,我揣著相機與錄音,去河邊找鬼芬探。 笑死神得,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的偷仿。 我是一名探鬼主播哩簿,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼宵蕉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了节榜?” 一聲冷哼從身側(cè)響起羡玛,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宗苍,沒想到半個月后稼稿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡浓若,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年渺杉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挪钓。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡是越,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碌上,到底是詐尸還是另有隱情倚评,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布馏予,位于F島的核電站天梧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏霞丧。R本人自食惡果不足惜呢岗,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛹尝。 院中可真熱鬧后豫,春花似錦、人聲如沸突那。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愕难。三九已至早龟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猫缭,已是汗流浹背葱弟。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饵骨,地道東北人翘悉。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像居触,于是被迫代替她去往敵國和親妖混。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容