日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

pandas 時(shí)序統(tǒng)計(jì)的高級(jí)用法!

 天承辦公室 2023-10-08 發(fā)布于北京

本次介紹pandas時(shí)間統(tǒng)計(jì)分析的一個(gè)高級(jí)用法--重采樣。

完整數(shù)據(jù)代碼可戳??《pandas進(jìn)階寶典》進(jìn)行了解。

重采樣指的是時(shí)間重采樣,就是將時(shí)間序列從一個(gè)頻率轉(zhuǎn)換到另一個(gè)頻率上,對(duì)應(yīng)數(shù)據(jù)也跟著頻率進(jìn)行變化。比如時(shí)間序列數(shù)據(jù)是以天為周期的,通過重采樣我們可以將其轉(zhuǎn)換為按分鐘、小時(shí)、周、月、季度等等的其他周期上。根據(jù)轉(zhuǎn)換的頻率精度可分為向上采樣和向下采樣。

  • 向上采樣:轉(zhuǎn)換到更細(xì)顆粒度的頻率,比如將天轉(zhuǎn)為小時(shí)、分鐘、秒等
  • 向下采樣:轉(zhuǎn)換到更粗顆粒度的頻率,比如將天轉(zhuǎn)為周、月、季度、年等

resample用法

pandas中時(shí)間重采樣的方法是resample(),可以對(duì)series和dataframe對(duì)象操作。由于重采樣默認(rèn)對(duì)索引執(zhí)行變換,因此索引必須是時(shí)間類型,或者通過on指定要重采樣的時(shí)間類型的column列。

用法:
pandas.DataFrame.resample()
pandas.Series.resample()
------
返回:Resampler對(duì)象

參數(shù):

  • rule:定義重采樣的規(guī)則,DateOffset,Timedelta或str類型,當(dāng)為str類型時(shí),其參數(shù)及含義如下表所示
  • axis:指定軸方向,str類型,默認(rèn)為0
    • 0:代表索引
    • 1:代表列
  • closed:指定時(shí)間頻率分組的左右閉合狀態(tài),默認(rèn)M,A,Q,BM,BA,BQ,W右閉合,其余均是左閉合
    • left:指定左閉合
    • right:指定右閉合
  • label:指定左或右邊界作為分組標(biāo)簽,默認(rèn)M,A,Q,BM,BA,BQ,W以右邊界為分組標(biāo)簽,其余均是以左邊界為分組標(biāo)簽
    • left:以左邊界為分組標(biāo)簽
    • right:以右邊界為分組標(biāo)簽
  • kind:將結(jié)果索引轉(zhuǎn)化為指定的時(shí)間類型
    • timestamp:將結(jié)果索引轉(zhuǎn)換為DateTimeIndex
    • period:將結(jié)果索引轉(zhuǎn)換為PeriodIndex
  • on:對(duì)于dataframe,指定被重采樣的列,且列必須是時(shí)間類型
  • level:對(duì)于多級(jí)索引,指定要被重采樣的索引層級(jí),int或str類型。
    • int:索引層級(jí)
    • str:索引層級(jí)名稱
  • origin:調(diào)整時(shí)間分組的起點(diǎn)。Timestamp或str類型,當(dāng)為str時(shí):
    • epoch:1970-01-01
    • start:時(shí)間序列的第一個(gè)值
    • start_day:時(shí)間序列第一天的午夜
    • end:時(shí)間序列的最后一個(gè)值
    • end_day:最后一天的午夜
  • offset:對(duì)origin添加的偏移量,Timedelta或str類型
  • group_keys:指定是否在結(jié)果索引包含分組keys,當(dāng)采樣對(duì)象使用了.apply()方法,默認(rèn)False不包含
圖片

舉例:

1)指定列名

resample默認(rèn)只對(duì)索引對(duì)象操作,換句話說,默認(rèn)情況下索引必須是時(shí)間類型的數(shù)據(jù),否則執(zhí)行會(huì)報(bào)錯(cuò)。

對(duì)于dataframe而言,如不想對(duì)索引重采樣,可以通過on參數(shù)選擇一個(gè)column列代替索引進(jìn)行重采樣操作。

# 將時(shí)間類型索引重置,變?yōu)閏olumn列
df.reset_index(drop=False,inplace=True)
# 通過參數(shù)on指定時(shí)間類型的列名,也可以實(shí)現(xiàn)重采樣
df.resample('W', on='index')['C_0'].sum().head()

