1. 程式人生 > 實用技巧 >Python:Pandas的基本操作和使用

Python:Pandas的基本操作和使用

Pandas整體內容概要

本文整體介紹

  1. Pands的資料結構
  2. Pands的讀取與儲存
  3. 資料的基本操作:資料的檢視、檢查、選擇、刪減、填充
  4. 資料的處理:合併、聚合、分組、filter、sort、groupBy
  5. 函式應用與對映
  6. 資料的簡單視覺化

Pandas 是非常著名的開源資料處理庫,其基於 NumPy 開發,該工具是 Scipy 生態中為了解決資料分析任務而設計。Pandas 納入了大量庫和一些標準的資料模型,提供了高效地操作大型資料集所需的函式和方法。
我們可以通過它完成對資料集進行快速讀取、轉換、過濾、分析等一系列操作。除此之外,Pandas 擁有強大的缺失資料處理與資料透視功能,可謂是資料預處理中的必備利器。

1.Pandas的資料結構

特有的資料結構是 Pandas 的優勢和核心。簡單來講,我們可以將任意格式的資料轉換為 Pandas 的資料型別,並使用 Pandas 提供的一系列方法進行轉換、操作,最終得到我們期望的結果。
Pandas 的資料型別主要有以下幾種,它們分別是:

  1. Series(一維陣列)
  2. DataFrame(二維陣列) -- 是不是與sparkSQL等大資料框架中的DataFrame很類似,其實可以理解就是一個東西,一個二維表格 + 一個Schema = 一個DataFrame,或 Series + Series = DataFrame
  3. Panel(三維陣列)
  4. Panel4D(四維陣列)
  5. PanelND(更多維陣列)

其中 Series 和 DataFrame 應用的最為廣泛,本文僅對 Series 和 DataFrame 進行討論

Series

Series 是 Pandas 中最基本的一維陣列形式。其可以儲存整數、浮點數、字串等型別的資料。
其基本結構為:

pandas.Series(data=None, index=None)

data 可以是字典,或者NumPy 裡的 ndarray 物件等
index 是資料索引

可以看出,其結構與Array或者List等資料結構也有相似型,每個資料都有個索引,可以根據索引快速定位資料。
Series的生成
通過傳入一個iterable物件,比如列表、range物件、迭代器等都可以生成一個Series。pd.Series方法可以自動給生成一個0開始的索引,也可以指定索引

也可以傳入Python的字典來建立Series,則key為索引,value為資料

注意: 特別宣告,在建立Series時指定的index的優先順序要高於values,表現在生成的Series嚴格按照指定的index排序,執行下列語句體會一下

由於 Pandas 基於 NumPy 開發。那麼 NumPy 的資料型別 ndarray 多維陣列自然就可以轉換為 Pandas 中的資料。而 Series 則可以基於 NumPy 中的一維資料轉換。

s = pd.Series(np.random.randn(5))

其他訪問方式
相比傳統的資料結構,Series擁有更高層的訪問索引方式,比如序列索引、布林索引

因為布林索引是非常常用的一種索引方式,所以這裡再強調一下。布林索引實質上就是傳入布林值組成的iterable物件比如[False,True,True] , 通過布林運算 series_3 >= 'b 得到的結果其實就是[False,True,True]

布林運算可以通過'與'(&)、'或'(|)、'非'(~)進行組合運算 , (每一個計算項一定要加括號,注意運算子的優先順序)

DataFrame

關於DataFrame在不同技術棧中的不同理解,其實本質是相同的,左圖是pandas中的理解,右圖為spark DataFrame的經典圖示

其實可以理解就是一個東西,一個二維表格 + 一個Schema = 一個DataFrame,或 Series + Series = DataFrame

dataframe是在Series的基礎上添加了一個軸,原來的行索引index稱為0軸(axis=0),新增軸列索引columns稱為1軸(axis=1) 1軸的優先順序要高於0軸
由python物件可以快速建立DataFrame , 同Series一樣,沒有指定index會由pandas自動建立

dict_2 = {'A':[1,2,3],'B':['a','b','c']}  # 1軸優先順序高,指定key時表示的是1軸,如果想要類似Series一樣指定index,需要用巢狀字典
dataframe_1 = pd.DataFrame(dict_2,index=range(1,4)) # 可以指定index
dataframe_1


