目錄
    Add a header to begin generating the table of contents

    pandas map 和 applymap 如何使用?Series 和 DataFrame 各有不同

    pandas map 和 applymap 如何使用?Series 和 DataFrame 各有不同
    Share on facebook
    Share on twitter
    Share on linkedin
    Share on whatsapp
    目錄
      Add a header to begin generating the table of contents

      分析數據時,我們經常需要對每一個元素(element)進行計算和轉換(Transform)。

      比方說,我們想將一群學生身高的列(column)的單位從釐米轉成米時,便需要把每個元素除以 100。

      我們如何妙用 pandas 內置的功能完成這個任務?

      在 Series 的 map 功能

      我們首先介紹在 pandas Series (即一個列 Column)的方法。

      map 功能是一個可以幫我們把一個行動(operation)按元素地使用。比方說,將身高從米轉成釐米時,map 把「乘以 10」這個行動向每一個元素使用。

      我是廣告 ^o^

      Series 上的 map 主要有以下 3 個用途:

      1. 使用 map 進行簡單算法運算(arithmetic operation)或條件運算(conditional operation)
      2. 使用 map 映射數據
      3. 使用 map 將一個 Python 功能使用在每一個元素

      第 1 個用途:簡單算法或條件運算

      import pandas as pd height = pd.Series([1.67, 1.78, 1.45, 1.20]) print(height.map(lambda x: x * 100)) print(height.map(lambda x: x > 1.5))

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      這是一個最簡單的用法。如上圖,運用我們的身高米轉釐米例子,我們使用 .map(lambda x: x * 100) 便可以對每一個元素乘以 100。

      除此之外,我們也可以進行條件的運算,例如上圖使用 .map(lambda x: x > 1.5) 檢查身高是否高於 1.5 米。

      我們在另一篇提及過,您可以想像 lambda x 是一個把列(column)轉成每個元素(element)的語法,讓您可以直接對每一個元素演算。

      我是廣告 ^o^

      當然,如果您有學習過其他編程語言,可能會知道所謂函式多載化(function overloading)。許多我們使用的算法(例如 + – * /)和條件(例如 == != > <)等都可以直接用於 pandas Series 上。

      以下我們可以見到除了使用 map 之外,直接使用原來的運算(operator)反而更快。

      import pandas as pd height = pd.Series([1.67, 1.78, 1.45, 1.20]) print(height * 100) print(height > 1.5)

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      第 2 個用途:映射數據

      這個用途比較貼近 map 這個字原來的意思。

      譬如我們有一個我們去過的國家名稱列表(例如 ['Canada', 'Canada', 'Japan', 'Japan', 'Japan', 'Taiwan', 'Taiwan', 'United Kingdom']),而我們希望數算有多少個國家在亞洲、美洲等,如何達至這個目的?

      我是廣告 ^o^

      map 除了可以用 lambda 的型態處理每一個元素以外,我們亦可以輸入一個字典(dictionary)讓 pandas 知道每一個獨特(unique)的元素應該輸出甚麼結果(例如 Canada -> Americas,Taiwan -> Asia 等)。

      import pandas as pd countries_visited = pd.Series(['Canada', 'Canada', 'Japan', 'Japan', 'Japan', 'Taiwan', 'Taiwan', 'United Kingdom']) countries_visited.map({'Canada': 'Americas', 'Japan': 'Asia', 'Taiwan': 'Asia', 'United Kingdom': 'Europe'})

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      以上的例子裡,我們在 countries_visited.map 的函數輸入一個字典({'Canada': 'Americas', 'Japan': 'Asia', 'Taiwan': 'Asia', 'United Kingdom': 'Europe'}),讓 pandas 知道遇到每一個國家名稱時應該輸出甚麼。

      import pandas as pd countries_visited = pd.Series(['Canada', 'Canada', 'Japan', 'Japan', 'Japan', 'Taiwan', 'Taiwan', 'United Kingdom']) countries_visited.map({'Canada': 'Americas', 'Japan': 'Asia', 'Taiwan': 'Asia', 'United Kingdom': 'Europe'}).value_counts()

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      以上可見,由於 countries_visited.map 也是回傳一個 pandas Series,我們在 .map() 後加入 pandas 內置功能 .value_counts()便可以回傳我們去了每一個洲多少次。

      我是廣告 ^o^

      第 3 個用途:將 Python 功能使用在每一個元素

      import pandas as pd names = pd.Series(['Chan, Siu Wan','Lam, Tai Ming','Yung, Hong Chi']) names.map(len)

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      最後一個 map 的用途時將一個 Python 的功能使用在每一個元素上。

      一個簡單的例子是計算名稱有多少個字元。如果我們想知道 ‘abcd’ 這個字有多少個字元,我們可以使用 len('abcd') 輸出 4。

      而上面的例子顯示我們在 names 這個 pandas Series 裡使用 .apply(len) 的話,可以數算每一個姓名的字元,得出一條有多少字元的 pandas Series。

      我們也可以把自訂功能使用在每一個元素上。 沿用我們國家名稱的例子,我們也可以自訂一個 continent() 的 Python 功能達到相同效果:

      我是廣告 ^o^
      import pandas as pd countries_visited = pd.Series(['Canada', 'Canada', 'Japan', 'Japan', 'Japan', 'Taiwan', 'Taiwan', 'United Kingdom']) def continent(country): if country in ['Canada']: return 'Americas' if country in ['Japan', 'Taiwan']: return 'Asia' if country in ['United Kingdom']: return 'Europe' countries_visited.map(continent)

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      在 DataFrame 的 applymap 功能

      在 pandas DataFrame 也有 applymap 這一個功能。

      本質上,DataFrame 的 applymap 跟 Series 的 map 的作用一樣,但 DataFrame 的 applymap 會將您提供的字典/功能應用在每一個 DataFrame 的元素裡。

      譬如我們有一個量度 2 個箱子長闊高(單位是米)的 DataFrame,有 3 個列(column):height, widthdepth。如果我們想將全部的數字變成釐米,怎麼使用 applymap 達至目的?

      import pandas as pd measures = pd.DataFrame({'height': [1.3,0.6],'width': [0.8,0.9],'depth':[2.5,1.5]}) measures.applymap(lambda x: x * 100)

      註:先按一下綠色按鈕 “Run” 執行代碼,讓您能在 IPython Shell 看到編程結果!

      我是廣告 ^o^

      如上圖,我們可以使用 .applymap(lambda x: x * 100) 把 DataFrame 每一個數字乘以 100,並換成米。

      map 與 apply 的分別

      延伸閱讀:如何使用 pandas 的 apply?Dataframe 加入新 Column?Python 數據整合處理!

      我們在另一篇教學介紹了 pandas 的 apply 功能,而您會發現 apply 似乎跟 map/applymap 的功能十分相似。

      以下我們總括了一些何時使用 map 與 apply 的情況。留意這個分類帶一些個人喜好,但希望能給您作參考。

      用於 pandas Series

      功能用途
      Series.map()map 應該配合一個字典(dictionary)去做分類,就像我們上面的 countries_visited 例子。
      Series.apply()apply 應該配合 Python 功能使用(如 len 或其他自訂功能),就像我們上面的 names 例子。

      用於 pandas DataFrame

      功能用途
      DataFrame.applymap()applymap 適用於所有列都是同一個數據類型的 DataFrame。現實中較小機會用到。
      DataFrame.apply()apply 適用於需要指定某些列個別處理的情況。現實中比較常用到。
      閱讀:如何使用 pandas 的 apply?Dataframe 加入新 Column?Python 數據整合處理!

      總結而言,map 是一個在比較特殊/簡單的情況下使用得宜的功能,而 apply 則比較在日常處理數據的情況時用到。當然,精明的您會因時制宜,在不同情況下選用最合適的方法。

      我是廣告 ^o^

      教學完整代碼

      最後送給大家這篇教學的 Google Colab 完整代碼。如果您不懂得使用免安裝又好用的 Google Colab Notebook,記得閱讀這篇教學了:新手 1/3:5 分鐘免安裝學習 Python?Google Colab Notebook 幫緊您!

      結語

      希望您學會了 map 以後,能懂得如何更快地處理數據吧!

      其他 pandas 文章:

      人氣文章

      快讓我學更多

      small_c_popup.png
      想學習 Python 嗎?
      快來訂閱我們的電子報!