一 . pandas簡單介紹
一、pandas是一個強大的Python數據分析的工具包。
二、pandas是基於NumPy構建的。php
三、pandas的主要功能html
- 具有對其功能的數據結構DataFrame、Series
- 集成時間序列功能
- 提供豐富的數學運算和操做
- 靈活處理缺失數據
四、安裝方法:pip install pandas
五、引用方法:import pandas as pdpython
二 . Series
1 . Series 數組
Series是一種相似於一維數組的對象 , 有下面兩部分組成 : 數據結構
-
- values : 一組數據(ndarray類型)
- index : 相關的數據索引標籤
2 . series的建立 app
1) . 由列表或numpy數組建立 : 默認索引爲 0 到 N-1 的整數 dom
2) . 由字典建立 : 不能再使用index , 可是依然存在默認索引函數
注意 : 數據源必須是一維數組工具
二-1 . series特性
1 . series 的索引post
可使用中括號取單個索引(此時返回的是元素類型) , 或者中括號裏一個列表取多個索引(此時返回的是一個Series類型) .
(1) . 顯示索引 :
- 使用 index 中的元素做爲索引值
- 使用 s.loc [ ] (推薦) , 注意 : loc 中括號中放置的必定是顯示索引
注意 : 此時是閉區間
(2) . 隱式索引 :
- 使用整數做爲索引值
- 使用 .iloc [ ] (推薦) : iloc 中的括號中必需要放置隱式索引
注意 : 此時是半開區間
2 . 切片
(1) . 顯示索引切片 : index 和 loc
(2) . 隱式索引切片 : 整數索引值 和 iloc
3 . 基本概念
能夠把series當作是一個定長的有序字典
(1) . 向Series增長一行 , 至關於給字典增長一組鍵值對. 能夠經過 shape , size , index , values 等獲得 series的屬性 .
(2) . 可使用 .head() 和 .tail 分別查看前n個和後n個值
4 . 去重
.unique()
二-2 . Series數據對齊
1 . pandas在運算時,會按索引進行對齊而後運算,若是存在不一樣的索引,則結果的索引是兩個操做索引的並集.
2 . series 之間的運算
1) . + - * /
2) . add() , sub() , mul() , div() ,
注意 : 如何在兩個Series對象相加時將缺失值設爲0?
sr1.add(sr2, fill_value=0)
3) . 在運算中自動對齊不一樣索引的數據 , 若是索引對不齊,則補NaN
二-3 . Series數據缺失
當索引沒有對應值的時候,可能會出現缺失數據顯示NaN的狀況
一、缺失數據:使用NaN(Not a Number)來表示缺失數據。其值等於np.nan。內置的None值也會被當作NaN處理。
二、處理缺失數據的相關方法:
- dropna() 過濾掉值爲NaN的行
- fillna() 填充缺失數據
- isnull() 返回布爾數組,缺失值對應爲True
- notnull() 返回布爾數組,缺失值對應爲False
三、過濾缺失數據:sr.dropna() 或 sr[data.notnull()]
四、填充缺失數據:fillna(0)
三 . DataFrame
DataFrame是一個表格型的數據結構.
DataFrame由必定順序排列的多列數據組成
DataFrame既有行索引,也有列索引
- 行索引:index
- 列索引:columns
- 值:values
三-1 . DataFrame的建立
導包 : from pandas import DataFrame
最經常使用的方法是傳遞一個字典來建立。DataFrame以字典的鍵做爲每一【列】的名稱,以字典的值(一個數組)做爲每一列。
此外,DataFrame會自動加上每一行的索引。
使用字典建立的DataFrame後,則columns參數將不可被使用。
同Series同樣,若傳入的列與字典的鍵不匹配,則相應的值爲NaN。
1 . 使用 ndarray 建立DataFrame
2 . 使用 字典 建立 DataFrame
三-2 . DataFrame查看數據
查看數據經常使用屬性及方法: index 獲取索引 T 轉置 columns 獲取列索引 values 獲取值數組 describe() 獲取快速統計 DataFrame各列name屬性:列名 rename(columns={}) #字典建立不能用
三-3 . DataFrame的索引與切片
DataFrame有行索引和列索引。
DataFrame一樣能夠經過標籤和位置兩種方法進行索引和切片。
DataFrame使用索引切片:
- 方法1:兩個中括號,先取列再取行。 df['A'][0]
- 方法2(推薦):使用loc/iloc屬性,一箇中括號,逗號隔開,先取行再取列。
loc屬性:解釋爲標籤
iloc屬性:解釋爲下標
向DataFrame對象中寫入值時只使用方法2
行/列索引部分能夠是常規索引、切片、布爾值索引、花式索引任意搭配。(注意:兩部分都是花式索引時結果可能與預料的不一樣)
1 . DataFrame的索引
(1) . 對列進行索引
(2) . 對行進行索引
- 使用 .loc [] 加index來進行索引
- 使用 .iloc [] 加整數來進行索引
一樣返回一個 Series , index爲原來的 columns
(3) . 對元素進行索引
- 使用列索引
- 使用行索引(iloc[3,1] or loc['C','q']) 行索引在前,列索引在後
2 . 切片
注意 : 直接使用中括號時 :
- 索引表示列索引
- 切片表示行切片
三-4 . DataFrame的運算
DataFrame之間的運算同Series同樣
- 在運算中自動對齊不一樣索引的數據
- 若是索引不對應,則補NaN
三-5 . DataFrame的數據對齊和數據缺失
DataFrame對象在運算時,一樣會進行數據對齊,行索引與列索引分別對齊。
結果的行索引與列索引分別爲兩個操做數的行索引與列索引的並集。
注意 :
- None
None是Python自帶的,其類型爲python object。所以,None不能參與到任何計算中。
- np.nan (NaN)
np.nan是浮點類型,能參與到計算中。但計算的結果老是NaN。
案例 :
pandas中None與np.nan都視做np.nan
DataFrame處理缺失數據的相關方法:
- dropna(axis=0,where=‘any’,…) 過濾掉值爲NaN的行
- 注意 : 在dropna中, axis=0 表示行,與常規相反
- fillna() 填充缺失數據
- 參數 : method
- bfill : 選擇向後填充(和後面數相同) df.fillna(method='bfill',axis=1)
- ffill : 選擇向前填充 df.fillna(method='ffill',axis=1)
- 參數 : method
- isnull() 返回布爾數組,缺失值對應爲True
- 檢查條件 isnull.any(axis=1)
- notnull() 返回布爾數組,缺失值對應爲False
- 檢查條件 notnull.all(axis=1)
三-6 . 建立多層DataFrame
- 取得列:df['col'] df[[c1,c2]] df.loc[:,col]
- 取行:df.loc['index'] df[index1:inde2]
1 . 隱式構造
最多見的方法是給DataFrame構造函數的index或者columns參數傳遞兩個或更多的數組
DataFrame(data=np.random.randint(0,100,size=(2,2)),columns=[['a','b'],['A','B']])
2 . 顯示構造
pd.MultiIndex.from_product
col=pd.MultiIndex.from_product([['qizhong','qimo'], ['chinese','math']]) #建立DF對象 df = DataFrame(data=np.random.randint(60,120,size=(2,4)),index=['tom','jay'], columns=col)
3 . 多層行索引
逐級降層
df['qimo']
df['qimo']['math']
# 獲取tom期中全部科目的考試成績 df['qizhong'].loc['tom']
注意
在對行索引的時候,若一級行索引還有多個,對二級行索引會遇到問題!也就是說,沒法直接對二級索引進行索引,必須讓
二級索引變成一級索引後才能對其進行索引!
總結:
訪問一列或多列 直接用中括號[columnname] [[columname1,columnname2...]]
訪問一行或多行 .loc[indexname]
訪問某一個元素 .loc[indexname,columnname] 獲取李四期中的php成績
行切片 .[index1:index2] 獲取張三李四的期中成績
列切片 .loc[:,column1:column2] 獲取張三李四期中的php和c++成績
三-7 . 聚合操做
所謂的聚合操做:平均數,方差,最大值,最小值…
df.sum(axis=0)
df.mean()
三-8 . pandas的拼接操做
pandas的拼接分爲兩種:
- 級聯:pd.concat, pd.append
- 合併:pd.merge, pd.join
1 . 使用pd.concat()級聯
pandas使用pd.concat函數,與np.concatenate函數相似,只是多了一些參數:
objs axis=0 keys join='outer' / 'inner':表示的是級聯的方式,outer會將全部的項進行級聯(忽略匹配和不匹配), 而inner只會將匹配的項級聯到一塊兒,不匹配的不級聯 ignore_index=False
導包 :
import numpy as np import pandas as pd from pandas import Series,DataFrame
(1) . 匹配級聯
df1 = DataFrame(data=np.random.randint(0,100,size=(3,3)),index=['a','b','c'],columns=['A','B','C']) df2 = DataFrame(data=np.random.randint(0,100,size=(3,3)),index=['a','d','c'],columns=['A','d','C'])
(2) . 不匹配級聯
不匹配指的是級聯的維度索引不一致.例如 : 縱向級聯時索引不一致,橫向級聯時索引不一致
鏈接方式 :
-
-
- 外鏈接 : 補NaN (默認方式)
- 內鏈接 : 只鏈接匹配的項
-
pd.concat((df1,df2),axis=1,join='outer') # 內鏈接
(3) . 使用df.append() 函數添加
因爲在後面級聯的使用很是廣泛,所以有一個函數append專門用於在後面添加
df1.append(df2) #列索引必須一致
2 . 使用 pd.merge() 合併
merge與concat的區別在於,merge須要依據某一共同的列來進行合併
使用pd.merge()合併時,會自動根據二者相同column名稱的那一列,做爲key來進行合併。
注意每一列元素的順序不要求一致
參數:
- how:out取並集 inner取交集
- on:當有多列相同的時候,可使用on來指定使用那一列進行合併,on的值爲一個列表
(1) . 一對一合併
df1 = DataFrame({'employee':['Bob','Jake','Lisa'], 'group':['Accounting','Engineering','Engineering'], }) df2 = DataFrame({'employee':['Lisa','Bob','Jake'], 'hire_date':[2004,2008,2012], }) pd.merge(df1,df2) #自動找相同的,列進行合併
(2) . 多對一合併
df3 = DataFrame({ 'employee':['Lisa','Jake'], 'group':['Accounting','Engineering'], 'hire_date':[2004,2016]}) df4 = DataFrame({'group':['Accounting','Engineering','Engineering'], 'supervisor':['Carly','Guido','Steve'] }) pd.merge(df3,df4,how='outer')
left right
(3) . 多對多合併
df1 = DataFrame({'employee':['Bob','Jake','Lisa'], 'group':['Accounting','Engineering','Engineering']}) df5 = DataFrame({'group':['Engineering','Engineering','HR'], 'supervisor':['Carly','Guido','Steve'] }) pd.merge(df1,df5,how='left')
left right
(4) . key 的規範化
-
- 當列衝突時,即有多個列名稱相同時,須要使用on=來指定哪個列做爲key,配合suffixes指定衝突列名
df1 = DataFrame({'employee':['Jack',"Summer","Steve"], 'group':['Accounting','Finance','Marketing']}) df2 = DataFrame({'employee':['Jack','Bob',"Jake"], 'hire_date':[2003,2009,2012], 'group':['Accounting','sell','ceo']}) pd.merge(df1,df2,on='group',how='outer')
-
- 當兩張表沒有可進行鏈接的列時,可以使用left_on和right_on手動指定merge中左右兩邊的哪一列列做爲鏈接的列
df1 = DataFrame({'employee':['Bobs','Linda','Bill'], 'group':['Accounting','Product','Marketing'], 'hire_date':[1998,2017,2018]}) df5 = DataFrame({'name':['Lisa','Bobs','Bill'], 'hire_dates':[1998,2016,2007]}) display(df1,df5)
(5) . 內合併與外合併 : out取並集 , inner取交集
-
- 內合併 : 只保留二者都有的key(默認模式)
df6 = DataFrame({'name':['Peter','Paul','Mary'], 'food':['fish','beans','bread']} ) df7 = DataFrame({'name':['Mary','Joseph'], 'drink':['wine','beer']}) display(df6,df7)
-
- 外合併 : how='outer' : 補NaN
df6 = DataFrame({'name':['Peter','Paul','Mary'], 'food':['fish','beans','bread']} ) df7 = DataFrame({'name':['Mary','Joseph'], 'drink':['wine','beer']}) display(df6,df7) pd.merge()
三-9 . 數據處理
1 . 刪除重複元素 : duplicated()
使用duplicated()函數檢測重複的行,返回元素爲布爾類型的Series對象,每一個元素對應一行,若是該行不是第一次出現,則元素爲True
- keep 參數 : 指定保留那一重複的行數據
# 建立具備重複元素行的DataFrame import numpy as np import pandas as pd from pandas import Series,DataFrame # 建立一個 df np.random.seed(1) df = DataFrame(data=np.random.randint(0,100,size=(8,6))) df
#手動將df的某幾行設置成相同的內容 df.iloc[1] = [6,6,6,6,6,6] df.iloc[3] = [6,6,6,6,6,6] df.iloc[4] = [6,6,6,6,6,6]
未變以前 改變以後
(1) . 方式一 :
# 使用duplicated查看全部重複元素行 df.duplicated(keep='last')
indexs = df[df.duplicated(keep='last')].index #獲取須要刪除行的索引 df.drop(labels=indexs,axis=0) #刪除重複行
(2) . 方式二 :
使用drop_duplicates()函數刪除重複的行
- drop_duplicates(keep='first/last'/False)
df.drop_duplicates() #一步到位
2 . 映射
(1) . replace() 函數 : 替換元素
使用replace()函數,對values進行映射操做
Series替換操做
- 單值替換
- 普通替換
- 字典替換(推薦)
- 多值替換
- 列表替換
- 字典替換(推薦)
- 參數
- to_replace:被替換的元素
replace參數說明:
- method:對指定的值使用相鄰的值填充替換
- limit:設定填充次數
DataFrame替換操做
- 單值替換
- 普通替換: 替換全部符合要求的元素:to_replace=15,value='e'
- 按列指定單值替換: to_replace={列標籤:替換值} value='value'
- 多值替換
- 列表替換: to_replace=[] value=[]
- 字典替換(推薦) to_replace={to_replace:value,to_replace:value}
注意:DataFrame中,沒法使用method和limit參數
df.replace(to_replace=6,value='six') #用'six'代替df中的'6' df.replace(to_replace={3:6},value='six') #用'six'代替df中第4列的'6' df.replace(to_replace={1:'one'}) #用'one'代替df中的''1'
3 . map() 函數 :
新建一列 , map函數並非df的方法 , 而是series的方法
- map()能夠映射新一列數據
- map()中可使用lambd表達式
-
map()中可使用方法,能夠是自定義的方法
eg:map({to_replace:value})
注意 map()中不能使用sum之類的函數,for循環
dic = { 'name':['周杰倫','李四','王五'], 'salary':[1000,2000,3000] } df = DataFrame(data=dic)
#新增一列:給df中,添加一列,該列的值爲中文名對應的英文名 #封裝一個映射關係表 dic = { '周杰倫':'jay', '王五':'wangwu', '李四':'lisi' } df['ename'] = df['name'].map(dic) df
(1) . map當作一種運算工具,至於執行何種運算,是由map函數的參數決定的(參數:lambda,函數)
- 使用自定義函數
#自定義函數 def after_salary(s): if s <= 500: return s else: return s - (s-500)*0.5 #超過500部分的錢繳納50%的稅 after_sal = df['salary'].map(after_salary) df['after_salary'] = after_sal df
- 使用lambda表達式
#員工的薪資集體提升500 df['salary'].map(lambda x:x+500)
4 . 數據重排 --- 使用 .take() 函數排序
- take()函數接受一個索引列表,用數字表示,使得df根據列表中索引的順序進行排序
- eg:df.take([1,3,4,2,5])
- np.random.permutation(x)能夠生成x個從0-(x-1)的隨機數列
df.take(np.random.permutation(1000),axis=0).take(np.random.permutation(3),axis=1) #np.random.permutation(1000) :把0,1000隨機排列成列表
當DataFrame規模足夠大時,直接使用np.random.permutation(x)函數,就配合take()函數實現隨機抽樣
5 . 數據分類處理 [重點]
數據聚合是數據處理的最後一步,一般是要使每個數組生成一個單一的數值。
數據分類處理:
- 分組:先把數據分爲幾組
- 用函數處理:爲不一樣組的數據應用不一樣的函數以轉換數據
- 合併:把不一樣組獲得的結果合併起來
數據分類處理的核心:
- groupby()函數 - groups屬性查看分組狀況 - eg: df.groupby(by='item').groups
(1) . 分組
#數據源 df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'], 'price':[4,3,3,2.5,4,2], 'color':['red','yellow','yellow','green','green','green'], 'weight':[12,20,50,30,20,44]}) #分組 df.groupby(by='item') #查看分組狀況 df.groupby(by='item').groups
分組後還能夠聚合 : sum , mean
#計算出蘋果的平均價格 dic = { 'Apple':3, 'Banana':2.75, 'Orange':3.5 } df['mean_price'] = df['item'].map(dic) df.groupby(by='item')['price'].mean()['Apple'] #按顏色查看各類顏色的水果的平均價格 df.groupby(by='color')['price'].mean() dic={ 'green':2.83, 'red':4, 'yellow':3 } df['color_mean_price'] = df['color'].map(dic) df
6 . 高級數據聚合
使用groupby分組後,也可使用transform和apply提供自定義函數實現更多的運算
- df.groupby('item')['price'].sum() <==> df.groupby('item')['price'].apply(sum)
- transform和apply都會進行運算,在transform或者apply中傳入函數便可
- transform和apply也能夠傳入一個lambda表達式
#求出各類水果價格的平均值 df.groupby(by='item')['price'].mean()
apply和transform
#定義執行方法 def fun(s): sum = 0 for i in s: sum+=s return sum/s.size
#使用apply函數求出水果的平均價格 df.groupby(by='item')['price'].apply(fun) #給fun傳入的參數是一個列表 #使用transform函數求出水果的平均價格 df.groupby(by='item')['price'].transform(fun) #給fun傳入的參數是一個列表