現(xiàn)在我們已經(jīng)學(xué)會如何將數(shù)據(jù)導(dǎo)入 DataFrame 中,我們可以利用它來解決工作上遇到的問題。Pandas提供了大量的函數(shù),本文無法全部覆蓋,有興趣的讀者可以詳細閱讀官方說明文檔或者利用 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方法,默認情況下,head方法會返回數(shù)據(jù)集的前五條記錄,tail方法會返回最后五條記錄。


此外,我們還可以利用 Python 的常用切片語法來提取數(shù)據(jù)。

Selecting
我們可以將 DataFrames 看出由一組共享索引的 Series 組成,因此從DataFrame 中選取某個變量將返回一個 Series 對象。

將多個變量的名字傳遞給 DataFrame,即可獲得一個包含多列變量的 DataFrame。

從 DataFrame 中提取行數(shù)據(jù)有多種方法,常用的方法有行索引法和布爾索引法。


由于通常情況下行索引值都是一組無實際意義的數(shù)值,我們可以利用set_index方法將user_id設(shè)定為索引變量。默認情況下,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ù)默認索引變量。

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ī)則。
默認情況下,pandas.merge采用內(nèi)連接方式合并數(shù)據(jù)集,我們可以修改參數(shù)how來控制合并的方式。

以下是幾個案例說明:


inner join(默認設(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ù)處理的是列表對象,所以可以同時合并多個對象。

默認情況下,該函數(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ù)。

我們還可以對單獨的分組序列對象進行計算:比如我們想要了解數(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 作為默認數(shù)據(jù)庫形式。不幸的是,MySQL 中沒有相似的函數(shù)。
利用groupby方法我們可以定義一個函數(shù)用于將所有的觀測值從1標(biāo)記到N。我們還可以利用apply函數(shù)來實現(xiàn)這個功能:

