問題緣起
pandas的DataFrame可以用 diff() 方法實(shí)現(xiàn)相鄰單元數(shù)值相減,但是目前有這樣一個(gè)實(shí)用場景:已知數(shù)據(jù)集是某公司每個(gè)季度當(dāng)年盈利總和的數(shù)據(jù),需要求出該公司每個(gè)季度的盈利數(shù)據(jù)。
換一個(gè)方式表達(dá)就是:每年有四個(gè)季度的數(shù)據(jù),一季度的數(shù)據(jù)就是單一的一季度盈利值,二季度的數(shù)據(jù)是一二兩個(gè)季度盈利值的和,以此類推。
要求出每個(gè)季度單一的盈利值,那么就是除了每年的第一季度,都用自己的值減去前一季度的值——這是一個(gè)** 部分相鄰相減 ** 問題。
解決思路
先用全部數(shù)據(jù)做相鄰相減;然后將每年的第一季度的值替換成原始數(shù)據(jù)。使用到的關(guān)鍵方法是:diff()/update()
注意:update()方法本身返回的一定是None,之前測試時(shí)一直覺得奇怪,print a.update(b),得到的都是 None。原來,正確的姿勢是 a.update(b),這時(shí)候 a 已經(jīng)更新數(shù)據(jù)了,直接 print a,就會(huì)看到結(jié)果。
import pandas as pd
s=pd.Series(['2014-03-31','2014-06-30','2014-09-30','2014-12-31','2015-03-31','2015-06-30','2015-09-30','2016-12-31','2016-03-31','2016-06-30','2016-09-30','2016-12-31'])
income=[12,23,36,56,22,32,35,29,12,45,68,98]
df=pd.DataFrame(income,index=s,columns=['income'])
# 全部相鄰相減
sub_all=df.diff(axis=0)
print sub_all
# 找出需要替換回來的
print '--------現(xiàn)在開始替換回來---------'
retain=df.iloc[[0,4,8]]
sub_all.update(retain)
print sub_all
income
2014-03-31 NaN
2014-06-30 11.0
2014-09-30 13.0
2014-12-31 20.0
2015-03-31 -34.0
2015-06-30 10.0
2015-09-30 3.0
2016-12-31 -6.0
2016-03-31 -17.0
2016-06-30 33.0
2016-09-30 23.0
2016-12-31 30.0
--------現(xiàn)在開始替換回來---------
income
2014-03-31 12.0
2014-06-30 11.0
2014-09-30 13.0
2014-12-31 20.0
2015-03-31 22.0
2015-06-30 10.0
2015-09-30 3.0
2016-12-31 -6.0
2016-03-31 12.0
2016-06-30 33.0
2016-09-30 23.0
2016-12-31 30.0
如何快速找出所有的一季度數(shù)據(jù)
重點(diǎn)是先用 pd.to_datetime()方法將index轉(zhuǎn)為 datetime 對(duì)象,這樣就能很容易的獲得 month
import pandas as pd
import numpy as np
import re,datetime as dt
def get_all_season_one(df_raw,base_key_name):
# df_raw[base_key_name] 是疊加的每季度數(shù)據(jù),即二季度數(shù)據(jù)是一二季度之和
# df_raw.index 每年只有四個(gè)值,是每年的報(bào)告期 yyyy-03-31,yyyy-06-30,yyyy-09-30,yyyy-12-31
# df_raw.index 的數(shù)據(jù)是按照時(shí)間逆序排列
df_raw['diff']= df_raw.diff(axis=0)[base_key_name]
df_raw.index=pd.to_datetime(df_raw.index)
df_raw['season']=df_raw.index.month/3
season_ones=df_raw[df_raw['season']==1]
return season_ones
s=pd.Series(['2014-03-31','2014-06-30','2014-09-30','2014-12-31','2015-03-31','2015-06-30','2015-09-30','2016-12-31','2016-03-31','2016-06-30','2016-09-30','2016-12-31'])
income=[12,23,36,56,22,32,35,29,12,45,68,98]
df=pd.DataFrame(income,index=s,columns=['income'])
print get_all_season_one(df,'income')
執(zhí)行結(jié)果:
income diff season
2014-03-31 12 NaN 1
2015-03-31 22 -34.0 1
2016-03-31 12 -17.0 1