由于W是默認(rèn)為右閉且取右邊界作為分組標(biāo)簽的,重采樣后結(jié)果如下。從1/3至1/9(綠色)是完整一周,因此之前非完整部分(黃色)自動(dòng)歸為一周,后面依次按周統(tǒng)計(jì)。

圖片
2)開閉區(qū)間指定

通過closed參數(shù)可以控制左右閉合的狀態(tài)。

默認(rèn)情況下,M,A,Q,BM,BA,BQ,W是右閉合,其余頻率均是左閉合。

下面將天頻率轉(zhuǎn)為W周頻率(默認(rèn)是右閉)。我們手動(dòng)設(shè)置左、右閉合進(jìn)行對(duì)比,可以看出二者區(qū)別,對(duì)于求和結(jié)果的影響。

df=generate_sample_data_datetime()
pd.concat([df.resample('W', closed='left')['C_0'].sum().to_frame(name='left_clsd'),
           df.resample('W', closed='right')['C_0'].sum().to_frame(name='right_clsd')],
          axis=1).head(5)
圖片
3)輸出結(jié)果控制

通過label參數(shù)可以控制輸出結(jié)果的標(biāo)簽。

默認(rèn)情況下,M,A,Q,BM,BA,BQ,W以分組內(nèi)右側(cè)邊界為輸出的標(biāo)簽,其余均是以分組內(nèi)左邊界為標(biāo)簽。

下面將天頻率轉(zhuǎn)為W周頻率(label默認(rèn)右邊界)。我們手動(dòng)設(shè)置label為左、右進(jìn)行對(duì)比,可以看出第二個(gè)采樣分組下輸出標(biāo)簽的區(qū)別。

df=generate_sample_data_datetime()
df.resample('W', label='left')['C_0'].sum().to_frame(name='left_bnd').head(5)
df.resample('W', label='right')['C_0'].sum().to_frame(name='right_bnd').head(5)
圖片
4)聚合統(tǒng)計(jì)

類似于groupby和窗口的聚合方法, 重采樣也適用相關(guān)方法,參考pandas分組8個(gè)常用技巧!

以下是resample采樣后可以支持的描述性統(tǒng)計(jì)和計(jì)算的內(nèi)置函數(shù)。

圖片

內(nèi)置方法下面例子中會(huì)舉例說明。

上采樣

分為上采樣和下采樣。通過以下數(shù)據(jù)舉例說明。

# 生成時(shí)間索引的數(shù)據(jù)
def generate_sample_data_datetime():
    np.random.seed(123)
    number_or_rows = 365*2
    num_cols = 5
    start_date = '2022-01-01'
    cols = ['C_0''C_1''C_2''C_3''C_4']
    df = pd.DataFrame(np.random.randint(1100, size = (number_or_rows, num_cols)), columns=cols)
    df.index = pd.date_range(start=start_date, periods=number_or_rows)
    return df
df=generate_sample_data_datetime()

以上生成數(shù)據(jù)時(shí)間索引是以天為頻率的。

根據(jù)rule參數(shù)含義碼表,H代表小時(shí)的意思,12H也就是12小時(shí)。這是resample非常強(qiáng)大的地方,可以把采樣定位的非常精確。

下面將天的時(shí)間頻率轉(zhuǎn)換為12小時(shí)的頻率,并對(duì)新的頻率分組后求和。

df.resample('12H')['C_0'].sum().head(10)
圖片

比天顆粒度更小的還可以有分鐘、秒、毫秒、微秒、納秒,可根據(jù)實(shí)際情況自行設(shè)定頻率大小。

以上可以看到,上采樣的過程中由于頻率更高導(dǎo)致采樣后數(shù)據(jù)部分缺失。這時(shí)候可以使用上采樣的填充方法,方法如下:

圖片
1)ffill

只有一個(gè)參數(shù)limit控制向前填充的數(shù)量。

下面將天為頻率的數(shù)據(jù)上采樣到8H頻率,向前填充1行和2行的結(jié)果。

df.resample('8H')['C_0'].ffill(limit=1)
圖片
2)bfill

與向前填充用法一樣,下面向后填充1行和2行的結(jié)果。

df.resample('8H')['C_0'].bfill(limit=1)
圖片
3)nearest

該方法為就近填充,無確定方向,可能向前或者向后。參數(shù)也是limit對(duì)填充數(shù)量進(jìn)行控制。以下對(duì)缺失部分按最近數(shù)據(jù)填充1行,結(jié)果如下。

df.resample('8H')['C_0'].nearest(limit=1)
圖片
4)fillna

