33 Pandas计算同比环比指标的3种方法

33 Pandas计算同比环比指标的3种方法

同比和环比:环比和同比用于描述统计数据的变化情况

  • 环比:表示本次统计段与相连的上次统计段之间的比较。
    • 比如2010年中国第一季度GDP为G2010Q1亿元,第二季度GDP为G2010Q2亿元,则第二季度GDP环比增长(G2010Q2-G2010Q1)/G2010Q1;
  • 同比:即同期相比,表示某个特定统计段今年与去年之间的比较。
    • 比如2009年中国第一季度GDP为G2009Q1亿元,则2010年第一季度的GDP同比增长为(G2010Q1-G2009Q1)/G2009Q1。


演示步骤: 0. 读取连续3年的天气数据

  1. 方法1:pandas.Series.pct_change
  2. 方法2:pandas.Series.shift
  3. 方法3:pandas.Series.diff

pct_change、shift、diff,都实现了跨越多行的数据计算

0. 读取连续3年的天气数据

import pandas as pd %matplotlib inline fpath = "./datas/beijing_tianqi/beijing_tianqi_2017-2019.csv" df = pd.read_csv(fpath, index_col="ymd", parse_dates=True) df.head(3)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2017-01-01 5℃ -3℃ 霾~晴 南风 1-2级 450 严重污染 6
2017-01-02 7℃ -6℃ 晴~霾 南风 1-2级 246 重度污染 5
2017-01-03 5℃ -5℃ 南风 1-2级 320 严重污染 6
# 替换掉温度的后缀℃ df["bWendu"] = df["bWendu"].str.replace("℃", "").astype('int32') df.head(3)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2017-01-01 5 -3℃ 霾~晴 南风 1-2级 450 严重污染 6
2017-01-02 7 -6℃ 晴~霾 南风 1-2级 246 重度污染 5
2017-01-03 5 -5℃ 南风 1-2级 320 严重污染 6
# 新的df,为每个月的平均最高温 df = df[["bWendu"]].resample("M").mean() # 将索引按照日期升序排列 df.sort_index(ascending=True, inplace=True) df.head()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu
ymd
2017-01-31 3.322581
2017-02-28 7.642857
2017-03-31 14.129032
2017-04-30 23.700000
2017-05-31 29.774194
df.index DatetimeIndex(['2017-01-31', '2017-02-28', '2017-03-31', '2017-04-30', '2017-05-31', '2017-06-30', '2017-07-31', '2017-08-31', '2017-09-30', '2017-10-31', '2017-11-30', '2017-12-31', '2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30', '2018-05-31', '2018-06-30', '2018-07-31', '2018-08-31', '2018-09-30', '2018-10-31', '2018-11-30', '2018-12-31', '2019-01-31', '2019-02-28', '2019-03-31', '2019-04-30', '2019-05-31', '2019-06-30', '2019-07-31', '2019-08-31', '2019-09-30', '2019-10-31', '2019-11-30', '2019-12-31'], dtype='datetime64[ns]', name='ymd', freq='M') df.plot() <matplotlib.axes._subplots.AxesSubplot at 0x13d8d77dc48>

方法1:pandas.Series.pct_change

pct_change方法直接算好了"(新-旧)/旧"的百分比

官方文档地址:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.pct_change.html

df["bWendu_way1_huanbi"] = df["bWendu"].pct_change(periods=1) df["bWendu_way1_tongbi"] = df["bWendu"].pct_change(periods=12) df.head(15)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu bWendu_way1_huanbi bWendu_way1_tongbi
ymd
2017-01-31 3.322581 NaN NaN
2017-02-28 7.642857 1.300277 NaN
2017-03-31 14.129032 0.848658 NaN
2017-04-30 23.700000 0.677397 NaN
2017-05-31 29.774194 0.256295 NaN
2017-06-30 30.966667 0.040051 NaN
2017-07-31 31.612903 0.020869 NaN
2017-08-31 30.129032 -0.046939 NaN
2017-09-30 27.866667 -0.075089 NaN
2017-10-31 17.225806 -0.381849 NaN
2017-11-30 9.566667 -0.444632 NaN
2017-12-31 4.483871 -0.531303 NaN
2018-01-31 1.322581 -0.705036 -0.601942
2018-02-28 4.892857 2.699477 -0.359813
2018-03-31 14.129032 1.887685 0.000000

方法2:pandas.Series.shift

shift用于移动数据,但是保持索引不变

官方文档地址:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.shift.html

