作為一名數據分析師,平常用的最多的工具是SQL(包括MySQL和Hive SQL等)。對于存儲在數據庫中的數據,自然用SQL提取會比較方便,但有時我們會處理一些文本數據(txt,csv),這個時候就不太好用SQL了。Python也是分析師常用的工具之一,尤其pandas更是一個數據分析的利器。雖然二者的語法,原理可能有很大差別,但在實現的功能上,他們有很多相通的地方,這里特進行一個總結,方便大家對比學習~
本次學習的數據是虛構的訂單數據,和實際業務無關,目的只是為了學習。大概長下面這樣子,分別表示,自增id,訂單時間,用戶id,訂單id,訂單金額。
我們將用pandas和SQL來實現同樣的目標,以此來聯系二者,達到共同學習的目的。數據可以在公眾號后臺回復“對比”獲取,你將得到本文所有的excel數據和SQL腳本數據以及本文的清晰PDF版本,便于實操和查看。
準備工作:
-
pandas準備,我們本次采用jupyter notebook進行演示。
import pandas as pdorder_data = pd.read_csv('order.csv')
-
SQL 準備
只需將我提供的SQL文件運行一下即可將數據插入數據庫表中。推薦使用navicate客戶端連接數據庫。
開始學習
1.查看全部數據或者前n行數據
查看全部數據,pandas中直接打印dataframe對象即可,此處是order_data。而在SQL中,需要執行的語句是select * from t_order;
表示從t_order表中查詢全部的數據,*號表示查詢所有的字段。結果如下:(點擊圖片可以查看大圖)
如果只想查看前10行數據呢。pandas可以調用head(n)方法,n是行數。MySQL可以使用limit n,n同樣表示行數。(點擊圖片可以查看大圖)
2.查詢特定列的數據
有的時候我們只想查看某幾列的數據。在pandas里可以使用中括號或者loc,iloc等多種方式進行列選擇,可以選擇一列或多列。loc方式可以直接寫列名,iloc方式需要指定索引,即第幾列。SQL里只需寫相應的列名即可,舉例如下,實際操作一下更容易理解,選擇一種自己習慣的即可。(點擊圖片可以查看大圖)
3.查詢特定列去重后的數據
例如我們想查看一共有多少人(去重過的)下過單。pandas里有unique方法,SQL里有distinct關鍵字。如下面圖左側代碼所示。兩種方式輸出的結果都含有9個uid,并且知道是哪9個。如果僅僅想知道有多少個uid,不關注具體值的話,可以參考右邊的SQL,pandas用nunique()方法實現,而SQL里就需要用到一個count聚合函數與distinct組合的方式,表示去重并計數。(點擊圖片可以查看大圖)
4.查詢帶有1個條件的數據
例如我們要查詢uid為10003的所有記錄。pandas需要使用布爾索引的方式,而SQL中需要使用where關鍵字。指定條件時,可以指定等值條件,也可以使用不等值條件,如大于小于等。但一定要注意數據類型。例如如果uid是字符串類型,就需要將10003加引號,這里是整數類型所以不用加。代碼如下:(點擊圖片可以查看大圖)
5.查詢帶有多個條件的數據。
-
多個條件同時滿足的情況
在前一小結基礎上,pandas需要使用&符號連接多個條件,每個條件需要加上小括號;SQL需要使用and關鍵字連接多個條件。例如我們查詢uid為10003并且金額大于50的記錄。兩種方式的實現代碼如下:(點擊圖片可以查看大圖)
image -
多個條件滿足其中一個的情況
與多個條件同時滿足使用&相對應的,我們使用|符號表示一個條件滿足的情況,而SQL中則用or關鍵字連接各個條件表示任意滿足一個。例如我們查詢uid為10003或者金額大于50的記錄。(點擊圖片可以查看大圖)
image這里需要特別說明的是有一種情況是需要判斷某字段是否為空值。pandas的空值用nan表示,其判斷條件需要寫成isna(),或者notna()。例如
#查找uid不為空的記錄order_data[order_data['uid'].notna()]#查找uid為空的記錄order_data[order_data['uid'].isna()]
MySQL相應的判斷語句需要寫成 is null 或者is not null。
select * from t_order where uid is not null;select * from t_order where uid is null;
還需要注意的是,空字符串或者空格雖然是有值的,但由于“不顯示”出來,我們通常認為是空值。這種情況的判斷條件和前面一樣使用等號即可。感興趣的朋友可以自己嘗試一下。
6.group by聚合操作
使用group by時,通常伴隨著聚合操作,這時候需要用到聚合函數。前面提到的count是一種聚合函數,表示計數,除此外還有sum表示求和,max,min表示最大最小值等。pandas和SQL都支持聚合操作。例如我們求每個uid有多少訂單量。兩種工具的操作如下:(點擊圖片可以查看大圖)
如果想要同時對不同的字段進行不同的聚合操作。例如目標變成:求每個uid的訂單數量和訂單總金額。寫法會稍微不同一些,如下圖所示。(點擊圖片可以查看大圖)
更進一步的,我們可以對結果的數據集進行重新命名。pandas可以使用rename方法,MySQL可以使用as 關鍵字進行結果的重命名。(點擊圖片可以查看大圖)
7.join相關操作
join相關的操作有inner join,left join,right join,full join,等。pandas中統一通過pd.merge方法,設置不同的參數即可實現不同的dataframe的連接。而SQL里就可以直接使用相應的關鍵字進行兩個表的連接。為了演示,我們此處引入一個新的數據集,user.csv(對應t_user表)。包含了用戶的昵稱,年齡信息。數據樣例如下所示。(點擊圖片可以查看大圖)
-
left join
首先需要把數據加載進來:
user_data = pd.read_csv('user.csv')
pandas的merge函數傳入4個參數,第一個是連接的主表,第二個是連接從表,第三個連接的key值,第四個是連接的方式,how為left時表示是左連接。SQL操作時基本也是同樣的邏輯,要指定主表,從表,連接方式和連接字段。此處我們使用user連接order并查詢所有字段和所有記錄。具體代碼如下所示,由于我們的數據沒有空值,所以體現不出左連接的特點,感興趣的讀者可以自己嘗試下。(點擊圖片可以查看大圖)
-
其他連接方式
如果要實現inner join,outer join,right join,pandas中相應的how參數為inner或者不填,outer,right。SQL也是同樣直接使用對應的關鍵字即可。其中inner join 可以縮寫為join。本例子中inner join 和left join的結果是一樣的,在這里不作結果展示,pandas和SQL代碼如下。
pd.merge(user_data, order_data, on='uid', how='inner')
SELECT * FROM t_user ainner join t_order bon a.uid = b.uid;
8.union操作
union相關操作分為union和union all兩種。二者通常用于將兩份含有同樣字段的數據縱向拼接起來的場景。但前者會進行去重。例如,我現在有一份order2的訂單數據,包含的字段和order數據一致,想把兩者合并到一個dataframe中。SQL場景下也是期望將order2表和order表合并輸出。執行的代碼如下:(點擊圖片可以查看大圖)
以上是沒有去重的情況,如果想要去重,SQL需要用union關鍵字。而pandas則需要加上去重操作。
order_union = pd.concat([order_data, order_data2]).drop_duplicates()
select * fromt_order union select * fromt_order2
9.排序操作
我們在實際工作中經常需要按照某一列字段進行排序。pandas中的排序使用sort_values方法,SQl中的排序可以使用order_by關鍵字。我們用一個實例說明:按照每個uid的訂單數從高到低排序。這是在前面聚合操作的基礎上的進行的。相應的代碼可以參考下方:(點擊圖片可以查看大圖)
排序時,asc表示升序,desc表示降序,能看到兩種方法都指定了排序方式,原因是默認是會按照升序排列。在此基礎上,可以做到對多個字段的排序。pandas里,dataframe的多字段排序需要用by指定排序字段,SQL只要將多個字段依次卸載order by之后即可。例如,輸出uid,訂單數,訂單金額三列,并按照uid降序,訂單金額升序排列。(點擊圖片可以查看大圖)
在pandas中可能有一些細節需要注意,比如我們將聚合結果先賦值,然后重命名,并指定了inplace=True替換原來的命名,最后才進行排序,這樣寫雖然有點繞,但整體思路比較清晰。
10.case when 操作
相比于其他操作,case when 操作可能不是那么“通用”。它更常見于SQL場景中,可能會用于分組,可能會用于賦值,也可能用于其他場景。分組,比如按照一定的分數區間分成優良中差。賦值,比如當數值小于0時,按照0計算。我們來舉例看一下分組的場景。將每個uid按照總金額分為[0-300),[300,600),[600,900),三組。分別用pandas和SQL實現如下,注意這里我們的基礎數據是上一步的order_df,SQL中也需要用子查詢來實現。(點擊圖片可以查看大圖)
熟悉pandas的朋友應該能想到,pandas的這種分組操作有一種專門的術語叫“分箱”,相應的函數為cut,qcut,能實現同樣的效果。為了保持和SQL操作的一致性,此處采用了map函數的方式。您可以自己查閱資料了解另外的實現方式。
11.更新和刪除操作
更新和刪除都是要改變原有數據的操作。對于更新操作,操作的邏輯是:先選出需要更新的目標行,再進行更新。pandas中,可以使用前文提到的方式進行選擇操作,之后可以直接對目標列進行賦值,SQL中需要使用update關鍵字進行表的更新。示例如下:將年齡小于20的用戶年齡改為20。(點擊圖片可以查看大圖)
刪除操作可以細分為刪除行的操作和刪除列的操作。對于刪除行操作,pandas的刪除行可以轉換為選擇不符合條件進行操作。SQL需要使用delete關鍵字。例如刪除年齡為30歲的用戶:(點擊圖片可以查看大圖)
對于刪除列的操作。pandas需要使用drop方法。SQL也需要使用drop關鍵字。(點擊圖片可以查看大圖)
總結:
簡單粗暴,小結如下圖所示:
reference:
https://pandas.pydata.org/pandas-docs/stable/getting_started/comparison/comparison_with_sql.html
https://juejin.im/post/5b5e5b2ee51d4517df1510c7
需要說明的是,pandas和SQL是兩種不同的工具,本文進行比較并不想說明孰優孰劣,只是為了對于二者的類似操作加深理解,從而方便實際工作中更高效的使用二者。實際工作中的操作可能比本文涉及到的復雜很多,甚至會有多種組合的方式出現,也可能會有本文沒有提及的情況。但我們掌握了本文的方法,就可以以不變應萬變,遇到復雜情況也可從容應對了,希望對你有所幫助!公眾號后臺回復“對比”可以獲得本次聯系的數據樣例以及文章清晰PDF版本,您可自行進行練習。
推薦閱讀: