數(shù)據(jù)透視表(Pivot Table)是一種交互式的表,可以進行某些計算,如求和與計數(shù)等,其所進行的計算與數(shù)據(jù)跟數(shù)據(jù)透視表中的排列有關(guān)。
在Excel中我們可以輕而易舉地實現(xiàn)數(shù)據(jù)透視表功能,“插入——數(shù)據(jù)透視表——拖動選項——完成透視表”。
那么在Python中也能實現(xiàn)數(shù)據(jù)透視表功能嗎?答案是肯定的。本文旨在介紹Python Pandas中實現(xiàn)數(shù)據(jù)透視表功能的函數(shù)Pivot_table,并用實例解析它的參數(shù)設(shè)置及使用方法。
首先,觀看官方文檔對pandas.pivot_table函數(shù)的解釋:
pandas.pivot_table (data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All', observed=False)
各個參數(shù)的解釋如下:

參數(shù)太多難理解?沒關(guān)系,接下來將以實例的方式解析pivot_table函數(shù)及參數(shù)來幫助大家理解并使用。
案例實踐:
1、導(dǎo)入相關(guān)庫
import pandas as pd
import numpy as np
python實現(xiàn)透視表功能的pivot_table函數(shù)主要需要兩個庫pandas和numpy。
2、導(dǎo)入要進行透視的數(shù)據(jù)文件
df=pd.read_excel("C:\\Users\\Administrator\\Desktop\\pivot_table\\銷售數(shù)據(jù)源.xlsx")
導(dǎo)入excel xlsx格式的文件需要使用read_excel函數(shù),若是csv格式則使用read_csv函數(shù),括號內(nèi)為文件路徑,保存為df。
3、查看剛剛導(dǎo)入數(shù)據(jù)的情況
df.head()

以上結(jié)果顯示,數(shù)據(jù)成功導(dǎo)入了python
4、以賬號站點歸類做個簡單的透視表
pd.pivot_table(df,index=["站點"])

數(shù)據(jù)透視成功。這段代碼pivot_table有兩個函數(shù),一個是df,另一個是index。df是之前導(dǎo)入的數(shù)據(jù),index是要設(shè)置的索引。
但是還有兩個問題:
一是team和周數(shù)不應(yīng)該出現(xiàn)在這里的,猜想原因可能是python誤將team和周數(shù)的數(shù)字識別為數(shù)值并對其進行了運算但我們并不需要。
二是銷售額小數(shù)點后的尾數(shù)太多了,能不能保留小數(shù)點后兩位。
解決方法為,轉(zhuǎn)換team和周數(shù)的數(shù)據(jù)類型,轉(zhuǎn)成 category類別 類型即可解決,這樣python就不會將其識別為數(shù)值并計算。
5、轉(zhuǎn)化 team、周數(shù) 的數(shù)據(jù)類型為category類型,將銷售額保留小數(shù)點后兩位
df["team"]=df["team"].astype("category")
df["周數(shù)"]=df["周數(shù)"].astype("category")
df["銷售額"]=df["銷售額"].round(2)
6、這時再看看數(shù)據(jù)轉(zhuǎn)化類型成功了沒有
pd.pivot_table(df,index=["站點"])

team和周數(shù)的數(shù)據(jù)列消失了,轉(zhuǎn)化類型成功解決了這個問題。但是小數(shù)點的問題還沒有解決...
7.pivot_table函數(shù)的參數(shù)values
values為數(shù)值列,是對數(shù)據(jù)進行聚合。
pd.pivot_table(df,index=["站點"],values=["銷售額"])

在這里values只設(shè)置了銷售額,結(jié)果也只顯示了銷售額。可以看出,我們可以通過values選擇控制要進行聚合的數(shù)值列。
8、完整地補充所有index和values
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team","周數(shù)"],values=["銷售額","銷量","訂單數(shù)"])

這一步結(jié)束后發(fā)現(xiàn),小數(shù)點后兩位的問題解決了,保留了小數(shù)點后兩位。
9、pivot_table函數(shù)的參數(shù)columns
現(xiàn)在,我要通過不同周數(shù)來分析銷售情況,那么參數(shù)columns將允許我們定義一個或多個列。
解決方法:columns=["周數(shù)"] 將周數(shù)從index參數(shù)中抽出放進columns參數(shù)中
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"])

結(jié)果看到,銷售額、銷量、訂單數(shù)根據(jù)周數(shù)均分成了四小列,能夠更直觀看出產(chǎn)品每一周銷售情況的變化。
10、pivot_table函數(shù)的參數(shù)aggfunc
這個參數(shù)很重要。你是想對數(shù)據(jù)列進行求和?還是求均值?求最大值或最小值?aggfunc可以幫到你。
aggfunc可以用列表list或字典dic來設(shè)置。
(1)列表方法
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"],aggfunc=[np.sum])

以上是"銷售額","銷量","訂單數(shù)"對數(shù)值均進行了求和運算。
那如果我想同時對"銷售額求和","銷量求均值","訂單數(shù)求最大值",這樣可不可以呢?可以的,用字典dict來設(shè)置。
(2)字典方法
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"],aggfunc={"銷售額":np.sum,"銷量":np.mean,"訂單數(shù)":max})

因此設(shè)置aggfunc顯得十分重要,它明確規(guī)定了運算方式,才能得到期望的運算結(jié)果。
11、pivot_table函數(shù)的參數(shù)fill_value
在上個步驟,可以發(fā)現(xiàn)數(shù)據(jù)透視表表中有許多非數(shù)值(NaN),填充非數(shù)值(NaN)可以使用參數(shù)fill_value
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"],aggfunc={"銷售額":np.sum,"銷量":np.mean,"訂單數(shù)":max},fill_value=0)

從結(jié)果可以看到,fill_value=0,非數(shù)值(NaN)全部被填充為0。
12、pivot_table函數(shù)的參數(shù)margins
你有一個新的需求,領(lǐng)導(dǎo)想看到銷售情況各項數(shù)據(jù)的總值,而不是現(xiàn)在的一行行數(shù)據(jù),如何新增一列匯總值列?
解決方法:增加匯總列——使用參數(shù)margins。(margins默認(rèn)為False,可以設(shè)置為True開啟匯總列的計算)
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"],aggfunc={"銷售額":np.sum,"銷量":np.mean,"訂單數(shù)":max},fill_value=0,margins=True)


可以看到,"銷售額","銷量","訂單數(shù)"的后面均出現(xiàn)一列"All",以及最下一行出現(xiàn)匯總行。這就是margins=True的作用。
當(dāng)然,你覺得"All"的名稱不好看,可以自定義匯總列的名稱,需要用到參數(shù)margins_name,如margins_name="訂單數(shù)匯總"。

13、pivot_table函數(shù)的最后一個參數(shù)dropna
dropna=True 的意思為不包括條目全部為NaN的列,即一列的數(shù)據(jù)如果全部為NaN則被刪除。(默認(rèn)為False)
pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"],aggfunc={"銷售額":np.sum,"銷量":np.mean,"訂單數(shù)":max},fill_value=0,margins=True,margins_name="匯總",dropna=True)

總結(jié):
至此,pivot_table的所有參數(shù)的使用方法和實例均已介紹完,大家可以根據(jù)自己項目的需求靈活使用這些參數(shù)。
最后復(fù)習(xí)一遍:
pandas.pivot_table (data, index=None, columns, values, aggfunc, fill_value, margins, margins_name, dropna)
還沒結(jié)束
最后的問題:數(shù)據(jù)透視表是做好了,但是我們怎么篩選條件查詢其中的某行數(shù)據(jù)呢?
首先、將上述做好的透視表保存到變量table中
table=pd.pivot_table(df,index=["賬號","站點","K3代碼","運營大類","大類","品牌","機型","款式","顏色","事業(yè)部","team"],columns=["周數(shù)"],values=["銷售額","銷量","訂單數(shù)"],aggfunc={"銷售額":np.sum,"銷量":np.mean,"訂單數(shù)":max},fill_value=0,margins=True,margins_name="匯總",dropna=True)
然后、查詢需要用到query()函數(shù)
table.query("站點=='US'")

結(jié)果顯示,成功查詢到US站點的所有數(shù)據(jù)。
單個條件篩選知道怎么寫了,那么多個篩選條件又要怎么寫?
table.query("(賬號=='CC')&(站點=='US')")

解析:query函數(shù)中,條件用括號含括,多個條件之間用&連接,篩選結(jié)果符合實際期望。
至此本文結(jié)束。
參考文獻:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.pivot_table.html