本文經授權轉自公眾號 凹凸數據(ID:alltodata)
如若轉載請聯繫原公眾號
1)都是用來處理表格數據
不管是mysql,還是pandas,都是處理像excel那樣的二維表格數據的。對於一個二維表,每一行都可以看作是一條記錄,每一列都可以看作是欄位。
2)分組聚合的風格不同
學過mysql的人都知道,mysql在做數據處理和統計分析的時候,有一個很大的痛點:語法順序和執行順序不一致,這就導致很多初學者很容易寫錯sql語句。
業界處理像excel那樣的二維表格數據,通常有如下兩種風格:
* DSL風格:使用面向對象的方式來操作,pandas就是採用這種方式,通俗說就是「語法順序和執行順序一致」。
* SQL風格:寫sql語句來處理。
3)從代碼角度,說明兩者的不同
① mysql
語法順序:
SELECT Column1, Column2, mean(Column3), sum(Column4)
FROM SomeTable
WHERE Condition 1
GROUP BY Column1, Column2
HAVING Condition2邏輯執行順序:
from...where...group...select...having...limit② pandas
語法順序和邏輯執行順序:
df[Condition1].groupby([Column1,Column2],as_index=False).agg({Column3: "mean",Column4:"sum"})③ 圖示說明
首先from相當於取出MySQL中的一張表,對比pandas就是得到了一個df表對象。
然後就是執行where篩選,對比pandas就相當於寫一個condition1過濾條件,做一個分組前的篩選篩選。
接著就是執行group分組條件,對比pandas就是寫一個groupby條件進行分組。
再接著就是執行select條件,聚合函數就是寫在select後面的,對比pandas就是執行agg()函數,在其中針對不同的列執行count、max、min、sum、mean聚合函數。
最後執行的是having表示分組後的篩選,在pandas中,通過上圖可以發現我們得到了一個df1對象,針對這個df1對象,我們再做一次篩選,也表示分組後的篩選。
綜上所述:只要你的邏輯想好了,在pandas中,由於語法順序和邏輯執行順序是一致的,你就按照邏輯順序寫下去,就很容易了。
4)用一個例子講述MySQL和Pandas分組聚合
① 求不同deptno(部門)下,sal(工資)大於8000的部門、工資;
② mysql中代碼執行如下
select deptno,sum(sal) sums
from emp
group by deptno
having sums > 9000;結果如下:
③ pandas中代碼執行如下
df = pd.read_excel(r"C:\Users\黃偉\Desktop\emp.xlsx")
display(df)
df = df.groupby("deptno",as_index=False).agg({"sal":"sum"})
display(df)
df1 = df[df["sal"]>9000]
display(df1)結果如下:
1)原理圖
2)原理說明
split:按照指定規則分組,由groupby實現;
apply:針對每個小組,使用函數進行操作,得到結果,由agg()函數實現;
combine:將每一組得到的結果,匯總起來,得到最終結果;
注意:combine這一步是自動完成的,因此針對pandas中的分組聚合,我們只需要學習兩個內容,① 學習怎麼分組;② 學習如何針對每個分組中的數據,進行對應的邏輯操作;
我們可以通過groupby方法來對Series或DataFrame對象實現分組操作,該方法會返回一個分組對象。但是,如果直接查看(輸出)該對象,並不能看到任何的分組信息。
1)groupby()函數語法
① 語法如下
* groupby(by=["欄位1","欄位2",...],as_index=True)② 參數說明
* by參數傳入的分組欄位,當只有一個欄位的時候,可以直接寫by="欄位1"。當多欄位聯合分組的時候,就寫成列表形式by=["欄位1","欄位2"]。
* as_index參數的使用如圖所示
③ 參數as_index的使用說明
x = {"name":["a","a","b","b","c","c","c"],"num":[2,4,0,5,5,10,15]}
df = pd.DataFrame(x)
display(df)
df.groupby("name",as_index=True).agg({"num":"sum"})
df.groupby("name",as_index=False).agg({"num":"sum"})結果如下:
2)groupby分組對象的常用方法或屬性。
① groups屬性:返回一個字典,key表示組名,value表示這一組中的所有記錄;
② size()方法:返回每個分組的記錄數;
x = {"name":["a","a","b","b","c","c","c"],"num":[2,4,0,5,5,10,15]}
df = pd.DataFrame(x)
display(df)
df.groupby("deptno").groups
df.groupby("deptno").size()結果如下:
3)使用for循環列印groupby()分組對象中每一組的具體數據
x = {"name":["a","a","b","b","c","c","c"],"num":[2,4,0,5,5,10,15]}
df = pd.DataFrame(x)
display(df)
groupdf = df.groupby("name")
for (x,y) in groupdf:
display(x, y)結果如下:
4)groupby()分組參數的4種形式
使用groupby進行分組時,分組的參數可以是如下的形式:
* 單欄位分組:根據df中的某個欄位進行分組。
* 多欄位分組:根據df中的多個欄位進行聯合分組。
* 字典或Series:key指定索引,value指定分組依據,即value值相等的記錄,會分為一組。
* 自定義函數:接受索引,索引相同的記錄,會分為一組。使用如下數據演示這4種分組參數:
df = pd.DataFrame({"部門":["A", "A", "B", "B"],
"小組":["g1", "g2", "g1", "g2"],
"利潤":[10, 20, 15, 28],
"人員":["a", "b", "c", "d"],
"年齡":[20, 15, 18, 30]})
display(df)結果如下:
① 單欄位分組:根據df中的某個欄位進行分組。
g = df.groupby("部門")
display(g)
for (x,y) in g:
display(x, y)結果如下:
② 多欄位分組:根據df中的多個欄位進行聯合分組。
g = df.groupby("部門")
display(g)
for (x,y) in g:
display(x, y)結果如下:
③ 字典:key指定索引,value指定分組依據,即value值相等的記錄,會分為一組。
g = df.groupby({0:1, 1:1, 2:1, 3:2})
display(g)
for (x,y) in g:
display(x, y)結果如下:
④ Series:分組排序(很重要)
df = pd.DataFrame({"部門":["A", "A", "A", "B", "B", "B"],
"利潤":[10, 32, 20, 15, 28, 10],
"銷售量":[20, 15, 33, 18, 30, 22]})
display(df)
df["排名"] = df["銷售量"].groupby(df["部門"]).rank()
df結果如下:
⑤ 自定義函數:將部門A、B分為一組,C單獨成為一組(很特別的需求)
df = pd.DataFrame({"部門":["A", "A", "B", "B", "C", "C"],
"小組":["g1", "g2", "g1", "g2", "g1", "g2"],
"利潤":[10, 20, 15, 28, 12, 14],
"人員":["a", "b", "c", "d", "e", "f"],
"年齡":[20, 15, 18, 30, 23, 34]})
df = df.set_index("部門")
display(df)
def func(x):
if x=="A" or x=="B":
return 0
else:
return 1
g = df.groupby(func)
display(g)
for (x,y) in g:
display(x, y)結果如下:
當使用了groupby()分組的時候,得到的就是一個分組對象。當沒有使用groupby()分組的時候,整張表可以看成是一個組,也相當於是一個分組對象。
針對分組對象,我們既可以直接調用聚合函數sum()、mean()、count()、max()、min(),還可以調用分組對象的agg()方法,然後像agg()中傳入指定的參數。
1)直接針對分組對象,調用聚合函數
① 針對df整張表,直接調用聚合函數
df = pd.DataFrame({"部門":["A", "A", "B", "B", "C", "C"],
"小組":["g1", "g2", "g1", "g2", "g1", "g2"],
"利潤":[10, 20, 15, 28, 12, 14],
"人員":["a", "b", "c", "d", "e", "f"],
"年齡":[20, 15, 18, 30, 23, 34]})
display(df)
df["利潤"].mean()
df[["年齡","利潤"]].mean()結果如下:
② 針對df分組後的對象,直接調用聚合函數
df = pd.DataFrame({"部門":["A", "A", "B", "B", "C", "C"],
"小組":["g1", "g2", "g1", "g2", "g1", "g2"],
"利潤":[10, 20, 15, 28, 12, 14],
"人員":["a", "b", "c", "d", "e", "f"],
"年齡":[20, 15, 18, 30, 23, 34]})
display(df)
df.groupby("部門")["利潤"].mean()
df.groupby("部門").mean()結果如下:
2)直接針對分組對象,調用agg()函數(很重要)
下面知識的講解,涉及到「聚合函數字符串」,這是我自己起的名字,類似於"sum"、"mean"、"count"、"max"、"min",都叫做「聚合函數字符串」。同時還需要注意一點,agg()函數中還有一個axis參數,用於指定行、列。
* df.agg("mean")
* df.agg(["mean", "sum", "max"])
* df.agg({"利潤":["mean", "sum"] , "年齡":["max", "min"]})
* df.agg(lambda x: x.mean())① 傳入單個聚合函數字符串
df = pd.DataFrame({"部門":["A", "A", "B", "B"],
"利潤":[10, 20, 15, 28],
"年齡":[20, 15, 18, 30]})
display(df)
df1 = df.groupby("部門").agg("mean")
display(df1)結果如下:
② 傳入多個聚合函數字符串
df = pd.DataFrame({"部門":["A", "A", "B", "B"],
"利潤":[10, 20, 15, 28],
"年齡":[20, 15, 18, 30]})
display(df)
df1 = df.groupby("部門").agg(["sum","mean"])
display(df1)結果如下:
③ 傳入一個字典:可以針對不同的列,提供不同的聚合信息。
df = pd.DataFrame({"部門":["A", "A", "B", "B"],
"利潤":[10, 20, 15, 28],
"年齡":[20, 15, 18, 30]})
display(df)
df1 = df.groupby("部門").agg({"利潤":["sum","mean"],"年齡":["max","min"]})
display(df1)結果如下:
④ 傳入自定義函數
df = pd.DataFrame({"部門":["A", "A", "A", "B", "B", "B"],
"利潤":[10, 32, 20, 15, 28, 10],
"銷售量":[20, 15, 33, 18, 30, 22]})
display(df)
df.groupby("部門").agg(lambda x:x.max()-x.min())結果如下:
更多精彩
在公眾號後臺對話框輸入以下關鍵詞
查看更多優質內容!
女朋友 | 大數據 | 運維 | 書單 | 算法
大數據 | JavaScript | Python | 黑客
AI | 人工智慧 | 5G | 區塊鏈
機器學習 | 數學 | 送書