一場pandas與SQL的巔峰大戰(一)

作為一名數據分析師,平常用的最多的工具是SQL(包括MySQL和Hive SQL等)。對于存儲在數據庫中的數據,自然用SQL提取會比較方便,但有時我們會處理一些文本數據(txt,csv),這個時候就不太好用SQL了。Python也是分析師常用的工具之一,尤其pandas更是一個數據分析的利器。雖然二者的語法,原理可能有很大差別,但在實現的功能上,他們有很多相通的地方,這里特進行一個總結,方便大家對比學習~

本次學習的數據是虛構的訂單數據,和實際業務無關,目的只是為了學習。大概長下面這樣子,分別表示,自增id,訂單時間,用戶id,訂單id,訂單金額。

image

我們將用pandas和SQL來實現同樣的目標,以此來聯系二者,達到共同學習的目的。數據可以在公眾號后臺回復“對比”獲取,你將得到本文所有的excel數據和SQL腳本數據以及本文的清晰PDF版本,便于實操和查看。

準備工作:

  • pandas準備,我們本次采用jupyter notebook進行演示。

    import pandas as pdorder_data = pd.read_csv('order.csv')
    
  • SQL 準備

    只需將我提供的SQL文件運行一下即可將數據插入數據庫表中。推薦使用navicate客戶端連接數據庫。

image

開始學習

1.查看全部數據或者前n行數據

查看全部數據,pandas中直接打印dataframe對象即可,此處是order_data。而在SQL中,需要執行的語句是select * from t_order;表示從t_order表中查詢全部的數據,*號表示查詢所有的字段。結果如下:(點擊圖片可以查看大圖)

image

如果只想查看前10行數據呢。pandas可以調用head(n)方法,n是行數。MySQL可以使用limit n,n同樣表示行數。(點擊圖片可以查看大圖)

image

2.查詢特定列的數據

有的時候我們只想查看某幾列的數據。在pandas里可以使用中括號或者loc,iloc等多種方式進行列選擇,可以選擇一列或多列。loc方式可以直接寫列名,iloc方式需要指定索引,即第幾列。SQL里只需寫相應的列名即可,舉例如下,實際操作一下更容易理解,選擇一種自己習慣的即可。(點擊圖片可以查看大圖)

image
image

3.查詢特定列去重后的數據

例如我們想查看一共有多少人(去重過的)下過單。pandas里有unique方法,SQL里有distinct關鍵字。如下面圖左側代碼所示。兩種方式輸出的結果都含有9個uid,并且知道是哪9個。如果僅僅想知道有多少個uid,不關注具體值的話,可以參考右邊的SQL,pandas用nunique()方法實現,而SQL里就需要用到一個count聚合函數與distinct組合的方式,表示去重并計數。(點擊圖片可以查看大圖)

image

4.查詢帶有1個條件的數據

例如我們要查詢uid為10003的所有記錄。pandas需要使用布爾索引的方式,而SQL中需要使用where關鍵字。指定條件時,可以指定等值條件,也可以使用不等值條件,如大于小于等。但一定要注意數據類型。例如如果uid是字符串類型,就需要將10003加引號,這里是整數類型所以不用加。代碼如下:(點擊圖片可以查看大圖)

image

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有多少訂單量。兩種工具的操作如下:(點擊圖片可以查看大圖)

image

如果想要同時對不同的字段進行不同的聚合操作。例如目標變成:求每個uid的訂單數量和訂單總金額。寫法會稍微不同一些,如下圖所示。(點擊圖片可以查看大圖)

image

更進一步的,我們可以對結果的數據集進行重新命名。pandas可以使用rename方法,MySQL可以使用as 關鍵字進行結果的重命名。(點擊圖片可以查看大圖)

image

7.join相關操作

join相關的操作有inner join,left join,right join,full join,等。pandas中統一通過pd.merge方法,設置不同的參數即可實現不同的dataframe的連接。而SQL里就可以直接使用相應的關鍵字進行兩個表的連接。為了演示,我們此處引入一個新的數據集,user.csv(對應t_user表)。包含了用戶的昵稱,年齡信息。數據樣例如下所示。(點擊圖片可以查看大圖)

