獲取文中的
CSV
文件用於代碼編程以及文章首發地址,請點擊下方超鏈接
在本文中,我們將使用Python
的Pandas
庫逐步完成許多不同的數據清理任務。具體而言,我們將重點關注可能是最大的數據清理任務,即 缺少值。
缺失值的來源
在深入研究代碼之前,了解丟失數據的來源很重要。這是數據丟失的一些典型原因:
- 用戶忘記填寫字段。
- 從舊版數據庫手動傳輸時,數據丟失。
- 發生編程錯誤。
- 用戶選擇不填寫字段。
其中一些來源只是簡單的隨機錯誤。在其他時候,可能會有更深層的原因導致數據丟失。
准備工作
在開始清理數據集之前,最好先大致了解一下數據。
- 有哪些功能?
- 預期的類型是什么(
int,float,string,boolean
)? - 是否有明顯的缺失數據(熊貓可以檢測到的值)?
- 是否還有其他類型的丟失數據不太明顯(無法通過Pandas輕松檢測到)?
了說明我的意思,讓我們開始研究示例。
我們要使用的數據是非常小的房地產數據集。獲取CSV
文件。你可以單擊此處獲取,以便可以進行編碼。
快速瀏覽一下數據:
快速了解數據的一種好方法是查看前幾行。在Pandas
中,你要編寫以下代碼:
# Importing libraries
import pandas as pd
import numpy as np
# Read csv file into a pandas dataframe
df = pd.read_csv("property data.csv")
# Take a look at the first few rows
print df.head()
Out:
ST_NUM ST_NAME OWN_OCCUPIED NUM_BEDROOMS
0 104.0 PUTNAM Y 3.0
1 197.0 LEXINGTON N 3.0
2 NaN LEXINGTON N 3.0
3 201.0 BERKELEY NaN 1.0
4 203.0 BERKELEY Y 3.0
我知道我說過我們將使用Pandas
,但是可以看到我也使用了Numpy
。稍后我們將使用它來重命名一些缺失的值。
導入庫后,我們將csv
文件讀取到Pandas
數據框中。
使用該方法,我們可以輕松看到前幾行。(使用.head()
方法)
從列名稱中推斷出以下字符組非常容易:
ST_NUM
: 街道號碼ST_NAME
: 街道名稱OWN_OCCUPIED
:住所所有人是否被占用NUM_BEDROOMS
:卧室數
我們還可以進行設置,獲取的數據類型是啥?
ST_NUM
:float或int…某種數字類型ST_NAME
: 細繩OWN_OCCUPIED
:字符串…Y(“是”)或N(“否”)NUM_BEDROOMS
:float或int,數字類型
標准缺失值
“標准缺失值”是什么意思?這些是Pandas
可以檢測到的缺失值。
回到我們的原始數據集,讓我們看一下“ ST_NUM
”列。
第三列中有一個空單元格。在第七行中,有一個“ NA
”值。
顯然,這些都是缺失值。讓我們看看Pandas
如何處理這些問題
# 查看ST_NUM列
print df['ST_NUM']
print df['ST_NUM'].isnull()
# 查看ST_NUM列
Out:
0 104.0
1 197.0
2 NaN
3 201.0
4 203.0
5 207.0
6 NaN
7 213.0
8 215.0
Out:
0 False
1 False
2 True
3 False
4 False
5 False
6 True
7 False
8 False
看一下該列,我們可以看到Pandas
在空白處填充了“ NA
”。使用該方法,我們可以確認缺失值和“ NA
”都被識別為缺失值。兩個布爾響應均為。isnull()
和True
這是一個簡單的示例,但強調了一個重點。Pandas
會將空單元格和“ NA
”類型都識別為缺失值。 下面,我將介紹一些Pandas
無法識別的類型。
非標准缺失值
有時可能是缺少具有不同格式的值的情況。
讓我們看一下“Number of Bedrooms
”一欄,了解我的意思。
在此列中,有四個缺失值。
- n/a
- NA
- —
- na
從上面中,我們知道Pandas
會將“ NA
”識別為缺失值,但其他的情況呢?讓我們來看看。
# 看NUM_BEDROOMS這一欄
print df['NUM_BEDROOMS']
print df['NUM_BEDROOMS'].isnull()
Out:
0 3
1 3
2 n/a
3 1
4 3
5 NaN
6 2
7 --
8 na
Out:
0 False
1 False
2 False
3 False
4 False
5 True
6 False
7 False
8 False
就像以前一樣,Pandas
認為“ NA
”是缺失的價值。不幸的是,其他類型未被識別。
如果有多個用戶手動輸入數據,則這是一個常見問題。也許我喜歡使用“ n / a
”,但是其他人喜歡使用“ na
”。
檢測這些各種格式的一種簡單方法是將它們放在列表中。然后,當我們導入數據時,Pandas
會立即識別出它們。這是我們將如何執行此操作的示例。
# 列出缺失的值類型
missing_values = ["n/a", "na", "--"]
df = pd.read_csv("property data.csv", na_values = missing_values)
現在,讓我們再看一下該欄,看看會發生什么。
# 看NUM_BEDROOMS這一欄
print df['NUM_BEDROOMS']
print df['NUM_BEDROOMS'].isnull()
Out:
0 3.0
1 3.0
2 NaN
3 1.0
4 3.0
5 NaN
6 2.0
7 NaN
8 NaN
Out:
0 False
1 False
2 True
3 False
4 False
5 True
6 False
7 True
8 True
下面中,我們將介紹一種更復雜但很常見的缺失值類型。
意外的缺失值
到目前為止,我們已經看到了標准缺失值和非標准缺失值。如果我們出現意外類型怎么辦?
例如,如果我們的功能應該是字符串,但是有數字類型,那么從技術上講,這也是一個缺失值。
讓我們看一下“Owner Occupied
**”一欄,看看我在說什么。
從前面的示例中,我們知道Pandas
將檢測到第7行中的空單元格為缺失值。讓我們用一些代碼進行確認。
# 查看OWN_OCCUPIED列
print df['OWN_OCCUPIED']
print df['OWN_OCCUPIED'].isnull()
# 查看OWN_OCCUPIED列
Out:
0 Y
1 N
2 N
3 12
4 Y
5 Y
6 NaN
7 Y
8 Y
Out:
0 False
1 False
2 False
3 False
4 False
5 False
6 True
7 False
8 False
在第四行中,數字為12。Owner Occupied
的響應顯然應該是字符串(Y或N)
,因此此數字類型應為缺失值。
這個示例稍微復雜一點,因此我們需要考慮一種策略來檢測這些類型的缺失值。有很多不同的方法,但是這是我要通過這種方法工作的方式。
- 遍歷OWN_OCCUPIED列
- 嘗試將條目轉換為整數
- 如果條目可以更改為整數,請輸入缺失值
- 如果數字不能是整數,我們知道它是一個字符串,所以繼續
看一下代碼,然后我將對其進行詳細介紹
# 檢測數據
cnt=0
for row in df['OWN_OCCUPIED']:
try:
int(row)
df.loc[cnt, 'OWN_OCCUPIED']=np.nan
except ValueError:
pass
cnt+=1
在代碼中,我們循環瀏覽“所有者已占用”列中的每個條目。要嘗試將條目更改為整數,我們使用。int(row)
如果可以將值更改為整數,則可以使用Numpy's
將條目更改為缺少的值。np.nan
另一方面,如果不能將其更改為整數,我們pass
將繼續。
您會注意到我使用try
和except ValueError
。這稱為異常處理,我們使用它來處理錯誤。
如果我們嘗試將一個條目更改為一個整數並且無法更改,則將ValueError返回a
,並且代碼將停止。為了解決這個問題,我們使用異常處理來識別這些錯誤,並繼續進行下去。
代碼的另一個重要部分是.loc
方法。這是用於修改現有條目的首選Pandas方法。有關此的更多信息,請查看Pandas
文檔。
現在,我們已經研究了檢測缺失值的不同方法,下面將概述和替換它們。
總結缺失值
清除缺失的值后,我們可能要對它們進行匯總。例如,我們可能要查看每個功能的缺失值總數。
# Total missing values for each feature
print df.isnull().sum()
Out:
ST_NUM 2
ST_NAME 0
OWN_OCCUPIED 2
NUM_BEDROOMS 4
在更多的時候,我們可能需要進行快速檢查,以查看是否根本缺少任何值。
# Any missing values?
print df.isnull().values.any()
Out:
True
我們可能還希望獲得缺失值的總數。
# Total number of missing values
print df.isnull().sum().sum()
Out:
8
在上面,我們總結了缺失值的數量,讓我們看一下如何進行一些簡單的替換。
更換
通常,您必須弄清楚如何處理缺失值。
有時,您只是想刪除這些行,而其他時候,您將替換它們。
正如我之前提到的,這不應該掉以輕心。我們將介紹一些基本的推論。
# 用一個數字替換缺失的值
df['ST_NUM'].fillna(125, inplace=True)
如果進行基於位置的插補。
# 基於位置的更換
df.loc[2,'ST_NUM'] = 125
替換缺失值的一種非常常見的方法是使用中位數。
# 取代使用中位數
median = df['NUM_BEDROOMS'].median()
df['NUM_BEDROOMS'].fillna(median, inplace=True)