16 KiB
資料處理:資料準備
![]() |
|---|
| 資料準備 - Sketchnote by @nitya |
課前測驗
根據資料來源,原始資料可能包含一些不一致性,這些問題會在分析和建模時造成挑戰。換句話說,這些資料可以被歸類為「髒資料」,需要進行清理。本課程重點在於清理和轉換資料的技術,以處理缺失、不準確或不完整的資料。本課程涵蓋的主題將使用 Python 和 Pandas 庫,並在本目錄中的筆記本中進行演示。
清理資料的重要性
-
使用和重用的便利性:當資料被妥善組織和標準化後,搜尋、使用和與他人分享會更加容易。
-
一致性:資料科學通常需要處理多個資料集,來自不同來源的資料集需要合併在一起。確保每個資料集都有共同的標準化,能確保合併後的資料仍然有用。
-
模型準確性:清理過的資料能提高依賴該資料的模型的準確性。
常見的清理目標和策略
-
探索資料集:資料探索(在後續課程中會介紹)可以幫助你發現需要清理的資料。透過視覺化觀察資料集中的值,可以設想其餘部分的樣貌,或提供解決問題的思路。探索可以包括基本查詢、視覺化和抽樣。
-
格式化:根據來源,資料可能在呈現方式上存在不一致性。這可能導致搜尋和表示值時出現問題,資料雖然在資料集中可見,但在視覺化或查詢結果中未正確表示。常見的格式化問題包括解決空白、日期和資料類型。解決格式問題通常由使用資料的人來完成。例如,日期和數字的表示方式可能因國家而異。
-
重複資料:重複出現的資料可能會產生不準確的結果,通常需要移除。這在合併兩個或多個資料集時很常見。然而,有些情況下,合併後的重複資料可能包含額外資訊,需要保留。
-
缺失資料:缺失資料可能導致不準確以及結果偏差。有時可以通過重新載入資料、使用 Python 等程式碼填補缺失值,或直接移除該值及其相關資料來解決。資料缺失的原因多種多樣,解決缺失值的方式可能取決於其缺失的原因。
探索 DataFrame 資訊
學習目標:完成本小節後,你應該能夠熟練地找到 pandas DataFrame 中儲存的資料的一般資訊。
當你將資料載入 pandas 後,資料通常會以 DataFrame 的形式存在(參考之前的課程以獲得詳細概述)。然而,如果你的 DataFrame 中有 60,000 行和 400 列,該如何開始了解你正在處理的資料呢?幸運的是,pandas 提供了一些方便的工具,可以快速查看 DataFrame 的整體資訊以及前幾行和後幾行。
為了探索這些功能,我們將導入 Python 的 scikit-learn 庫並使用一個經典的資料集:Iris 資料集。
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])
| sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | |
|---|---|---|---|---|
| 0 | 5.1 | 3.5 | 1.4 | 0.2 |
| 1 | 4.9 | 3.0 | 1.4 | 0.2 |
| 2 | 4.7 | 3.2 | 1.3 | 0.2 |
| 3 | 4.6 | 3.1 | 1.5 | 0.2 |
| 4 | 5.0 | 3.6 | 1.4 | 0.2 |
- DataFrame.info:首先,
info()方法用於列印DataFrame中內容的摘要。讓我們看看這個資料集的內容:
iris_df.info()
RangeIndex: 150 entries, 0 to 149
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal length (cm) 150 non-null float64
1 sepal width (cm) 150 non-null float64
2 petal length (cm) 150 non-null float64
3 petal width (cm) 150 non-null float64
dtypes: float64(4)
memory usage: 4.8 KB
從中我們知道 Iris 資料集有 150 筆資料,分布在四個欄位中,且沒有空值。所有資料都以 64 位浮點數形式儲存。
- DataFrame.head():接下來,為了檢查
DataFrame的實際內容,我們使用head()方法。讓我們看看iris_df的前幾行:
iris_df.head()
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
- DataFrame.tail():相反地,為了檢查
DataFrame的後幾行,我們使用tail()方法:
iris_df.tail()
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
145 6.7 3.0 5.2 2.3
146 6.3 2.5 5.0 1.9
147 6.5 3.0 5.2 2.0
148 6.2 3.4 5.4 2.3
149 5.9 3.0 5.1 1.8
重點:僅僅透過查看 DataFrame 的元資料或前幾行和後幾行的值,你就能立即了解你正在處理的資料的大小、形狀和內容。
處理缺失資料
學習目標:完成本小節後,你應該知道如何替換或移除 DataFrame 中的空值。
大多數情況下,你想使用(或必須使用)的資料集中都會有缺失值。如何處理缺失資料涉及微妙的取捨,可能會影響最終分析和實際結果。
Pandas 以兩種方式處理缺失值。第一種方式你在之前的部分中已經見過:NaN,即非數值(Not a Number)。這是一個特殊值,是 IEEE 浮點規範的一部分,僅用於表示缺失的浮點值。
對於浮點數以外的缺失值,pandas 使用 Python 的 None 對象。雖然遇到兩種不同的缺失值表示方式可能會讓人感到困惑,但這種設計選擇有其合理的程式設計原因,實際上,這種方式為大多數情況提供了良好的折衷。不過,None 和 NaN 都有一些限制,需注意它們的使用方式。
在筆記本中了解更多關於 NaN 和 None 的資訊!
- 檢測空值:在
pandas中,isnull()和notnull()方法是檢測空資料的主要方法。兩者都返回布林遮罩。接下來我們將使用numpy來處理NaN值:
import numpy as np
example1 = pd.Series([0, np.nan, '', None])
example1.isnull()
0 False
1 True
2 False
3 True
dtype: bool
仔細查看輸出。是否有任何結果讓你感到驚訝?雖然 0 是一個算術上的空值,但它仍然是一個有效的整數,pandas 將其視為有效值。'' 則稍微微妙一些。雖然我們在第一部分中使用它來表示空字串值,但它仍然是一個字串對象,並非 pandas 所認為的空值。
現在,讓我們反過來以更實際的方式使用這些方法。你可以直接將布林遮罩用作 Series 或 DataFrame 的索引,這在處理孤立的缺失(或存在)值時非常有用。
重點:
isnull()和notnull()方法在DataFrame中的使用結果相似:它們顯示結果及其索引,這對於處理資料時非常有幫助。
- 移除空值:除了識別缺失值,pandas 還提供了一種方便的方法來移除
Series和DataFrame中的空值。(特別是在大型資料集中,通常建議直接移除缺失值,而不是以其他方式處理它們。)讓我們回到example1來看看這一點:
example1 = example1.dropna()
example1
0 0
2
dtype: object
注意,這應該與 example3[example3.notnull()] 的輸出類似。不同之處在於,dropna 移除了 Series example1 中的缺失值,而不是僅僅索引遮罩值。
由於 DataFrame 是二維的,它提供了更多移除資料的選項。
example2 = pd.DataFrame([[1, np.nan, 7],
[2, 5, 8],
[np.nan, 6, 9]])
example2
| 0 | 1 | 2 | |
|---|---|---|---|
| 0 | 1.0 | NaN | 7 |
| 1 | 2.0 | 5.0 | 8 |
| 2 | NaN | 6.0 | 9 |
(你是否注意到 pandas 將兩列資料提升為浮點數以容納 NaN?)
你無法從 DataFrame 中移除單個值,因此必須移除整行或整列。根據你的需求,你可能需要移除其中之一,pandas 提供了兩者的選項。由於在資料科學中,列通常代表變數,行代表觀測值,你更可能移除資料的行;dropna() 的預設設定是移除所有包含任何空值的行:
example2.dropna()
0 1 2
1 2.0 5.0 8
如果需要,你也可以移除列中的 NA 值。使用 axis=1 來完成:
example2.dropna(axis='columns')
2
0 7
1 8
2 9
注意,這可能會移除你想保留的大量資料,特別是在較小的資料集中。如果你只想移除包含多個或所有空值的行或列,可以在 dropna 中使用 how 和 thresh 參數來指定這些設定。
預設情況下,how='any'(如果你想自行檢查或查看該方法的其他參數,可以在程式碼單元中執行 example4.dropna?)。你也可以指定 how='all',以僅移除包含所有空值的行或列。讓我們擴展範例 DataFrame 來看看這一點。
example2[3] = np.nan
example2
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 0 | 1.0 | NaN | 7 | NaN |
| 1 | 2.0 | 5.0 | 8 | NaN |
| 2 | NaN | 6.0 | 9 | NaN |
thresh 參數提供了更細緻的控制:你可以設定行或列需要保留的非空值數量:
example2.dropna(axis='rows', thresh=3)
0 1 2 3
1 2.0 5.0 8 NaN
在這裡,第一行和最後一行被移除,因為它們僅包含兩個非空值。
- 填充空值:根據資料集,有時填充空值比移除它們更合理。你可以使用
isnull直接填充,但如果有大量值需要填充,這可能會很繁瑣。由於這是資料科學中的常見任務,pandas 提供了fillna,它返回一個Series或DataFrame的副本,將缺失值替換為你選擇的值。讓我們創建另一個範例Series來看看這在實際中的運作方式。
example3 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))
example3
a 1.0
b NaN
c 2.0
d NaN
e 3.0
dtype: float64
你可以用單一值(例如 0)填充所有空值:
example3.fillna(0)
a 1.0
b 0.0
c 2.0
d 0.0
e 3.0
dtype: float64
你可以向前填充空值,即使用最後一個有效值填充空值:
example3.fillna(method='ffill')
a 1.0
b 1.0
c 2.0
d 2.0
e 3.0
dtype: float64
你也可以向後填充,即向後傳播下一個有效值以填充空值:
example3.fillna(method='bfill')
a 1.0
b 2.0
c 2.0
d 3.0
e 3.0
dtype: float64
如你所料,這對 DataFrame 也適用,但你還可以指定沿著哪個 axis 填充空值。再次使用之前的 example2:
example2.fillna(method='ffill', axis=1)
0 1 2 3
0 1.0 1.0 7.0 7.0
1 2.0 5.0 8.0 8.0
2 NaN 6.0 9.0 9.0
注意,當前一個值不可用進行向前填充時,空值仍然保留。
重點: 處理資料集中缺失值的方法有很多。具體採用的策略(移除、替換,甚至替換的方式)應根據資料的特性來決定。隨著你處理和接觸更多的資料集,你將更能掌握如何應對缺失值。
移除重複資料
學習目標: 在本小節結束時,你應該能夠熟練地識別並移除 DataFrame 中的重複值。
除了缺失資料外,你在真實世界的資料集中還會經常遇到重複的資料。幸運的是,pandas 提供了一種簡便的方法來檢測和移除重複的項目。
- 識別重複值:
duplicated:你可以使用 pandas 的duplicated方法輕鬆地找到重複值。該方法會返回一個布林遮罩,指示某個DataFrame中的項目是否是之前項目的重複。讓我們建立另一個範例DataFrame來看看它的作用。
example4 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'],
'numbers': [1, 2, 1, 3, 3]})
example4
| letters | numbers | |
|---|---|---|
| 0 | A | 1 |
| 1 | B | 2 |
| 2 | A | 1 |
| 3 | B | 3 |
| 4 | B | 3 |
example4.duplicated()
0 False
1 False
2 True
3 False
4 True
dtype: bool
- 移除重複值:
drop_duplicates:該方法會返回一份資料的副本,其中所有duplicated值均為False:
example4.drop_duplicates()
letters numbers
0 A 1
1 B 2
3 B 3
duplicated 和 drop_duplicates 預設會考慮所有列,但你可以指定它們僅檢查 DataFrame 中的部分列:
example4.drop_duplicates(['letters'])
letters numbers
0 A 1
1 B 2
重點: 移除重複資料是幾乎每個資料科學專案中的重要步驟。重複的資料可能會影響分析結果,導致不準確的結論!
🚀 挑戰
所有討論的內容都提供為 Jupyter Notebook。此外,每個部分後面都有練習題,試著完成它們吧!
課後測驗
回顧與自學
有許多方法可以探索並準備你的資料進行分析和建模,而清理資料是一個需要「親身操作」的步驟。試試 Kaggle 上的這些挑戰,探索本課未涵蓋的技術。
作業
免責聲明:
本文件已使用 AI 翻譯服務 Co-op Translator 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。