image
  • left join

    首先需要把數據加載進來:

    user_data = pd.read_csv('user.csv')
    

    pandas的merge函數傳入4個參數,第一個是連接的主表,第二個是連接從表,第三個連接的key值,第四個是連接的方式,how為left時表示是左連接。SQL操作時基本也是同樣的邏輯,要指定主表,從表,連接方式和連接字段。此處我們使用user連接order并查詢所有字段和所有記錄。具體代碼如下所示,由于我們的數據沒有空值,所以體現不出左連接的特點,感興趣的讀者可以自己嘗試下。(點擊圖片可以查看大圖)

image
  • 其他連接方式

    如果要實現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表合并輸出。執行的代碼如下:(點擊圖片可以查看大圖)

image

以上是沒有去重的情況,如果想要去重,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的訂單數從高到低排序。這是在前面聚合操作的基礎上的進行的。相應的代碼可以參考下方:(點擊圖片可以查看大圖)

image

排序時,asc表示升序,desc表示降序,能看到兩種方法都指定了排序方式,原因是默認是會按照升序排列。在此基礎上,可以做到對多個字段的排序。pandas里,dataframe的多字段排序需要用by指定排序字段,SQL只要將多個字段依次卸載order by之后即可。例如,輸出uid,訂單數,訂單金額三列,并按照uid降序,訂單金額升序排列。(點擊圖片可以查看大圖)

image

在pandas中可能有一些細節需要注意,比如我們將聚合結果先賦值,然后重命名,并指定了inplace=True替換原來的命名,最后才進行排序,這樣寫雖然有點繞,但整體思路比較清晰。

10.case when 操作

相比于其他操作,case when 操作可能不是那么“通用”。它更常見于SQL場景中,可能會用于分組,可能會用于賦值,也可能用于其他場景。分組,比如按照一定的分數區間分成優良中差。賦值,比如當數值小于0時,按照0計算。我們來舉例看一下分組的場景。將每個uid按照總金額分為[0-300),[300,600),[600,900),三組。分別用pandas和SQL實現如下,注意這里我們的基礎數據是上一步的order_df,SQL中也需要用子查詢來實現。(點擊圖片可以查看大圖)

image

熟悉pandas的朋友應該能想到,pandas的這種分組操作有一種專門的術語叫“分箱”,相應的函數為cut,qcut,能實現同樣的效果。為了保持和SQL操作的一致性,此處采用了map函數的方式。您可以自己查閱資料了解另外的實現方式。

11.更新和刪除操作

更新和刪除都是要改變原有數據的操作。對于更新操作,操作的邏輯是:先選出需要更新的目標行,再進行更新。pandas中,可以使用前文提到的方式進行選擇操作,之后可以直接對目標列進行賦值,SQL中需要使用update關鍵字進行表的更新。示例如下:將年齡小于20的用戶年齡改為20。(點擊圖片可以查看大圖)

image

刪除操作可以細分為刪除行的操作和刪除列的操作。對于刪除行操作,pandas的刪除行可以轉換為選擇不符合條件進行操作。SQL需要使用delete關鍵字。例如刪除年齡為30歲的用戶:(點擊圖片可以查看大圖)

image

對于刪除列的操作。pandas需要使用drop方法。SQL也需要使用drop關鍵字。(點擊圖片可以查看大圖)

image
總結:

簡單粗暴,小結如下圖所示:

image

reference:

https://pandas.pydata.org/pandas-docs/stable/getting_started/comparison/comparison_with_sql.html

https://juejin.im/post/5b5e5b2ee51d4517df1510c7

需要說明的是,pandas和SQL是兩種不同的工具,本文進行比較并不想說明孰優孰劣,只是為了對于二者的類似操作加深理解,從而方便實際工作中更高效的使用二者。實際工作中的操作可能比本文涉及到的復雜很多,甚至會有多種組合的方式出現,也可能會有本文沒有提及的情況。但我們掌握了本文的方法,就可以以不變應萬變,遇到復雜情況也可從容應對了,希望對你有所幫助!公眾號后臺回復“對比”可以獲得本次聯系的數據樣例以及文章清晰PDF版本,您可自行進行練習。

推薦閱讀:

左手pandas右手Excel,帶你學習數據透視表

一次不算愉悅的爬蟲與可視化之旅

關于Left join,你可能不知道這些......

我所理解的互聯網數據分析師

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容