Python科学计算:Pandas
Pandas 提供的基礎數據結構 DataFrame 與 json 的契合度很高,轉換起來就很方便。如果說,在 NumPy 中數據結構是圍繞 ndarray 展開的,那么在 Pandas 中就有Series 和 DataFrame 這兩個核心數據結構,分別代表著一維的序列和二維的表結構。
數據結構:Series 和 DataFrame
Series 是個定長的字典序列。說是定長是因為在存儲的時候,相當于兩個 ndarray,這也是和字典結構最大的不同。因為在字典的結構里,元素的個數是不固定的。
Series有兩個基本屬性:index 和 values。在 Series 結構中,index 默認是 0,1,2……遞增;然而我們也可以自己來指定索引,比如 index=[‘a’, ‘b’, ‘c’, ‘d’]。
import pandas as pd from pandas import Series, DataFrame x1 = Series([1,2,3,4]) x2 = Series(data=[1,2,3,4], index=['a', 'b', 'c', 'd']) print x1 print x20 1 1 2 2 3 3 4 dtype: int64 a 1 b 2 c 3 d 4 dtype: int64我們也可以采用字典的方式來創建 Series,比如:
d = {'a':1, 'b':2, 'c':3, 'd':4} x3 = Series(d) print x3 a 1 b 2 c 3 d 4 dtype: int64Series 的一些特性
索引 可以通過相對位置的下標或者index來訪問Series中的元素import numpy as np import pandas as pd obj2 = pd.Series([4,7,-5,3],index=['d','b','a','c']) print(obj2[1])#引用一個元素一個中括號 print(obj2['b']) print(obj2[[1,2]]) #利用下標索引時兩個中括號 print(obj2['d':'a'])#切片:時一個中括號 print(obj2[['d','c']])#利用index索引時兩個中括號輸出 7 7 b 7 a -5 dtype: int64 d 4 b 7 a -5 dtype: int64 d 4 c 3 dtype: int64重新索引
我們可以使用reindex函數對Series進行重新索引,而不是簡單的改變索引的值:
reindex函數還有一個method屬性,進行差值填充,但是索引必須是單調遞增或者單調遞減的,所以一般用在時間序列這樣的有序數據中:
# obj5 = obj2.reindex(['a','b','c','d','e'],method='ffill') 會報錯 obj3 = pd.Series(['blue','Purple','yellow'],index = [0,2,4]) obj3.reindex(range(6),method='ffill') #輸出 0 blue 1 blue 2 Purple 3 Purple 4 yellow 5 yellow dtype: object數據運算
可以對Series進行numpy中的一些數組運算(如根據布爾型數據進行過濾,標量乘法、應用數學函數等),這些都會保留索引和值之間的鏈接:
Series最重要的一個功能是:它在算術運算中會自動對齊不同索引的數據:
obj4=obj2.reindex(range(6),fill_value=0) print(obj2+obj4)輸出 d NaN b NaN a NaN c NaN 0 NaN 1 NaN 2 NaN 3 NaN 4 NaN 5 NaN dtype: float64Series排序
Series是一維序列,按照index和values進行排序。
numpy中的ndarray多維數組排序則比較靈活;將數據看作矩陣,axis=0(按照列進行排序),axis=1(按照行排序),axis=none打通格式將矩陣看作向量進行全排,axis=-1為默認,實際上與axis=1(按照行排序)
#按照index排序 obj = pd.Series(range(4),index=['d','a','b','c']) obj.sort_index() #輸出: a 1 b 2 c 3 d 0 dtype: int64#按照values排序 obj.sort_values() #輸出: d 0 a 1 b 2 c 3 dtype: int64numpy中的ndarray排序 a = np.array([[4,3,2],[2,4,1]]) print np.sort(a) print np.sort(a, axis=None) print np.sort(a, axis=0) print np.sort(a, axis=1) [[2 3 4][1 2 4]] [1 2 2 3 4 4] [[2 3 1][4 4 2]] [[2 3 4][1 2 4]]統計相關
Series中的實現了sum、mean、max等方法,這里就不詳細介紹了,我們主要介紹求協方差和相關系數的方法:corr方法用于計算相關系數,cov計算協方差;
ndarray中統計函數比較靈活,結合維度axis進行處理。(不歸納研究一下很難一下子就看明白)
obj1 = pd.Series(np.arange(10),index = list('abcdefghij')) obj2 = pd.Series(np.arange(12),index = list('cdefghijklmn')) obj1.corr(obj2) #1.0 obj1.cov(obj2) #6.0#ndarray import numpy as np a = np.array([[1,2,3], [4,5,6], [7,8,9]]) print np.amin(a) print np.amin(a,0) print np.amin(a,1) print np.amax(a) print np.amax(a,0) print np.amax(a,1)1 [1 4 7] [1 2 3] 9 [7 8 9] [3 6 9]對于一個二維數組 a,amin(a) 指的是數組中全部元素的最小值,amin(a,0) 是延著 axis=0 軸的最小值---axis=0 軸是把元素看成了[1,4,7], [2,5,8], [3,6,9] 三個元素;所以最小值為 [1,4,7],amin(a,1) 是延著 axis=1 軸的最小值---axis=1 軸是把元素看成了 [1,2,3], [4,5,6], [7,8,9]三個元素;所以最小值為 [1,2,3]。同理 amax() 是計算數組中元素沿指定軸的最大值。
唯一數、值計數
unique返回沒有排序的唯一值數組,value_counts()返回各數的計數
?
DataFrame
類型數據結構類似數據庫表,它包括了行索引和列索引,我們可以將 DataFrame 看成是由相同索引的 Series 組成的字典類型。
ndarray在構建二維表結構時,一條語句寫列名與格式,一條語句寫行名,填充具體數據。
而DateFrame在創建二維表結構時,列名,填充具體數據一起完成(列索引),行名(行索引)。
在后面的案例中,我一般會用 df, df1, df2 這些作為 DataFrame?數據類型的變量名,我們以例子中的 df2 為例,列索引是?[‘English’, ‘Math’, ‘Chinese’],行索引是?[‘ZhangFei’,GuanYu’, ‘ZhaoYun’, ‘HuangZhon..]所以 df2 的輸出是:
import pandas as pd from pandas import Series, DataFrame data = {'Chinese': [66, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98, 96, 77, 90]} df1= DataFrame(data) df2 = DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei'], columns=['English', 'Math', 'Chinese']) print df1 print df2English Math Chinese ZhangFei 65 30 66 GuanYu 85 98 95 ZhaoYun 92 96 93 HuangZhong 88 77 90 DianWei 90 90 80##########實用ndarray創建二維表結構 import numpy as np import pandas as pd persontype = np.dtype({'names':['name', 'age', 'chinese', 'math', 'english'],'formats':['S32','i', 'i', 'i', 'f']}) peoples = np.array([("ZhangFei",32,75,100, 90),("GuanYu",24,85,96,88.5),("ZhaoYun",28,85,92,96.5),("HuangZhong",29,65,85,100)],dtype=persontype)數據導入和輸出:
Pandas 允許直接從 xlsx,csv 等文件中導入數據,也可以輸出到 xlsx, csv 等文件
import pandas as pd from pandas import Series, DataFrame score = DataFrame(pd.read_excel('data.xlsx')) score.to_excel('data1.xlsx') print scorefor windows import pandas as pd from pandas import Series,DataFrame score =DataFrame(pd.read_excel('C:/Users/baihua/Desktop/123.xlsx')) score.to_excel('C:/Users/baihua/Desktop/111.xlsx') print (score)Anaconda好用之處就體現出來了,不需要下載,因為這些包已經安裝了,直接調用 讀取桌面上的123.xlsx文件 并將文件轉化為111.xlsx存儲需要說明的是,在運行的過程可能會存在缺少 xlrd 和 openpyxl 包的情況,可以通過python腳本中的pip install xird(pip也要自己安裝),也可以用conda終端anaconda prompt中進行安裝:conda install xird;(mac輸入終端即可輸入命令,windows把anaconda prompt叫做終端)。
點這里教你如何安裝anaconda
點這里教你安裝Jupyter notebook
DataFrame一些性質
索引、切片
import pandas as pd import numpy as np data = pd.DataFrame(np.arange(16).reshape((4,4)),index = ['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four']) print(data[:2])#取第0,1行 print('-'*30) print(data[2:])#從第2行開始取 print('-'*30) print(data[['one','two']]) #取對應的列 print('-'*30) print(data.loc[['Ohio','Colorado'],['one','two']])#切片靈活取數,如果是標簽要加loc函數 print('-'*30) print(data.iloc[[1,2],[2,3]])#切片靈活取數,如果是數字下標要加iloc函數輸出one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 ------------------------------one two three four Utah 8 9 10 11 New York 12 13 14 15 ------------------------------one two Ohio 0 1 Colorado 4 5 Utah 8 9 New York 12 13 ------------------------------one two Ohio 0 1 Colorado 4 5 ------------------------------three four Colorado 6 7 Utah 10 11修改數據
data = {'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],'year':[2000,2001,2002,2001,2002],'pop':[1.5,1.7,3.6,2.4,2.9] } frame2 = pd.DataFrame(data,index=['one','two','three','four','five'],columns=['year','state','pop','debt']) #可以通過columns指定列名 frame2['debt']=16.5 #重新給列賦值 print(frame2) print('-'*30) frame2['debt']=np.arange(5)#可以使用一個列表來修改DataFrame print(frame2) print('-'*30) val = pd.Series([-1.2,-1.5,-1.7],index=['two','four','five']) frame2['debt'] = val #可以使用一個Series,此時會根據索引進行精確匹配 print(frame2)輸出year state pop debt one 2000 Ohio 1.5 16.5 two 2001 Ohio 1.7 16.5 three 2002 Ohio 3.6 16.5 four 2001 Nevada 2.4 16.5 five 2002 Nevada 2.9 16.5 ------------------------------year state pop debt one 2000 Ohio 1.5 0 two 2001 Ohio 1.7 1 three 2002 Ohio 3.6 2 four 2001 Nevada 2.4 3 five 2002 Nevada 2.9 4 ------------------------------year state pop debt one 2000 Ohio 1.5 NaN two 2001 Ohio 1.7 -1.2 three 2002 Ohio 3.6 NaN four 2001 Nevada 2.4 -1.5 five 2002 Nevada 2.9 -1.7重新索引
使用reindex方法對DataFrame進行重新索引。對DataFrame進行重新索引,可以重新索引行,列或者兩個都修改,如果只傳入一個參數,則會從新索引行:
frame = pd.DataFrame(np.arange(9).reshape((3,3)),index=[1,4,5],columns=['Ohio','Texas','California']) frame2 = frame.reindex(index=[1,2,4,5]) #沒匹配上則為Na frame2 #輸出Ohio Texas California 1 0.0 1.0 2.0 2 NaN NaN NaN 4 3.0 4.0 5.0 5 6.0 7.0 8.0states = ['Texas','Utah','California'] frame.reindex(columns=states) #輸出Texas Utah California 1 1 NaN 2 4 4 NaN 5 5 7 NaN 8填充數據只能按行填充,此時只能對行進行重新索引: frame = pd.DataFrame(np.arange(9).reshape((3,3)),index = ['a','c','d'],columns = ['Ohio','Texas','California']) frame.reindex(['a','b','c','d'],method = 'bfill') #frame.reindex(['a','b','c','d'],method = 'bfill',columns=states) 報錯輸出 Ohio Texas California a 0 1 2 b 3 4 5 c 3 4 5 d 6 7 8更多內容參考:https://blog.csdn.net/youngbit007/article/details/53067707
函數應用和映射
numpy的元素級數組方法,也可以用于操作Pandas對象:
排序
DataFrame,sort_index可以根據任意軸的索引進行排序,并指定升序降序:
frame = pd.DataFrame(np.arange(8).reshape((2,4)),index=['three','one'],columns=['d','a','b','c']) print(frame) print('-'*30) print(frame.sort_index(0,))#按照行index順序 print('-'*30) print(frame.sort_index(1,ascending=False)) #按照列index順序·,#默認升序,降序可在括號加ascending=False print('-'*30) print(frame.sort_index(by=['a','b']))#按照指定列排序 print('-'*30) print(frame.sort_values(by=['a','b'])) d a b c three 0 1 2 3 one 4 5 6 7 ------------------------------d a b c one 4 5 6 7 three 0 1 2 3 ------------------------------d a b c three 0 1 2 3 one 4 5 6 7 ------------------------------d c b a three 0 3 2 1 one 4 7 6 5 ------------------------------d a b c three 0 1 2 3 one 4 5 6 7 ------------------------------d a b c three 0 1 2 3 one 4 5 6 7匯總和計算描述統計
DataFrame中的實現了sum、mean、max等方法,我們可以指定進行匯總統計的軸,同時,也可以使用describe函數查看基本所有的統計項:
df = pd.DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index=['a','b','c','d'],columns=['one','two']) #輸出one two a 1.40 NaN b 7.10 -4.5 c NaN NaN d 0.75 -1.3df.sum(axis=0) #按列,Na默認不會被計算 #輸出 one 9.25 two -5.80 dtype: float64#Na會被自動排除,可以使用skipna選項來禁用該功能 df.mean(axis=1,skipna=False)#按行,有Na項不參與計算 #輸出 a NaN b 1.300 c NaN d -0.275 dtype: float64#idxmax返回間接統計,是達到最大值的索引 df.idxmax() #輸出 one b two d dtype: object#describe返回的是DataFrame的匯總統計 #非數值型的與數值型的統計返回結果不同 df.describe() #輸出 one two count 3.000000 2.000000 mean 3.083333 -2.900000 std 3.493685 2.262742 min 0.750000 -4.500000 25% 1.075000 -3.700000 50% 1.400000 -2.900000 75% 4.250000 -2.100000 max 7.100000 -1.300000DataFrame也實現了corr和cov方法來計算一個DataFrame的相關系數矩陣和協方差矩陣,同時DataFrame也可以與Series求解相關系數。
Series有corr,cov計算相關系數與協方差;DataFrame同樣可以
相關系數通常指兩個隨機變量之間,多個變量之間的相關系數稱為復相關系數。
協方差是與相關系數一起使用的,協方差>0,表示兩個隨機變量之間有正向相關關系,=0,表示兩個變量之間不相關;<0,表示負相關
frame1 = pd.DataFrame(np.random.randn(3,3),index=list('abc'),columns=list('abc')) frame1.corr #輸出 <bound method DataFrame.corr of a b c a 1.253773 0.429059 1.535575 b -0.113987 -2.837396 -0.894469 c -0.548208 0.834003 0.994863>frame1.cov() #輸出 a b c a 0.884409 0.357304 0.579613 b 0.357304 4.052147 2.442527 c 0.579613 2.442527 1.627843#corrwith用于計算每一列與Series的相關系數 frame1.corrwith(frame1['a']) #輸出 a 1.000000 b 0.188742 c 0.483065 dtype: float64數據清洗
import numpy as np import pandas as pd data = {'Chinese': [66, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98, 96, 77, 90]} df2 = DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei'], columns=['English', 'Math', 'Chinese'])English Math Chinese ZhangFei 65 30 66 GuanYu 85 98 95 ZhaoYun 92 96 93 HuangZhong 88 77 90 DianWei 90 90 801. 刪除 DataFrame 中的不必要的列或行
比如我們想把“語文”這列刪掉。
df2 = df2.drop(columns=['Chinese'])想把“張飛”這行刪掉。
df2.drop(index='ZhangFei')2. 重命名列名 columns,讓列表名更容易識別
df2.rename(columns={'Chinese': 'YuWen', 'English': 'Yingyu'}, inplace = True)3. 去重復的值
df = df.drop_duplicates() # 去除重復行4. 格式問題更改數據格式
比如我們把 Chinese 字段的值改成 str 類型,或者 int64 可以這么寫:
df2['Chinese'].astype('str') df2['Chinese'].astype(np.int64)5. 數據間的空格
這時想要刪除數據間的空格,我們就可以使用 strip 函數:
# 刪除左右兩邊空格 df2['Chinese']=df2['Chinese'].map(str.strip) # 刪除左邊空格 df2['Chinese']=df2['Chinese'].map(str.lstrip) # 刪除右邊空格 df2['Chinese']=df2['Chinese'].map(str.rstrip)刪除特殊符號:比如 Chinese 字段里有美元符號,我們想把這個刪掉,可以這么寫:
df2['Chinese']=df2['Chinese'].str.strip('$')6.大小寫轉換
在 Python 里直接使用 upper(), lower(), title() 函數,方法如下:
# 全部大寫 df2.columns = df2.columns.str.upper() # 全部小寫 df2.columns = df2.columns.str.lower() # 首字母大寫 df2.columns = df2.columns.str.title()7.查找空值
使用 Pandas 中的 isnull 函數進行查找。比如,我們輸入一個數據表如下
以針對數據表 df 進行 df.isnull()
如果我想知道哪列存在空值,可以使用 df.isnull().any()
使用 apply 函數對數據進行清洗
比如我們想對 name 列的數值都進行大寫轉化可以用:
df['name'] = df['name'].apply(str.upper)我們也可以定義個函數,在 apply 中進行使用。比如定義?double_df 函數是將原來的數值 *2 進行返回。然后對 df1 中的“語文”列的數值進行 *2 處理,可以寫成:
def double_df(x):return 2*x df1[u'語文'] = df1[u'語文'].apply(double_df)也可以這樣用:
def plus(df,n,m):df['new1'] = (df[u'語文']+df[u'英語']) * mdf['new2'] = (df[u'語文']+df[u'英語']) * nreturn df df1 = df1.apply(plus,axis=1,args=(2,3,))axis=0 是列運算;axis=1 是行運算。args 是傳遞的兩個參數,即 n=2, m=3;在 plus 函數中使用到了 n 和 m,從而生成新的 df。
數據統計
Pandas 和 NumPy 一樣,都有常用的統計函數,如果遇到空值 NaN,會自動排除。
表格中有一個 describe() 函數,統計函數千千萬,describe() 函數最簡便
df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) print df1.describe()數據表合并
比如我要創建兩個 DataFrame:
df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) df2 = DataFrame({'name':['ZhangFei', 'GuanYu', 'A', 'B', 'C'], 'data2':range(5)})1. 基于指定列進行連接比如我們可以基于 name 這列進行連接。
df3 = pd.merge(df1, df2, on='name')?
2. inner 內連接
inner 內鏈接是 merge 合并的默認情況,inner 內連接其實也就是鍵的交集在這里 df1, df2 相同的鍵是 name,所以是基于 name 字段做的連接:
df3 = pd.merge(df1, df2, how='inner')3. left 左連接
df3 = pd.merge(df1, df2, how='left')如何用 SQL 方式打開 Pandas
這里給你介紹個工具:pandasql。
pandasql 中的主要函數是 sqldf,它接收兩個參數:一個 SQL 查詢語句,還有一組環境變量 globals() 或 locals()。這樣我們就可以在 Python 里直接用 SQL 語句中對 DataFrame 進行操作,舉個例子:
import pandas as pd from pandas import DataFrame from pandasql import sqldf, load_meat, load_births df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)}) pysqldf = lambda sql: sqldf(sql, globals()) sql = "select * from df1 where name ='ZhangFei'" print pysqldf(sql)當然你會看到我們用到了 lambda,lambda 在 python 中算是使用頻率很高的,那 lambda 是用來做什么的呢?它實際上是用來定義一個匿名函數的具體的使用形式為:
lambda argument_list: expression pysqldf = lambda sql: sqldf(sql, globals())在這個例子里,輸入的參數是 sql,返回的結果是 sqldf 對 sql 的運行結果,當然 sqldf 中也輸入了 globals 全局參數,因為在 sql 中有對全局參數??df1 的使用。
?
練習題
對于下表的數據,請使用 Pandas 中的 DataFrame 進行創建,并對數據進行清洗。同時新增一列“總和”計算每個人的三科成績之和。
import numpy as np import pandas as pd data = {'Chinese': [None, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98, 96, 77, 90]} df2 = pd.DataFrame(data,index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei'], columns=['English', 'Math', 'Chinese']) df2=df2.reindex(index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei','CaoCao']) print (df2) print('--'*20) df2[['English','Math']].fillna(df2[['English','Math']].mean(),inplace=True)#成None df2['English'].fillna(df2['English'].mean(),inplace=True)#一次只能改一個 df2['Math'].fillna(df2['Math'].mean(),inplace=True)#一次只能改一個 df2['Chinese'].fillna(df2['Chinese'].mean(),inplace=True) print(df2) df2['total']=df2['English']+df2['Math']+df2['Chinese'] print('三科總成績:',df2) print('--'*20) print(df2.describe()) print('--'*20) def total_score(df2):df2['total']=df2['English']+df2['Math']+df2['Chinese']return df2 df2.apply(total_score,axis=1)#apply(函數名,維度,args=參數) df2.sort_values('total',ascending=False,inplace=True) print('三科總成績:',df2)?
結果English Math Chinese ZhangFei 65.0 30.0 NaN GuanYu 85.0 98.0 95.0 ZhaoYun 92.0 96.0 93.0 HuangZhong 88.0 77.0 90.0 DianWei 90.0 90.0 80.0 CaoCao NaN NaN NaN ----------------------------------------English Math Chinese ZhangFei 65.0 30.0 89.5 GuanYu 85.0 98.0 95.0 ZhaoYun 92.0 96.0 93.0 HuangZhong 88.0 77.0 90.0 DianWei 90.0 90.0 80.0 CaoCao 84.0 78.2 89.5 三科總成績: English Math Chinese total ZhangFei 65.0 30.0 89.5 184.5 GuanYu 85.0 98.0 95.0 278.0 ZhaoYun 92.0 96.0 93.0 281.0 HuangZhong 88.0 77.0 90.0 255.0 DianWei 90.0 90.0 80.0 260.0 CaoCao 84.0 78.2 89.5 251.7 ----------------------------------------English Math Chinese total count 6.000000 6.000000 6.000000 6.000000 mean 84.000000 78.200000 89.500000 251.700000 std 9.777525 25.190474 5.157519 35.059378 min 65.000000 30.000000 80.000000 184.500000 25% 84.250000 77.300000 89.500000 252.525000 50% 86.500000 84.100000 89.750000 257.500000 75% 89.500000 94.500000 92.250000 273.500000 max 92.000000 98.000000 95.000000 281.000000 ---------------------------------------- 三科總成績: English Math Chinese total ZhaoYun 92.0 96.0 93.0 281.0 GuanYu 85.0 98.0 95.0 278.0 DianWei 90.0 90.0 80.0 260.0 HuangZhong 88.0 77.0 90.0 255.0 CaoCao 84.0 78.2 89.5 251.7 ZhangFei 65.0 30.0 89.5 184.5參考文獻:
python中DataFrame靈活取數
pandas中reindex用法
?
總結
以上是生活随笔為你收集整理的Python科学计算:Pandas的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 决策树数学原理(ID3,c4.5,car
- 下一篇: python扫盲系列(5)--列表、元组