數聚點

數聚點

Share this post

數聚點
數聚點
約維安計畫:進階的資料處理技法
高級約維安

約維安計畫:進階的資料處理技法

第三十七週

Yao-Jen Kuo's avatar
Yao-Jen Kuo
Jan 26, 2024
∙ Paid

Share this post

數聚點
數聚點
約維安計畫:進階的資料處理技法
Share
來源:giphy.com

進階的資料處理技法一覽

繼第三十六週的約維安計畫:基礎的資料處理技法之後,接著要從基礎邁向進階,具體來說,我們將六種處理方法歸類在「進階」部分,分別是:

  1. 定位資料。

  2. 衍生計算欄位。

  3. 處理遺漏值。

  4. 處理文字欄位。

  5. 轉置資料。

  6. 合併資料。

接著我們會分六個小段落示範上述技法,為了能夠示範上述這些進階資料處理,我們先載入兩個儲存在工作目錄中的逗號分隔值檔案 UID_ISO_FIPS_LookUp_Table.csv 與 time_series_covid19_confirmed_global.csv。

lookup_table = pd.read_csv("UID_ISO_FIPS_LookUp_Table.csv")
time_series_confirmed = pd.read_csv("time_series_covid19_confirmed_global.csv")
print(lookup_table)
print(time_series_confirmed)

定位資料

定位資料的方式有兩種,第一種是透過資料的列索引、欄索引名稱來取得資料,使用 df.loc[row_index, column_index] 語法(loc 是 location 的縮寫)。

lookup_table.set_index("Combined_Key").loc["Taiwan*", ["Lat", "Long_", "Population"]]

第二種是透過資料的列相對位置、欄相對位置來取得資料,使用 df.iloc[row_number, column_number] 語法(iloc 是 integer location 的縮寫)。

lookup_table.iloc[782, [8, 9, 11]] 

衍生計算欄位

我們可以使用 Series 的 map() 方法來衍生計算欄位,map() 方法接受兩種輸入形式,第一種是輸入資料結構 dict,衍生計算的邏輯就是從 dict 中的 key 對應成 value。

map_dict = {
    "Taiwan*": "Taiwan"
}
time_series_confirmed["Country/Region"].map(map_dict)[249]

第二種是輸入函數,通常會以 lambda 匿名函數的形式寫作,衍生計算的邏輯就是從 lambda 敘述的輸入對應成輸出。

lookup_table["Combined_Key"] = lookup_table["Combined_Key"].map(lambda x: x.replace("*", "") if "*" in x else x)
lookup_table["Country_Region"] = lookup_table["Country_Region"].map(lambda x: x.replace("*", "") if "*" in x else x)
time_series_confirmed["Country/Region"] = time_series_confirmed["Country/Region"].map(lambda x: x.replace("*", "") if "*" in x else x)
lookup_table[lookup_table["Combined_Key"] == "Taiwan"]

處理遺漏值

面對資料中的遺漏值,我們可以使用 Series 的 isnull() 方法來判斷該資料值是否為遺漏值,輸出的 Series 由布林組成,長度和原始輸入的 Series 相同,並能夠進一步利用布林的天性(False 為整數 0、True 為整數 1)加總輸出的 Series,藉此暸解原始輸入的 Series 共有幾個遺漏值。

print(lookup_table["Province_State"].isnull())
print(lookup_table["Province_State"].isnull().sum())

若是希望判斷「非遺漏值」改採負面表列,Series 亦有對應的 notnull() 方法,或者可以使用 Series 的 NOT 運算符「~」將資料中的布林反轉(Negate)。

print(lookup_table["Province_State"].notnull())
print(~lookup_table["Province_State"].isnull())

判斷遺漏值的存在與否之後,我們可以從三種後續處理方式選擇,一是不對遺漏值做處理,沒錯你並沒有看錯,知道遺漏值存在於資料之中並在專案中與它共存不是罕見的做法;二是使用 Series 與 DataFrame 的 dropna() 方法來刪除遺漏值或者遺漏值存在的列、遺漏值存在的欄。