# 见识一下shift做了什么事情 # 使用pd.concat合并Series列表变成一个大的df pd.concat( [df["bWendu"], df["bWendu"].shift(periods=1), df["bWendu"].shift(periods=12)], axis=1 ).head(15)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu bWendu bWendu
ymd
2017-01-31 3.322581 NaN NaN
2017-02-28 7.642857 3.322581 NaN
2017-03-31 14.129032 7.642857 NaN
2017-04-30 23.700000 14.129032 NaN
2017-05-31 29.774194 23.700000 NaN
2017-06-30 30.966667 29.774194 NaN
2017-07-31 31.612903 30.966667 NaN
2017-08-31 30.129032 31.612903 NaN
2017-09-30 27.866667 30.129032 NaN
2017-10-31 17.225806 27.866667 NaN
2017-11-30 9.566667 17.225806 NaN
2017-12-31 4.483871 9.566667 NaN
2018-01-31 1.322581 4.483871 3.322581
2018-02-28 4.892857 1.322581 7.642857
2018-03-31 14.129032 4.892857 14.129032
# 环比 series_shift1 = df["bWendu"].shift(periods=1) df["bWendu_way2_huanbi"] = (df["bWendu"]-series_shift1)/series_shift1 # 同比 series_shift2 = df["bWendu"].shift(periods=12) df["bWendu_way2_tongbi"] = (df["bWendu"]-series_shift2)/series_shift2 df.head(15)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu bWendu_way1_huanbi bWendu_way1_tongbi bWendu_way2_huanbi bWendu_way2_tongbi
ymd
2017-01-31 3.322581 NaN NaN NaN NaN
2017-02-28 7.642857 1.300277 NaN 1.300277 NaN
2017-03-31 14.129032 0.848658 NaN 0.848658 NaN
2017-04-30 23.700000 0.677397 NaN 0.677397 NaN
2017-05-31 29.774194 0.256295 NaN 0.256295 NaN
2017-06-30 30.966667 0.040051 NaN 0.040051 NaN
2017-07-31 31.612903 0.020869 NaN 0.020869 NaN
2017-08-31 30.129032 -0.046939 NaN -0.046939 NaN
2017-09-30 27.866667 -0.075089 NaN -0.075089 NaN
2017-10-31 17.225806 -0.381849 NaN -0.381849 NaN
2017-11-30 9.566667 -0.444632 NaN -0.444632 NaN
2017-12-31 4.483871 -0.531303 NaN -0.531303 NaN
2018-01-31 1.322581 -0.705036 -0.601942 -0.705036 -0.601942
2018-02-28 4.892857 2.699477 -0.359813 2.699477 -0.359813
2018-03-31 14.129032 1.887685 0.000000 1.887685 0.000000

方法3. pandas.Series.diff

pandas.Series.diff用于新值减去旧值

官方文档:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.diff.html

pd.concat( [df["bWendu"], df["bWendu"].diff(periods=1), df["bWendu"].diff(periods=12)], axis=1 ).head(15)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu bWendu bWendu
ymd
2017-01-31 3.322581 NaN NaN
2017-02-28 7.642857 4.320276 NaN
2017-03-31 14.129032 6.486175 NaN
2017-04-30 23.700000 9.570968 NaN
2017-05-31 29.774194 6.074194 NaN
2017-06-30 30.966667 1.192473 NaN
2017-07-31 31.612903 0.646237 NaN
2017-08-31 30.129032 -1.483871 NaN
2017-09-30 27.866667 -2.262366 NaN
2017-10-31 17.225806 -10.640860 NaN
2017-11-30 9.566667 -7.659140 NaN
2017-12-31 4.483871 -5.082796 NaN
2018-01-31 1.322581 -3.161290 -2.00
2018-02-28 4.892857 3.570276 -2.75
2018-03-31 14.129032 9.236175 0.00
# 环比 series_diff1 = df["bWendu"].diff(periods=1) df["bWendu_way3_huanbi"] = series_diff1/(df["bWendu"]-series_diff1) # 同比 series_diff2 = df["bWendu"].diff(periods=12) df["bWendu_way3_tongbi"] = series_diff2/(df["bWendu"]-series_diff2) df.head(15)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } <pre><code>.dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } </code></pre>
bWendu bWendu_way1_huanbi bWendu_way1_tongbi bWendu_way2_huanbi bWendu_way2_tongbi bWendu_way3_huanbi bWendu_way3_tongbi
ymd
2017-01-31 3.322581 NaN NaN NaN NaN NaN NaN
2017-02-28 7.642857 1.300277 NaN 1.300277 NaN 1.300277 NaN
2017-03-31 14.129032 0.848658 NaN 0.848658 NaN 0.848658 NaN
2017-04-30 23.700000 0.677397 NaN 0.677397 NaN 0.677397 NaN
2017-05-31 29.774194 0.256295 NaN 0.256295 NaN 0.256295 NaN
2017-06-30 30.966667 0.040051 NaN 0.040051 NaN 0.040051 NaN
2017-07-31 31.612903 0.020869 NaN 0.020869 NaN 0.020869 NaN
2017-08-31 30.129032 -0.046939 NaN -0.046939 NaN -0.046939 NaN
2017-09-30 27.866667 -0.075089 NaN -0.075089 NaN -0.075089 NaN
2017-10-31 17.225806 -0.381849 NaN -0.381849 NaN -0.381849 NaN
2017-11-30 9.566667 -0.444632 NaN -0.444632 NaN -0.444632 NaN
2017-12-31 4.483871 -0.531303 NaN -0.531303 NaN -0.531303 NaN
2018-01-31 1.322581 -0.705036 -0.601942 -0.705036 -0.601942 -0.705036 -0.601942
2018-02-28 4.892857 2.699477 -0.359813 2.699477 -0.359813 2.699477 -0.359813
2018-03-31 14.129032 1.887685 0.000000 1.887685 0.000000 1.887685 0.000000

本文使用 文章同步助手 同步

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容