該方法是前三種方法的集合,參數(shù)method可設(shè)置{'pad'/'ffill','bfill','nearest'}三種,分別代表向前,向后、取最近,同時(shí)也可以設(shè)置limit進(jìn)行數(shù)量控制,因此該方法可以取代前面三種。

df.resample('8H')['C_0'].fillna(method='pad', limit=1)
5)asfreq

該方法可以指定固定值對(duì)所有缺失部分一次性填充,比如對(duì)缺失部分統(tǒng)一填充-999。

df.resample('8H')['C_0'].asfreq(-999)
圖片
6)interpolate

該方法可以使用更高級(jí)的算法進(jìn)行填充。具體方法可通過參數(shù)method設(shè)置,不詳細(xì)介紹,這里以linear線性插值方法舉例。

df.resample('8H').interpolate(method='linear').applymap(lambda x:round(x,2))
圖片

應(yīng)用函數(shù)

1)agg

如果想同時(shí)對(duì)多列的聚合,或者對(duì)單列賦予多個(gè)聚合函數(shù),可以使用agg()聚合方法。

下面進(jìn)行下采樣,將天頻率降為周,并對(duì)多個(gè)變量進(jìn)行多種聚合操作。

df.resample('W').agg(
    {
        'C_0': ['sum''mean'],
        'C_1'lambda x: np.std(x, ddof=1)
    }
).head()
圖片

以上結(jié)果列名顯示了兩個(gè)層級(jí),如果想去掉層級(jí)并自定義結(jié)果中的變量名,可通過以下代碼實(shí)現(xiàn)。

df=generate_sample_data_datetime()
df.resample('W').agg(
        C_0_sum=('C_0','sum'),
        C_0_avg=('C_0','mean'),
        C_1_delta=('C_1'lambda x:x.max()-x.min())
).head()
圖片
2)apply

使用apply函數(shù)也可以達(dá)到agg的聚合效果,以下對(duì)多個(gè)變量進(jìn)行不同的聚合函數(shù),其中也可以自定義函數(shù)。

def agg_func(x):
    names = {
        'C_0_mean': round(x['C_0'].mean(),2),
        'C_1_sum':  x['C_1'].sum(),
        'C_2_max':  x['C_2'].max(),
        'C_3_mean_plus1': round(x['C_3'].mean()+1,2),
    }
    return pd.Series(names, index=[ key for key in names.keys()])

df.resample('W').apply(agg_func).head()
圖片
3)transform

transform在分組系列中介紹過,會(huì)對(duì)原數(shù)據(jù)進(jìn)行分組內(nèi)轉(zhuǎn)換但不改變?cè)饕Y(jié)構(gòu),在重采樣中用法一樣。transform()函數(shù)的使用方法可參考pandas transform 數(shù)據(jù)轉(zhuǎn)換的 4 個(gè)常用技巧!

以下對(duì)C_0變量進(jìn)行采樣分組內(nèi)的累加和排序操作。

df['C_0_cumsum'] = df.resample('W')['C_0'].transform('cumsum')
df['C_0_rank'] = df.resample('W')['C_0'].transform('rank')
df.head(10)
圖片
4)pipe

pipe()被稱為管道函數(shù),可以對(duì)重采樣后的resampler對(duì)象應(yīng)用帶參數(shù)的自定義函數(shù)。pipe()函數(shù)的使用方法可參考pandas一個(gè)優(yōu)雅的高級(jí)應(yīng)用函數(shù)!

它最大的優(yōu)勢(shì)在于可以鏈?zhǔn)?/strong>使用,每次函數(shù)執(zhí)行后的輸出結(jié)果可以作為下一個(gè)函數(shù)的參數(shù),形式如:pipe(func1).pipe(func2),參數(shù)可以是series、dataFrames、groupBy對(duì)象、或者resampler對(duì)象。

通過pipe的鏈?zhǔn)娇梢韵窆艿酪粯影错樞蛞来螆?zhí)行操作,并且只需要一行代碼即可,極大地提高了可讀性。

以下對(duì)下采樣后的C_0和C_1變量進(jìn)行累加求和操作,然后再對(duì)兩個(gè)求和作差。

df['cumsum_delta'] = df.resample('W')['C_0','C_1'] \
    .pipe(lambda x:x.cumsum()) \
    .pipe(lambda x:x['C_1']-x['C_0'])
df.head(10)
圖片

這里當(dāng)pipe應(yīng)用了cumsum()函數(shù)后,與transform一樣可以返回不改變?cè)饕慕Y(jié)果。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多