現(xiàn)在我們已經(jīng)學(xué)會如何將數(shù)據(jù)導(dǎo)入 DataFrame 中鼻百,我們可以利用它來解決工作上遇到的問題绞旅。Pandas提供了大量的函數(shù)质况,本文無法全部覆蓋,有興趣的讀者可以詳細(xì)閱讀官方說明文檔或者利用 google 搜索更多相關(guān)的信息——網(wǎng)上有許多 StackOverflow 的問題和一些介紹該軟件庫的技術(shù)博客玻靡。
接下來我們將利用MovieLens數(shù)據(jù)集來介紹 DataFrame 的使用方法结榄。
檢查數(shù)據(jù)
Pandas 中有許多用于獲取 DataFrame 基本信息的函數(shù),其中最常用的是 info 方法囤捻。
上述輸出結(jié)果中告訴我們 DataFrame 的一些信息:
1.該數(shù)據(jù)集是一個 DataFrame 實例臼朗。
2.數(shù)據(jù)的行索引是從 0 到 N-1 的一組數(shù)字,其中 N 為 DataFrame 的行數(shù)蝎土。
3.數(shù)據(jù)集中總共有 1682 行觀測值视哑。
4.數(shù)據(jù)集中有五列變量,其中變量 video_release_date 中沒有數(shù)據(jù)誊涯,變量 release_date 和 imdb_url 中存在個別缺失值挡毅。
5.最后一行給出了變量數(shù)據(jù)類型匯總情況,你可以利用 dtypes 方法獲取每個變量的數(shù)據(jù)類型暴构。
6.保存該數(shù)據(jù)集所耗費的內(nèi)存跪呈,你可以利用 .memory_usage 獲取更多信息。
DataFrames 中還有一個 describe 方法取逾,它用于獲取數(shù)據(jù)集的常用統(tǒng)計量信息耗绿。需要注意的是,該方法僅會返回數(shù)值型變量的信息砾隅,所以我們會得到 user_id 和 age 兩個變量的統(tǒng)計量信息误阻。
?從上表中可以看出用戶的平均年齡為 34 歲,最年輕的用戶為 7 歲晴埂,最年長的用戶為 73 歲究反,中位數(shù)為 31 歲,25分位數(shù)為 25 歲儒洛,75 分位數(shù)為 43 歲精耐。
你可能已經(jīng)注意到我的文章中經(jīng)常使用head方法,默認(rèn)情況下晶丘,head方法會返回數(shù)據(jù)集的前五條記錄黍氮,tail方法會返回最后五條記錄唐含。
此外浅浮,我們還可以利用 Python 的常用切片語法來提取數(shù)據(jù)。
Selecting
我們可以將 DataFrames 看出由一組共享索引的 Series 組成捷枯,因此從DataFrame 中選取某個變量將返回一個 Series 對象滚秩。
將多個變量的名字傳遞給 DataFrame,即可獲得一個包含多列變量的 DataFrame淮捆。
從 DataFrame 中提取行數(shù)據(jù)有多種方法郁油,常用的方法有行索引法和布爾索引法本股。
由于通常情況下行索引值都是一組無實際意義的數(shù)值,我們可以利用set_index方法將user_id設(shè)定為索引變量桐腌。默認(rèn)情況下拄显,set_index方法將返回一個新的 DataFrame。
你還可以設(shè)定參數(shù)inplace的數(shù)值來修改現(xiàn)有的 DataFrame 數(shù)據(jù)集案站。
從上表中可以看出躬审,user_id替代了原先的索引變量,我們可以利用iloc方法根據(jù)位置來選擇相應(yīng)的行數(shù)據(jù)蟆盐。
我們也可以利用loc方法根據(jù)label來選取行數(shù)據(jù)承边。
此外,我們還可以利用reset_index方法來恢復(fù)默認(rèn)索引變量石挂。
Joining
在數(shù)據(jù)分析過程中博助,我們經(jīng)常需要根據(jù)一定的規(guī)則合并多個數(shù)據(jù)集。
比如上文提到的 MovieLens 數(shù)據(jù)集就是一個很好的例子——每個電影評價都涉及到用戶和電影信息痹愚,我們可以通過user_id和movie_id將其連接起來富岳。類似于 SQL 中的 JOIN 語法,pandas.merge可以根據(jù)某幾個鍵值合并兩個 DataFrames拯腮。該函數(shù)提供了一系列的參數(shù)(on,left_on,right_on,left_index,right_index)城瞎,這些參數(shù)用于指定合并的規(guī)則。
默認(rèn)情況下疾瓮,pandas.merge采用內(nèi)連接方式合并數(shù)據(jù)集脖镀,我們可以修改參數(shù)how來控制合并的方式。
以下是幾個案例說明:
inner join(默認(rèn)設(shè)定)
從上表中可以看出狼电,兩個表中鍵值不匹配的數(shù)據(jù)被剔除掉了蜒灰。SQL等價語句為:
SELECT left_frame.key, left_frame.left_value, right_frame.value FROM left_frame INNER JOIN right_frame ON left_frame.key = right_frame.key;
如果兩個 DataFrame 的鍵值命名不一致,我們可以left_on和right_on參數(shù)來指定合并的鍵值——pd.merge(left_frame, right_frame, left_on = 'left_key', right_on = 'right_key')肩碟。此外强窖,如果鍵值是 DataFrame 的索引值,我們還可以利用left_index和right_index參數(shù)來指定合并的鍵值——pd.merge(left_frame, right_frame, left_on = 'key', right_index = True)削祈。
left_outer join
從上表可得翅溺,左表中的數(shù)據(jù)全被保留下來,右表中鍵值不匹配的樣本由 NULL 所替代髓抑。SQL 等價語句為:
SELECT left_frame.key, left_frame.left_value, right_frame.right_value FROM left_frame LEFT JOIN right_frame ON left_frame.key = right_frame.key;
right outer join
此時咙崎,我們保留右表的所有數(shù)據(jù),左表中鍵值不匹配的樣本由 NULL 替代吨拍。SQL 等價語句為:
SELECT right_frame.key, left_frame.left_value, right_frame.right_value FROM left_frame RIGHT JOIN right_frame ON left_frame.key = right_frame.key;
full outer join
此時褪猛,我們保留兩個表中所有的觀測值,其中鍵值不匹配的樣本均由 NULL 所替代羹饰。SQL 等價語句為(部分?jǐn)?shù)據(jù)庫不支持 FULL JOIN 語句伊滋,比如 MYSQL):
SELECT IFNULL(left_frame.key, right_frame.key) key, left_frame.left_value, right_frame.right_value FROM left_frame FULL OUTER JOIN right_frame ON left_frame.key = right_frame.key;
Combining
Pandas 還提供了另一種沿著軸向合并 DataFrames 的方法——pandas.concat碳却,該函數(shù)等價于 SQL 中的 UNION 語法。
pandas.concat傳入 Series 或者 DataFrame 的列表對象笑旺,并返回合并后的對象昼浦。需要注意的是由于該函數(shù)處理的是列表對象,所以可以同時合并多個對象筒主。
默認(rèn)情況下座柱,該函數(shù)會沿垂直方向合并不同的對象,其中不匹配的樣本由 NULL 所替代物舒。
此外色洞,我們還可以利用axis參數(shù)來控制合并的方向。
pandas.concat的用途非常廣冠胯,但是我僅僅利用它來合并 Series/DataFrame 對象火诸。
Grouping
我花了好久才掌握了 pandas 中的分組功能,但該功能確實非常實用荠察。
pandas 中的groupby方法主要用于執(zhí)行數(shù)據(jù)分析過程中的split-apply-combine策略置蜀。如果你不熟悉這個方法的話,我建議你閱讀上述說明文檔悉盆。它很好地闡述了如何思考一個數(shù)據(jù)分析問題盯荤,我覺得對于數(shù)據(jù)分析師來說這是一個非常重要的技能。
處理一個數(shù)據(jù)分析問題時焕盟,你通常會將數(shù)據(jù)集切分成一系列小塊數(shù)據(jù)秋秤,然后對每部分的數(shù)據(jù)執(zhí)行相應(yīng)的處理,最后再匯總各部分的運算結(jié)果(這就是split-apply-combine策略的主體思想)脚翘。pandas 中的groupby主要用于解決該問題灼卢,R 語言中的 plyr 和 dplyr 包中也有相應(yīng)的分組函數(shù)。
如果你曾經(jīng)接觸過 SQL 的 GROUP BY 功能或者 Excel 中的數(shù)據(jù)透視表功能来农,那么你的腦海中已經(jīng)有了這種觀念鞋真,只是你沒有意識到罷了。
假設(shè)我們擁有一個 DataFrame沃于,我們想要計算每個組的平均值涩咖,如下圖所示:
芝加哥政府將整個城市的員工工資數(shù)據(jù)掛在其數(shù)據(jù)開放平臺上,我們接下來利用這些數(shù)據(jù)來舉例說明groupby方法繁莹。
由于該數(shù)據(jù)集的工資變量中包含美元符號檩互,所以 Python 會識別成字符型變量。我們可以利用concerters參數(shù)來改變讀取規(guī)則蒋困。
pandas的groupby方法將返回一個 DataFrameGroupBy 對象盾似,該對象擁有許多常用的匯總方法敬辣。
count方法將返回每一列變量中所有非缺失數(shù)據(jù)的個數(shù)雪标,size方法將返回每組變量的個數(shù)零院。
此外,我們還可以利用sum和mean來計算變量的總數(shù)和平均數(shù)村刨。
我們還可以對單獨的分組序列對象進(jìn)行計算:比如我們想要了解數(shù)據(jù)集中最常見的五個部門名稱:
SELECT department, COUNT(DISTINCT title) FROM chicago GROUP BY department ORDER BY 2 DESC LIMIT 5;
pandas 中的語法為:
split-apply-combine
groupby方法最強大的地方在于它的split-apply-combine能力告抄。
如果我們想要了解每個部門中最高工資的員工,我們要怎么做呢嵌牺?首先打洼,我們可以利用 SQL 語句來查詢:
SELECT * FROM chicago c INNER JOIN ( SELECT department, max(salary) max_salary FROM chicago GROUP BY department ) m ON c.department = m.department AND c.salary = m.max_salary;
上述代碼會返回每個部門中最高收入的所有員工信息,或者你可以更改表格中的數(shù)據(jù)逆粹,增加一列變量然后執(zhí)行更新語句募疮。
備注:該方法適用于 PostgreSQL, T-SQL 和 Oracle 數(shù)據(jù)庫,但考慮到使用的便捷性僻弹,本文中選取 MySQL 作為默認(rèn)數(shù)據(jù)庫形式阿浓。不幸的是,MySQL 中沒有相似的函數(shù)蹋绽。
利用groupby方法我們可以定義一個函數(shù)用于將所有的觀測值從1標(biāo)記到N芭毙。我們還可以利用apply函數(shù)來實現(xiàn)這個功能: