Pandas時(shí)間序列重采樣(resample)方法中closed、label的作用詳解
Pandas提供了便捷的方式對(duì)時(shí)間序列進(jìn)行重采樣,根據(jù)時(shí)間粒度的變大或者變小分為降采樣和升采樣:
- 降采樣:時(shí)間粒度變大。例如,原來(lái)是按天統(tǒng)計(jì)的數(shù)據(jù),現(xiàn)在變成按周統(tǒng)計(jì)。降采樣會(huì)涉及到數(shù)據(jù)的聚合,比如天數(shù)據(jù)變成周數(shù)據(jù),那么就得對(duì)一周的7天數(shù)據(jù)聚合,聚合的方式可以是求和,求均值等等。
- 升采樣:時(shí)間粒度變小。例如,原來(lái)是按周統(tǒng)計(jì)的數(shù)據(jù),現(xiàn)在變成按天統(tǒng)計(jì)。升采樣會(huì)涉及到數(shù)據(jù)的填充,根據(jù)填充的方法不同填充的數(shù)據(jù)也就不同。
下面涉及的例子,都需要導(dǎo)入numpy和pandas(如下),并且對(duì)于降采樣數(shù)據(jù)的聚合做簡(jiǎn)單的求和處理。
import numpy as np import pandas as pd
Pandas重采樣方法resample
在Pandas里,通過(guò)resample來(lái)處理重采樣,根據(jù)頻率的不同(freq)會(huì)處理成降采樣或者升采樣。我們先來(lái)看看Resample的定義和關(guān)鍵參數(shù)注釋:
resample(self, rule, how=None, axis=0, fill_method=None, closed=None, label=None, convention='start', kind=None, loffset=None, limit=None, base=0, on=None, level=None)
Convenience method for frequency conversion and resampling of time
series. Object must have a datetime-like index (DatetimeIndex,
PeriodIndex, or TimedeltaIndex), or pass datetime-like values
to the on or level keyword.
Parameters
----------
closed : {'right', 'left'}
Which side of bin interval is closed. The default is ‘left' for all frequency offsets except for ‘M', ‘A', ‘Q', ‘BM', ‘BA', ‘BQ', and ‘W' which all have a default of ‘right'.
label : {'right', 'left'}
Which bin edge label to label bucket with. The default is ‘left' for all frequency offsets except for ‘M', ‘A', ‘Q', ‘BM', ‘BA', ‘BQ', and ‘W' which all have a default of ‘right'.
第一眼看closed和label這兩個(gè)參數(shù),會(huì)感覺(jué)云里霧里,即使看了例子也可能會(huì)覺(jué)得莫名奇妙。下面我們通過(guò)具體的降采樣和升采樣例子,來(lái)解讀一下這個(gè)兩個(gè)參數(shù)內(nèi)含的玄機(jī)。
降采樣
首先先來(lái)創(chuàng)建一個(gè)時(shí)間序列,起始日期是2018/01/01,一共12天,每天對(duì)應(yīng)的數(shù)值分別是1到12:
rng = pd.date_range('20180101', periods=12)
ts = pd.Series(np.arange(1,13), index=rng)
print(ts)
#### Outputs ####
2018-01-01 1
2018-01-02 2
2018-01-03 3
2018-01-04 4
2018-01-05 5
2018-01-06 6
2018-01-07 7
2018-01-08 8
2018-01-09 9
2018-01-10 10
2018-01-11 11
2018-01-12 12
Freq: D, dtype: int32
下面使用resample方法來(lái)做降采樣處理,頻率是5天,上面提到的兩個(gè)參數(shù),都使用默認(rèn)值:
ts_5d = ts.resample('5D').sum()
print(ts_5d)
#### Outputs ####
2018-01-01 15
2018-01-06 40
2018-01-11 23
Freq: 5D, dtype: int32
到這里,我相信不論是代碼還是代碼的結(jié)果都很好理解:無(wú)非就是每5天來(lái)個(gè)求和。在第一部分中,我們列出了closed參數(shù)的注釋,從注釋可知,closed默認(rèn)的值是'left'。那如果把closed的值改為'right',結(jié)果有是怎么樣的?
ts_5d_rightclosed = ts.resample('5D', closed='right').sum()
print(ts_5d_rightclosed)
#### Outputs ####
2017-12-27 1
2018-01-01 20
2018-01-06 45
2018-01-11 12
Freq: 5D, dtype: int32
怎么會(huì)這樣?為什么變成了四個(gè)區(qū)間?closed=right到底做了什么?
別著急,我們來(lái)一步一步看看,這其中發(fā)生了什么事情。原始的時(shí)間序列是從18年1月1號(hào)到1月12號(hào),一共12天。以5天為單位降采樣處理后,變成了三個(gè)5天,分別是:
- 第一個(gè)5天:1-2-3-4-5-6
- 第二個(gè)5天:6-7-8-9-10-11
- 第三個(gè)5天:12-13-14-15-16
實(shí)際上,這三個(gè)5天就是三個(gè)區(qū)間了。和數(shù)學(xué)里區(qū)間的概念一樣,區(qū)間有開和閉的概念。在resample中,區(qū)間的開和閉,就是通過(guò)closed這個(gè)參數(shù)來(lái)控制。用數(shù)學(xué)符號(hào)表示的話:
closed = 'left' 左閉右開
上面的三個(gè)5天可以由以下的三個(gè)左閉右開的區(qū)間構(gòu)成:
- 區(qū)間1:[1, 6)
- 區(qū)間2: [6, 11)
- 區(qū)間3:[11, 16) 例子中,時(shí)間只到12號(hào)為止,但是這里會(huì)往后補(bǔ)足5天
現(xiàn)在,在這三個(gè)區(qū)間上做數(shù)據(jù)聚合也就很好理解了。對(duì)于區(qū)間1進(jìn)行求和,也就是12、13、14、15、16這5天的值求和即可。區(qū)間2和區(qū)間3也是同理。所以下面的代碼就很好理解了:
ts_5d_leftclosed = ts.resample('5D', closed='right').sum()
print(ts_5d_leftclosed)
#### Outputs #### 2018-01-01 15 2018-01-06 40 2018-01-11 23 Freq: 5D, dtype: int32
closed = 'right' 左開右閉
上面的三個(gè)5天可以由以下的四個(gè)左開右閉的區(qū)間構(gòu)成。注意,由于第一個(gè)5天是從1號(hào)到6號(hào),但由于是左開區(qū)間,1號(hào)就落不到1到6號(hào)的那個(gè)區(qū)間,所以要往前補(bǔ)足:
- 區(qū)間1:(27, 1]
- 區(qū)間2:(1, 6]
- 區(qū)間3: (6, 11]
- 區(qū)間4:(11, 16]
現(xiàn)在,在這四個(gè)區(qū)間上做數(shù)據(jù)聚合也是一樣的道理了:對(duì)于區(qū)間1,是對(duì)28,29,30,31,1這五天的值求和(這里只有1號(hào)是有值的),其余的區(qū)間也是同理,但需要注意是左開右閉。所以到這里,上面“莫名其妙”的代碼和結(jié)果就好理解了。復(fù)制代碼和結(jié)果如下:
ts_5d_rightclosed = ts.resample('5D', closed='right').sum()
print(ts_5d_rightclosed)
#### Outputs ####
2017-12-27 1
2018-01-01 20
2018-01-06 45
2018-01-11 12
Freq: 5D, dtype: int32
理解了clsoed的意義以后,再來(lái)理解label就so easy了。由注釋可知,label的默認(rèn)值是left。下面在closed='right'的基礎(chǔ)上,將label設(shè)置為right:
ts_5d_rightclosed_rightlable = ts.resample('5D', closed='right', label='right').sum()
print(ts_5d_rightclosed_rightlable)
#### Outputs ####
2018-01-01 1
2018-01-06 20
2018-01-11 45
2018-01-16 12
Freq: 5D, dtype: int32
于label為left相比,二者結(jié)果的異同點(diǎn)如下:
- 相同點(diǎn):一樣是四個(gè)區(qū)間,每個(gè)區(qū)間的聚合的值是一樣的
- 不同點(diǎn):每個(gè)區(qū)間的索引不同
不難發(fā)現(xiàn),label為left的時(shí)候,就以區(qū)間左邊的那個(gè)日期作為索引;label,就以區(qū)間的右邊那個(gè)日期作為索引。
綜上,我們可以總結(jié)一下closed和label的用法和意義了:
- closed:劃分區(qū)間的依據(jù),left會(huì)劃成左閉右開區(qū)間;right會(huì)劃分成左開右閉的區(qū)間。一般來(lái)說(shuō),closed為right的時(shí)候,區(qū)間會(huì)比為left的時(shí)候多一個(gè)。區(qū)間劃分完畢,聚合運(yùn)算就在這個(gè)區(qū)間內(nèi)執(zhí)行。
- label:劃分區(qū)間完畢,根據(jù)label的不同,區(qū)間的索引就不同。如果label為left,則區(qū)間左邊的日期作為索引;如果label為right,則區(qū)間右邊的日期作為索引。
升采樣
創(chuàng)建一個(gè)時(shí)間序列,起始日期是2018/01/01,一共2天,每天對(duì)應(yīng)的數(shù)值分別是1到2:
rng = pd.date_range('20180101', periods=2)
ts = pd.Series(np.arange(1,2), index=rng)
print(ts)
#### Outputs ####
2018-01-01 1
2018-01-02 2
Freq: D, dtype: int32
升采樣就不涉及到closed和label的值,也就是會(huì)忽略(筒子們可以驗(yàn)證一下),所以我們?cè)谑褂玫臅r(shí)候無(wú)需設(shè)置這兩個(gè)值。對(duì)于升采樣,前面也提到,主要是涉及到值的填充。有下面的四種填充方法(實(shí)際是三種):
- 不填充。那么對(duì)應(yīng)無(wú)值的地方,用NaN代替。對(duì)應(yīng)的方法是asfreq。
- 用前值填充。用前面的值填充無(wú)值的地方。對(duì)應(yīng)的方法是ffill或者pad。這里方便記憶,ffill的第一個(gè)f是代表forward,向前的意思
- 用后值填充。對(duì)應(yīng)的方法是bfill,b代表back。
下面是一個(gè)例子:
ts_6h_asfreq = ts.resample('6H').asfreq()
print(ts_6h_asfreq)
ts_6h_pad = ts.resample('6H').pad()
print(ts_6h_pad)
ts_6h_ffill = ts.resample('6H').ffill()
print(ts_6h_ffill)
ts_6h_bfill = ts.resample('6H').bfill()
print(ts_6h_bfill)
#### Outputs ####
2018-01-01 00:00:00 1.0
2018-01-01 06:00:00 NaN
2018-01-01 12:00:00 NaN
2018-01-01 18:00:00 NaN
2018-01-02 00:00:00 2.0
Freq: 6H, dtype: float64
2018-01-01 00:00:00 1
2018-01-01 06:00:00 1
2018-01-01 12:00:00 1
2018-01-01 18:00:00 1
2018-01-02 00:00:00 2
Freq: 6H, dtype: int32
2018-01-01 00:00:00 1
2018-01-01 06:00:00 1
2018-01-01 12:00:00 1
2018-01-01 18:00:00 1
2018-01-02 00:00:00 2
Freq: 6H, dtype: int32
2018-01-01 00:00:00 1
2018-01-01 06:00:00 2
2018-01-01 12:00:00 2
2018-01-01 18:00:00 2
2018-01-02 00:00:00 2
Freq: 6H, dtype: int32
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python還能這么玩之用Python修改了班花的開機(jī)密碼
今天帶大家學(xué)習(xí)如何用Python修改開機(jī)密碼,文中有非常詳細(xì)的代碼示例,喜歡惡作劇的小伙伴可以看一下,不過(guò)不要亂用哦,需要的朋友可以參考下2021-06-06
python使用knn實(shí)現(xiàn)特征向量分類
這篇文章主要為大家詳細(xì)介紹了python使用knn實(shí)現(xiàn)特征向量分類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Python sqlparse 解析庫(kù)的基礎(chǔ)使用過(guò)程解析
sqlparse 是一個(gè) Python 庫(kù),是一個(gè)用于 Python 的非驗(yàn)證 SQL 解析器, 用于解析 SQL 語(yǔ)句并提供一個(gè)簡(jiǎn)單的 API 來(lái)訪問(wèn)解析后的 SQL 結(jié)構(gòu),這篇文章主要介紹了Python sqlparse 解析庫(kù)的基礎(chǔ)使用,需要的朋友可以參考下2024-08-08
詳解TensorFlow2實(shí)現(xiàn)前向傳播
這篇文章主要介紹了TensorFlow2如何實(shí)現(xiàn)前向傳播,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
win7下 python3.6 安裝opencv 和 opencv-contrib-python解決 cv2.xfeat
這篇文章主要介紹了win7下 python3.6 安裝opencv 和 opencv-contrib-python解決 cv2.xfeatures2d.SIFT_create() 的問(wèn)題,需要的朋友可以參考下2019-10-10
python3如何使用saml2.0協(xié)議接入SSO
SAML是一種用于在不同系統(tǒng)之間傳輸安全聲明的XML框架,通過(guò)IDP和SP之間的重定向訪問(wèn),SP向IDP請(qǐng)求用戶身份認(rèn)證,IDP驗(yàn)證用戶身份后返回SAML應(yīng)答,本文以python3和python3-saml庫(kù)為例,介紹了如何接入公司SSO系統(tǒng),包括配置和處理登錄和登出請(qǐng)求2024-11-11
python pandas消除空值和空格以及 Nan數(shù)據(jù)替換方法
今天小編就為大家分享一篇python pandas消除空值和空格以及 Nan數(shù)據(jù)替換方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10