也可以指定列索引的額順序

dataframe_2 = pd.DataFrame(dict_2,index=range(1,4),columns=['B','A']) # 同上面演示的Series的index一樣,可以指定列索引的順序
dataframe_2


獲取列索引

預設對dataframe進行索引是執行列索引,得到一個Series,指定的column退化為Series的name屬性

# 兩種訪問方式都可以 
print(dataframe_2.B )
print(dataframe_2['B'] )
#訪問某個元素,先指定列再指定行
print(dataframe_2['A'][2])  #2不可以加引號,為索引號


新增或修改某一列的值
新增或修改某一列只需要類似賦值的操作,賦值一個iterable物件

指定 series或者dict會對index/key進行匹配,只賦值key與index匹配的value

刪除columns:兩種方法


行列轉置(0軸和1軸的轉置)

2.資料的讀取與儲存

資料的讀取

pandas的I/O API是一組read函式,比如pandas.read_csv()函式。這類函式可以返回pandas物件。相應的write函式是像DataFrame.to_csv()一樣的物件方法。下面是一個方法列表,包含了這裡面的所有readers函式和writer函式。

該部分可參見官方文件,或pandas中文網 https://www.pypandas.cn/docs/user_guide/io.html#csv-文字檔案

  1. pd.read_csv(filename):從CSV檔案匯入資料
  2. pd.read_table(filename):從限定分隔符的文字檔案匯入資料
  3. pd.read_excel(filename):從Excel檔案匯入資料
  4. pd.read_sql(query, connection_object):從SQL表/庫匯入資料
  5. pd.read_json(json_string):從JSON格式的字串匯入資料
  6. pd.read_html(url):解析URL、字串或者HTML檔案,抽取其中的tables表格
  7. pd.read_clipboard():從你的貼上板獲取內容,並傳給read_table()
  8. pd.DataFrame(dict):從字典物件匯入資料,Key是列名,Value是資料
    常用的方法的讀取引數解釋
  9. pd.read_csv(filename):從CSV檔案匯入資料

下列為常用的引數及解釋

引數 解釋 必填/非必填
filepath_or_buffer 檔案路徑 必填
sep 指定分隔符,預設逗號',' 非必填
header 指定第幾行作為表頭。預設為0(即第1行作為表頭),若沒有表頭,需設定header=None,可以是int或list。 非必填
names 指定列的名稱,用list表示,預設None 非必填
index_col 指定行索引,可以是一列或多列,預設None 非必填
usecols 需要讀取的列,可以使用列序列也可以使用列名,預設None 非必填
prefix 給列名新增字首。如prefix=x,會出來X0,X1,....,預設None 非必填
skiprows 需要忽略的行數(從檔案開始處算起),或需要跳過的行號列表(從0開始),預設None 非必填
skipfooter 需要忽略的行數(從最後一行開始算) 非必填
nrows 需要讀取的行數(從檔案頭開始算起),預設None 非必填
encoding 編碼方式,亂碼時使用,預設None 非必填

另附上公司大佬整理的常用引數,以供參考,膜拜大佬

資料的儲存

常用的方式,更全面請詳見官檔

  1. df.to_csv(filename):匯出資料到CSV檔案
  2. df.to_excel(filename):匯出資料到Excel檔案
  3. df.to_sql(table_name, connection_object):匯出資料到SQL表
  4. df.to_json(filename):以Json格式匯出資料到文字檔案

loc/iloc方式訪問DataFrame

3. 資料的基本操作:資料的檢查、檢視、選擇、刪減、填充

在pandas中,使用的最多的資料結構是series和DataFrame,以下操作更多的基於這兩者進行。

常用資料檢查方法

