一、先建立一組有問題的資料
先自己製造一份資料,方便觀察。
import pandas as pd
data = [
{
"title": "Book A",
"price": 51.77,
"stock": 22,
"rating": 4
},
{
"title": "Book B",
"price": 35.02,
"stock": None,
"rating": 5
},
{
"title": "Book C",
"price": None,
"stock": 15,
"rating": 3
},
{
"title": "Book A",
"price": 51.77,
"stock": 22,
"rating": 4
}
]
df = pd.DataFrame(data)
print(df)
結果大概會是:
title price stock rating
0 Book A 51.77 22.0 4
1 Book B 35.02 NaN 5
2 Book C NaN 15.0 3
3 Book A 51.77 22.0 4
這裡的:
NaN
就是 Pandas 常見的缺失值表示方式。
二、什麼是缺失值?
缺失值就是資料原本應該有內容,但是現在沒有。
例如:
price = NaN
可能代表:
網站沒有提供價格
爬蟲沒有成功抓到
原始資料本身就是空的
資料清理過程中產生問題
這時候不能直接假設它是 0。
例如:
NaN
和:
0
代表的是完全不同的意思。
三、使用 isnull() 找缺失值
可以使用:
print(df.isnull())
結果會顯示每個位置是不是缺失值:
title price stock rating
0 False False False False
1 False False True False
2 False True False False
3 False False False False
True 就代表這個位置是缺失值。
四、統計每個欄位有多少缺失值
這個功能在實際資料分析非常常用。
print(df.isnull().sum())
結果:
title 0
price 1
stock 1
rating 0
代表:
title → 沒有缺失
price → 1 筆缺失
stock → 1 筆缺失
rating → 沒有缺失
所以如果今天拿到一份不知道品質如何的資料,可以先做:
df.isnull().sum()
快速檢查。
五、直接刪除缺失資料
如果某些資料缺失,而且我們決定不要這些資料,可以使用:
df_clean = df.dropna()
然後:
print(df_clean)
原本:
Book A
Book B
Book C
Book A
其中 Book B 和 Book C 有缺失值,所以會被移除。
最後可能只剩:
Book A
Book A
這種方法很簡單。
但是也有一個問題:
資料不一定真的應該被刪掉。
如果 1000 筆資料裡面只有 2 筆缺失,刪掉可能沒什麼影響。
但如果有 1000 筆資料,其中 400 筆都有缺失,全部刪掉就可能損失太多資料。
所以另一種方法是:
填補缺失值。
六、使用 fillna() 填補缺失值
例如 stock 缺失時,我們可以先設定成:
0
df["stock"] = df["stock"].fillna(0)
再查看:
print(df)
原本:
Book B stock = NaN
會變成:
Book B stock = 0
但這裡要注意:
不是所有缺失值都適合填 0。
如果價格缺失:
price = NaN
直接:
price = 0
可能會造成錯誤的分析結果。
七、用平均值填補
有些數值資料可以考慮使用平均值。
例如:
average_price = df["price"].mean()
df["price"] = df["price"].fillna(
average_price
)
假設原本:
51.77
35.02
NaN
51.77
平均值可能是:
46.19
那缺失的價格就會被填成:
46.19
不過這只是一種資料處理方式,實際分析時還是要根據資料的意義決定。
八、檢查重複資料
今天另一個重要問題就是:
Duplicate Data
例如:
Book A
Book B
Book C
Book A
Book A 出現兩次。
可以使用:
print(df.duplicated())
結果:
0 False
1 False
2 False
3 True
最後一筆 True 就代表它是重複資料。
九、統計有多少筆重複資料
可以:
print(df.duplicated().sum())
結果:
1
代表有 1 筆重複資料。
十、刪除重複資料
使用:
df = df.drop_duplicates()
再:
print(df)
就會變成:
Book A
Book B
Book C
重複的 Book A 被移除了。
十一、指定欄位判斷重複
有時候我們不一定要整列完全一樣才算重複。
例如:
title price stock
Book A 51.77 22
Book A 51.77 30
雖然 stock 不一樣,但是如果我們認為 title 就應該是唯一值,可以:
df = df.drop_duplicates(
subset=["title"]
)
這樣 Pandas 就會按照 title 判斷重複。
十二、把今天的功能放在一起
現在可以建立一個比較完整的資料清理流程:
import pandas as pd
data = [
{
"title": "Book A",
"price": 51.77,
"stock": 22,
"rating": 4
},
{
"title": "Book B",
"price": 35.02,
"stock": None,
"rating": 5
},
{
"title": "Book C",
"price": None,
"stock": 15,
"rating": 3
},
{
"title": "Book A",
"price": 51.77,
"stock": 22,
"rating": 4
}
]
df = pd.DataFrame(data)
print("原始資料")
print(df)
print()
print("缺失值數量")
print(df.isnull().sum())
print()
print("重複資料數量")
print(df.duplicated().sum())
df["stock"] = df["stock"].fillna(0)
df["price"] = df["price"].fillna(
df["price"].mean()
)
df = df.drop_duplicates()
print()
print("清理後資料")
print(df)
整個流程就是:
原始資料
↓
檢查缺失值
↓
處理缺失值
↓
檢查重複資料
↓
刪除重複資料
↓
乾淨的 DataFrame
十三、實際接到前幾天的爬蟲
前面我們已經有:
df = pd.DataFrame(all_books)
所以今天可以直接對爬蟲資料進行檢查。
print("資料筆數:", len(df))
print()
print("缺失值:")
print(df.isnull().sum())
print()
print("重複資料:")
print(df.duplicated().sum())
如果發現:
price 0
stock 2
rating 0
title 0
就代表 stock 有 2 筆缺失。
接著再決定怎麼處理。
例如:
df["stock"] = df["stock"].fillna(0)
十四、清理後再次確認
清理完不要直接當作成功。
還要再檢查一次:
print(df.isnull().sum())
以及:
print(df.duplicated().sum())
如果結果:
title 0
price 0
stock 0
rating 0
以及:
0
就代表目前沒有發現缺失值和重複資料。
這也是資料分析很重要的一個習慣:
處理完資料後,再檢查一次。
十五、今天學到的 Pandas 指令
今天主要記住這幾個就可以:
df.isnull()
檢查缺失值。
df.isnull().sum()
統計每個欄位缺失值數量。
df.dropna()
刪除含有缺失值的資料。
df.fillna()
填補缺失值。
df.duplicated()
檢查重複資料。
df.drop_duplicates()
刪除重複資料。
十六、今天的資料分析流程
目前整個專題的流程越來越清楚:
網站
↓
Requests
↓
BeautifulSoup
↓
爬蟲
↓
資料清理
↓
DataFrame
↓
檢查缺失值
↓
處理缺失值
↓
檢查重複資料
↓
清理完成
↓
資料分析
前面的爬蟲負責「取得資料」。
今天的 Pandas 則開始負責「整理資料」。
接下來就可以繼續進行更進一步的資料轉換、分組和統計。