经济学中的定量分析python_(转)Python中的结构化数据分析利器-Pandas简介
Pandas是python的一個數據分析包,最初由AQR Capital Management于2008年4月開發,并于2009年底開源出來,目前由專注于Python數據包開發的PyData開發team繼續開發和維護,屬于PyData項目的一部分。Pandas最初被作為金融數據分析工具而開發出來,因此,pandas為時間序列分析提供了很好的支持。 Pandas的名稱來自于面板數據(panel data)和python數據分析(data analysis)。panel data是經濟學中關于多維數據集的一個術語,在Pandas中也提供了panel的數據類型。 這篇文章會介紹一些Pandas的基本知識,偷了些懶其中采用的例子大部分會來自官方的10分鐘學Pandas。我會加上個人的理解,幫助大家記憶和學習。
Pandas中的數據結構
Series:一維數組,與Numpy中的一維array類似。二者與Python基本的數據結構List也很相近,其區別是:List中的元素可以是不同的數據類型,而Array和Series中則只允許存儲相同的數據類型,這樣可以更有效的使用內存,提高運算效率。
Time- Series:以時間為索引的Series。
DataFrame:二維的表格型數據結構。很多功能與R中的data.frame類似。可以將DataFrame理解為Series的容器。以下的內容主要以DataFrame為主。
Panel :三維的數組,可以理解為DataFrame的容器。
創建DataFrame
首先引入Pandas及Numpy:
import pandas as pd
import numpy as np
官方推薦的縮寫形式為pd,你可以選擇其他任意的名稱。 DataFrame是二維的數據結構,其本質是Series的容器,因此,DataFrame可以包含一個索引以及與這些索引聯合在一起的Series,由于一個Series中的數據類型是相同的,而不同Series的數據結構可以不同。因此對于DataFrame來說,每一列的數據結構都是相同的,而不同的列之間則可以是不同的數據結構。或者以數據庫進行類比,DataFrame中的每一行是一個記錄,名稱為Index的一個元素,而每一列則為一個字段,是這個記錄的一個屬性。 創建DataFrame有多種方式:
以字典的字典或Series的字典的結構構建DataFrame,這時候的最外面字典對應的是DataFrame的列,內嵌的字典及Series則是其中每個值。
d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']),'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
可以看到d是一個字典,其中one的值為Series有3個值,而two為Series有4個值。由d構建的為一個4行2列的DataFrame。其中one只有3個值,因此d行one列為NaN(Not a Number)--Pandas默認的缺失值標記。
從列表的字典構建DataFrame,其中嵌套的每個列表(List)代表的是一個列,字典的名字則是列標簽。這里要注意的是每個列表中的元素數量應該相同。否則會報錯:
ValueError: arrays must all be same length
從字典的列表構建DataFrame,其中每個字典代表的是每條記錄(DataFrame中的一行),字典中每個值對應的是這條記錄的相關屬性。
d = [{'one' : 1,'two':1},{'one' : 2,'two' : 2},{'one' : 3,'two' : 3},{'two' : 4}]
df = pd.DataFrame(d,index=['a','b','c','d'],columns=['one','two'])
df.index.name='index'
以上的語句與以Series的字典形式創建的DataFrame相同,只是思路略有不同,一個是以列為單位構建,將所有記錄的不同屬性轉化為多個Series,行標簽冗余,另一個是以行為單位構建,將每條記錄轉化為一個字典,列標簽冗余。使用這種方式,如果不通過columns指定列的順序,那么列的順序會是隨機的。
個人經驗是對于從一些已經結構化的數據轉化為DataFrame似乎前者更方便,而對于一些需要自己結構化的數據(比如解析Log文件,特別是針對較大數據量時),似乎后者更方便。創建了DataFrame后可以通過index.name屬性為DataFrame的索引指定名稱。
DataFrame轉換為其他類型
df.to_dict(outtype='dict')
outtype的參數為‘dict’、‘list’、‘series’和‘records’。 dict返回的是dict of dict;list返回的是列表的字典;series返回的是序列的字典;records返回的是字典的列表
查看數據
head和tail方法可以顯示DataFrame前N條和后N條記錄,N為對應的參數,默認值為5。這通常是拿到DataFrame后的第一個命令,可以方便的了解數據內容和含義。
df.head()
onetwo
index
a
1
1
b
2
2
c
3
3
d
NaN
4
4 rows × 2 columns
R中的對應函數:
head(df)
df.tail()
onetwo
index
a
1
1
b
2
2
c
3
3
d
NaN
4
4 rows × 2 columns
index(行)和columns(列)屬性,可以獲得DataFrame的行和列的標簽。這也是了解數據內容和含義的重要步驟。
df.index
Index([u'a', u'b', u'c', u'd'], dtype='object')
查看字段名
df.columns
Index([u'one', u'two'], dtype='object')
decribe方法可以計算各個列的基本描述統計值。包含計數,平均數,標準差,最大值,最小值及4分位差。
df.describe()
onetwo
count
3.0
4.000000
mean
2.0
2.500000
std
1.0
1.290994
min
1.0
1.000000
25%
1.5
1.750000
50%
2.0
2.500000
75%
2.5
3.250000
max
3.0
4.000000
8 rows × 2 columns
R中的對應函數:
summary(df)
行列轉置
df.T
indexabcd
one
1
2
3
NaN
two
1
2
3
4
2 rows × 4 columns
排序
DataFrame提供了多種排序方式。
df.sort_index(axis=1, ascending=False)
sort_index可以以軸的標簽進行排序。axis是指用于排序的軸,可選的值有0和1,默認為0即行標簽(Y軸),1為按照列標簽排序。 ascending是排序方式,默認為True即降序排列。
df.sort(columns='two')
df.sort(columns=['one','two'],ascending=[0,1])
DataFrame也提供按照指定列進行排序,可以僅指定一個列作為排序標準(以單獨列名作為columns的參數),也可以進行多重排序(columns的參數為一個列名的List,列名的出現順序決定排序中的優先級),在多重排序中ascending參數也為一個List,分別與columns中的List元素對應。
讀寫數據
DataFrame可以方便的讀寫數據文件,最常見的文件為CSV或Excel。Pandas讀寫Excel文件需要openpyxl(Excel 2007),?xlrd/xlwt(Excel?2003)。
從CSV中讀取數據:
df = pd.read_csv('foo.csv')
R中的對應函數:
df = read.csv('foo.csv')
將DataFrame寫入CSV:
df.to_csv('foo.csv')
R中的對應函數:
df.to.csv('foo.csv')
從Excel中讀取數據:
xls = ExcelFile('foo.xlsx')
xls.parse('sheet1', index_col=None, na_values=['NA'])
先定義一個Excel文件,用xls.parse解析sheet1的內容,index_col用于指定index列,na_values定義缺失值的標識。
將DataFrame寫入Excel文件:
df.to_excel('foo.xlsx', sheet_name='sheet1')
默認的sheet為sheet1,也可以指定其他sheet名。
數據切片
通過下標選取數據:
df['one']
df.one
以上兩個語句是等效的,都是返回df名稱為one列的數據,返回的為一個Series。
df[0:3]
df[0]
下標索引選取的是DataFrame的記錄,與List相同DataFrame的下標也是從0開始,區間索引的話,為一個左閉右開的區間,即[0:3]選取的為1-3三條記錄。與此等價,還可以用起始的索引名稱和結束索引名稱選取數據:
df['a':'b']
有一點需要注意的是使用起始索引名稱和結束索引名稱時,也會包含結束索引的數據。以上兩種方式返回的都是DataFrame。
使用標簽選取數據:
df.loc[行標簽,列標簽]
df.loc['a':'b']#選取ab兩行數據
df.loc[:,'one']#選取one列的數據
df.loc的第一個參數是行標簽,第二個參數為列標簽(可選參數,默認為所有列標簽),兩個參數既可以是列表也可以是單個字符,如果兩個參數都為列表則返回的是DataFrame,否則,則為Series。
使用位置選取數據:
df.iloc[行位置,列位置]
df.iloc[1,1]#選取第二行,第二列的值,返回的為單個值
df.iloc[0,2],:]#選取第一行及第三行的數據
df.iloc[0:2,:]#選取第一行到第三行(不包含)的數據
df.iloc[:,1]#選取所有記錄的第一列的值,返回的為一個Series
df.iloc[1,:]#選取第一行數據,返回的為一個Series
PS:loc為location的縮寫,iloc則為integer & location的縮寫
更廣義的切片方式是使用.ix,它自動根據你給到的索引類型判斷是使用位置還是標簽進行切片
df.ix[1,1]
df.ix['a':'b']
通過邏輯指針進行數據切片:
df[邏輯條件]
df[df.one >= 2]#單個邏輯條件
df[(df.one >=1 ) & (df.one < 3) ]#多個邏輯條件組合
這種方式獲得的數據切片都是DataFrame。
基本運算
Pandas支持基本的運算及向量化運算。
df.mean()#計算列的平均值,參數為軸,可選值為0或1.默認為0,即按照列運算
df.sum(1)#計算行的和
df.apply(lambda x: x.max() - x.min())#將一個函數應用到DataFrame的每一列,這里使用的是匿名lambda函數,與R中apply函數類似
設置索引
df.set_index('one')
重命名列
df.rename(columns={u'one':'1'}, inplace=True)
查看每個列的數據類型
df.dtypes
R中的對應函數:
str(df)
查看最大值/最小值
pd.Series.max()
pd.Series.idxmax()
重設索引
df.reset_index(inplace=True)
改變數據類型
df['A'].astype(float)
計算Series每個值的頻率
df['A'].value_counts()
R的對應函數:
table(df['A'])
字符方法
pandas提供許多向量化的字符操作,你可以在str屬性中找到它們
s.str.lower()
s.str.len()
s.str.contains(pattern)
DataFrame的合并
Contact:
ds = [{'one' : 4,'two':2},{'one' : 5,'two' : 3},{'one' : 6,'two' : 4},{'two' : 7,'three':10}]
dfs = pd.DataFrame(ds,index=['e','f','g','h'])
##構建一個新的DataFrame,dfs
df_t=pd.concat([df,dfs])#合并兩個DataFrame
Merge(類似SQL中的Join操作):
left = pd.DataFrame({'key': ['foo1', 'foo2'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo1', 'foo2'], 'rval': [4, 5]})
#構建了兩個DataFrame
pd.merge(left, right, on='key')#按照key列將兩個DataFrame join在一起
DataFrame中的Group by:
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three','two', 'two', 'one', 'three'],
'C' :randn(8), 'D' : randn(8)});
df.groupby('A').sum()#按照A列的值分組求和
df.groupby(['A','B']).sum()##按照A、B兩列的值分組求和
對應R函數:
tapply()
在實際應用中,先定義groups,然后再對不同的指標指定不同計算方式。
groups = df.groupby('A')#按照A列的值分組求和
groups['B'].sum()##按照A列的值分組求B組和
groups['B'].count()##按照A列的值分組B組計數
默認會以groupby的值作為索引,如果不將這些值作為索引,則需要使用as_index=False
df.groupby(['A','B'], as_index=False).sum()
構建透視表
使用pivot_table和crosstab都可以創建數據透視表
df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,'B' : ['A', 'B', 'C'] * 4,
'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D' : np.random.randn(12), 'E' : np.random.randn(12)})
pd.pivot_table(df, values = 'D', rows = ['A', 'B'], cols = ['C'])#以A、B為行標簽,以C為列標簽將D列的值匯總求和
pd.crosstab(rows = ['A', 'B'], cols = ['C'], values = 'D')#以A、B為行標簽,以C為列標簽將D列的值匯總求和
時間序列分析
時間序列也是Pandas的一個特色。時間序列在Pandas中就是以Timestamp為索引的Series。
pandas提供to_datetime方法將代表時間的字符轉化為Timestamp對象:
s = '2013-09-16 21:00:00'
ts = pd.to_datetime(s)
有時我們需要處理時區問題:
ts=pd.to_datetime(s,utc=True).tz_convert('Asia/Shanghai')
構建一個時間序列:
rng = pd.date_range('1/1/2012', periods=5, freq='M')
ts = pd.Series(randn(len(rng)), index=rng)
Pandas提供resample方法對時間序列的時間粒度進行調整:
ts_h=ts.resample('H', how='count')#M,5Min,1s
以上是將時間序列調整為小時,還可以支持月(M),分鐘(Min)甚至秒(s)等。
畫圖
Pandas也支持一定的繪圖功能,需要安裝matplot模塊。
比如前面創建的時間序列,通過plot()就可以繪制出折線圖,也可以使用hist()命令繪制頻率分布的直方圖。
關于Panda作圖,請查看另一篇博文:用Pandas作圖
以上是關于Pandas的簡單介紹,其實除了Pandas之外,Python還提供了多個科學計算包,比如Numpy,Scipy,以及數據挖掘的包:Scikit Learn,Orage,NLTK等,感興趣的同學可以了解一下。
總結
以上是生活随笔為你收集整理的经济学中的定量分析python_(转)Python中的结构化数据分析利器-Pandas简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue中引用js_从JS中的内存管理说起
- 下一篇: python建立数据库并序列化_pyth