常用方法 介紹
df.head() 預設顯示前 5 條
df.tail(7) 指定顯示後 7 條,不填為5條
df.describe() 對資料集進行概覽,會輸出該資料集每一列資料的計數、最大值、最小值,std,25%,50%,75%值等
df.values 將 DataFrame 轉換為 NumPy 陣列
df.index 檢視索引
df.columns 檢視列名
df.shape 檢視形狀,如(n,m)n行m列
df.mean() 返回所有列的均值
df.corr() 返回列與列之間的相關係數
df.count() 返回每一列中的非空值的個數
df.median() 返回每一列的中位數
... count,min,max,std..
pd.isnull() 檢查DataFrame物件中的null值,並返回一個Boolean陣列
pd.notnull() 檢查DataFrame物件中的非null值,並返回一個Boolean陣列
pd.isna() 檢查DataFrame物件中的空值(null和''),並返回一個Boolean陣列
pd.notna() 檢查DataFrame物件中的非空值(非null和非''),並返回一個Boolean陣列
s.value_counts(dropna=False) 檢視Series物件的唯一值和計數
df.apply(pd.Series.value_counts) 檢視DataFrame物件中每一列的唯一值和計數

常用資料檢視選擇方法
在資料預處理過程中,我們往往會對資料集進行切分,只將需要的某些行、列,或者資料塊保留下來,輸出到下一個流程中去。這也就是所謂的資料選擇,或者資料索引。由於 Pandas 的資料結構中存在索引、標籤,所以我們可以通過多軸索引完成對資料的選擇。

基於索引數字選擇
當我們新建一個 DataFrame 之後,如果未自己指定行索引或者列對應的標籤,那麼 Pandas 會預設從 0 開始以數字的形式作為行索引,並以資料集的第一行作為列對應的標籤。其實,這裡的「列」也有數字索引,預設也是從 0 開始,只是未顯示出來
我們可以用.iloc 方法對資料集進行基於索引數字的選擇。Selection by Position i可理解為index,與下方的loc區分開
該方法可接受的索引為:

  1. 整數;
  2. 整數構成的列表或陣列,例如:[1, 2, 3];
  3. 布林陣列;
  4. 可返回索引值的函式或引數。

選擇示例

方法 介紹
df.iloc[:3] 選擇前3行,類似Python的切片
df.iloc[5] 選擇特定一行
df.iloc[[1, 3, 5]] 選擇1,3,5行,注意不是 df.iloc[1, 3, 5],df.iloc[] 的 [[行],[列]] 裡面可以同時接受行和列的位置
df.iloc[:, 1:4] 選擇2-4列,注意:df.iloc[] 的 [[行],[列]] 裡面可以同時接受行和列的位置
df.iloc[:3, 1:4] 選擇前3行的2-4列,#訪問指定的index和columns,注意此處指的是索引,所以是前閉後開區間

基於標籤名稱選擇
直接根據標籤對應的名稱選擇,為 df.loc[]。loc為Selection by Label函式
df.loc[] 可以接受的型別有:

  1. 單個標籤。例如:2 或 'a',這裡的 2 指的是標籤而不是索引位置。
  2. 列表或陣列包含的標籤。例如:['A', 'B', 'C']。
  3. 切片物件。例如:'A':'E',注意這裡和上面切片的不同之處,首尾都包含在內。
  4. 布林陣列。
  5. 可返回標籤的函式或引數。
常用方法 介紹
df.loc[0:2] 訪問前3條(和index無關,和順序有關)
df.loc[[0, 2, 4]] 選擇1,3,5行
df.loc[:, 'A':'B'] 選擇A,B列
df.loc[:, 'A':] 選擇A列後面的列

資料刪減/清理

df.drop(labels=['A','B'], axis=1) 直接去掉資料集中指定的列和行。一般在使用時,我們指定 labels 標籤引數,然後再通過 axis 指定按列或按行刪除即可。
df.drop_duplicates 剔除資料集中的重複值。使用方法非常簡單,指定去除重複值規則,以及 axis 按列還是按行去除即可
df.dropna() 刪除所有包含空值的行
df.dropna(axis=1) 刪除所有包含空值的列
df.dropna(axis=1,thresh=n) 刪除所有小於n個非空值的行

資料填充/替換

常用方法 介紹
df.fillna(x) 用x替換DataFrame物件中所有的空值(null和''),也可以新增引數method='pad'和method='bfill'使用缺失值前面/後面的值進行完全填充,可通過limit= 引數設定連續填充的限制數量
df.fillna(df.mean()['C':'E']) 通過C,E列的平均值來填充na值
s.astype(float) 將Series中的資料型別更改為float型別
s.replace(1,'one') 用‘one’代替所有等於1的值
s.replace([1,3],['one','three']) 用'one'代替1,用'three'代替3
df.rename(columns=lambda x: x + 1) 批量更改列名
df.rename(columns={'old_name': 'new_ name'}) 選擇性更改列名
df.set_index('column_one') 更改索引列
df.rename(index=lambda x: x + 1) 批量重新命名索引