print(lookup_table["Province_State"].dropna())
print(lookup_table.dropna())

三是使用 Series 與 DataFrame 的 fillna() 方法將遺漏值以指定的常數或參數取代。

lookup_table["Province_State"].fillna("No Province State Data")

處理文字欄位

面對資料中的文字欄位,我們可以使用 Series 底下的 str 小模組中的各種文字處理方法,例如 str.capitalize() 能夠將英文轉換為大寫開頭的格式。

lookup_table["Country_Region"].str.capitalize()

而 str.casefold() 則能夠將英文轉換為全小寫的格式。

lookup_table["Country_Region"].str.casefold()

Series 底下的 str 小模組有眾多的方法可以使用,族繁不及備載,直接查找 Series 的方法文件是最完整便捷的:https://pandas.pydata.org/docs/reference/series.html#string-handling

轉置資料

我們可以使用 Pandas 模組的 melt() 函數將寬格式的資料轉換為長格式。

id_variables = ["Province/State", "Country/Region", "Lat", "Long"]
time_series_confirmed_long = pd.melt(time_series_confirmed, 
                                     id_vars=id_variables,
                                     var_name="date",
                                     value_name="cumulative_confirmed"
                                    )
time_series_confirmed_long

也可以使用資料框的 pivot() 方法將長格式的資料轉換為寬格式。

time_series_confirmed_wide = time_series_confirmed_long.pivot(columns="date",
                                 index=id_variables,
                                 values="cumulative_confirmed"
                                ).reset_index()
time_series_confirmed_wide = time_series_confirmed_wide.rename_axis(None, axis=1)
time_series_confirmed_wide

關於資料的寬格式與長格式背景知識,推薦可以閱讀維基百科的頁面:https://en.wikipedia.org/wiki/Wide_and_narrow_data

合併資料

合併資料的方式分為兩種,第一種是單純的垂直與水平合併,第二種則是根據相同的欄位或列索引水平合併。我們可以使用 Pandas 模組的 concat() 函數進行單純的垂直與水平合併。

print(pd.concat((lookup_table["iso2"], lookup_table["iso3"]), axis=0))
print(pd.concat((lookup_table[["iso2"]], lookup_table[["iso3"]]), axis=1))

如果要根據相同的欄位進行水平合併,我們可以使用 Pandas 模組的 merge() 函數指定對應的欄位與合併參數,預設合併參數為內部連結(Inner join)。

time_series_confirmed_long = time_series_confirmed_long[time_series_confirmed_long["Province/State"].isna()]
lookup_table = lookup_table[["iso2", "iso3", "Country_Region"]]
pd.merge(time_series_confirmed_long, lookup_table,
         left_on="Country/Region", right_on="Country_Region")

如果要根據相同的列索引進行水平合併,我們可以使用資料框物件的 join() 方法指定合併參數,預設合併參數為左外部連結( Left outer-join)。

time_series_confirmed_long = time_series_confirmed_long.set_index("Country/Region")
lookup_table = lookup_table.set_index("Country_Region")
time_series_confirmed_long.join(lookup_table)

關於資料的連結背景知識,推薦可以閱讀:

  1. 約維安計畫:SQL 的進階查詢(第十週)

  2. 維基百科的頁面:https://en.wikipedia.org/wiki/Join_(SQL)

掌握進階的資料操作技巧之後,我們就能夠在下次的電子報中介紹如何應用資料操作技巧彙整中選會選舉資料庫。第三十七週約維安計畫:進階的資料處理技法來到尾聲,希望您也和我一樣期待下一篇文章。對於這篇文章有什麼想法呢?喜歡😻、留言🙋‍♂️、訂閱📨或者分享🙌

Share

Leave a comment


約維安計畫學員專區

約維安計畫學員可以點選下列連結將本篇文章完整的 Google Colab 複製到自己的 Google Drive 之中:

This post is for paid subscribers

Already a paid subscriber? Sign in
© 2025 DATAINPOINT, INC.
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share