插值填充
還有一種比較符合資料趨勢的填充方式,插值填充,是利用資料的變化趨勢來填充

# 生成一個 DataFrame
df = pd.DataFrame({'A': [1.1, 2.2, np.nan, 4.5, 5.7, 6.9],
                   'B': [.21, np.nan, np.nan, 3.1, 11.7, 13.2]})
df
df_interpolate = df.interpolate()  # 線性插值
df_interpolate


下面是插值插入的兩個資料,

對於 interpolate() 支援的插值演算法,也就是 method=。建議

  1. 如果你的資料增長速率越來越快,可以選擇 method='quadratic'二次插值。
  2. 如果資料集呈現出累計分佈的樣子,推薦選擇 method='pchip'。
  3. 如果需要填補預設值,以平滑繪圖為目標,推薦選擇 method='akima'。
    最後提到的 method='akima',需要你的環境中安裝了 Scipy 庫。除此之外,method='barycentric' 和 method='pchip' 同樣也需要 Scipy 才能使用

4. 資料的處理:合併、聚合、分組、filter、sort、groupBy

合併

  1. merge 實現兩個DataFrame通過value或index連線成一張寬表的操作,是基於column連線
  2. join 基於兩個DataFrame的索引進行合併,是基於索引連線
  3. concat 兩個DataFrame按照0軸或1軸拼接成一個DataFrame(即行拼接或列拼接)

merge方法
pd.merge(df1,df2,how='inner',on='column')
引數

df1/df2:左/右位置的dataframe。
how:資料合併的方式。left:基於左dataframe列的資料合併;right:基於右dataframe列的資料合併;outer:基於列的資料外合併(取並集);inner:基於列的資料內合併(取交集);預設為'inner'。
on:用來合併的列名,這個引數需要保證兩個dataframe有相同的列名。on=['A','B']
left_on/right_on:左/右dataframe合併的列名,也可為索引,陣列和列表。
left_index/right_index:是否以index作為資料合併的列名,True表示是。
sort:根據dataframe合併的keys排序,預設是。
suffixes:若有相同列且該列沒有作為合併的列,可通過suffixes設定該列的字尾名,一般為元組和列表型別。
整體效果,與SQL中的join操作類似,就是制定連線方式,按on的列進行join,然後以how的方式輸出DataFrame。
測試資料如下:

內連線

左連線

另外,外連線寫作outer,右連線寫作right ;和SQL的join效果簡直一模一樣。

join方法
join方法是基於index連線dataframe,merge方法是基於column連線,連線方法有內連線,外連線,左連線和右連線,與merge一致。
join和merge的連線方法類似,與merge很相似,直接用merge方法就ok了。

concat方法
concat方法是拼接函式,有行拼接和列拼接,預設是行拼接,拼接方法預設是外拼接(並集),拼接的物件是pandas資料型別。
series型別,行拼接和列拼接


注:也可在其中新增引數,join='inner' 預設是以並集的方式拼接的

dataframe型別,行拼接和列拼接
dataframe型別的行拼接

dataframe型別的列拼接

分組
size方法直接獲取分組後每組的大小

5. 函式應用與對映

  1. map() 將一個自定義函式應用於Series結構中的每個元素
  2. apply() 將一個函式作用於DataFrame中的每個行或者列
  3. applymap() 將函式做用於DataFrame中的所有元素

map()
map() 是一個Series的函式,將一個自定義函式應用於Series結構中的每個元素(elements),注意DataFrame結構中沒有map()

apply()
apply() 針對DataFrame在每行或者每列上執行計算 (支援維度變化: n==>1 返回Series 、 n ==>m 返回DataFrame)
基於上一步的df繼續操作:

apply中還可搭配邏輯判斷,或者value_counts()效果很佳

applymap()
applymap()
以下案例為向DataFrame中的每個元素新增‘!’結尾,以下兩種方式是等效的