1. 程式人生 > >小白學 Python 資料分析(8):Pandas (七)資料預處理

小白學 Python 資料分析(8):Pandas (七)資料預處理

人生苦短,我用 Python

前文傳送門:

小白學 Python 資料分析(1):資料分析基礎

小白學 Python 資料分析(2):Pandas (一)概述

小白學 Python 資料分析(3):Pandas (二)資料結構 Series

小白學 Python 資料分析(4):Pandas (三)資料結構 DataFrame

小白學 Python 資料分析(5):Pandas (四)基礎操作(1)檢視資料

小白學 Python 資料分析(6):Pandas (五)基礎操作(2)資料選擇

小白學 Python 資料分析(7):Pandas (六)資料匯入

引言

上一篇我們介紹了資料匯入,在進行分析之前,還有一個比較重要的步驟就是資料的預處理,很多時候,我們匯入的資料質量並不高,會有很多不達標的資料。

這就和我們每天做飯是一樣的,買回來的菜總歸會有一些不太好的部分,我們需要在做飯之前對這些菜做一些預處理,將不好的部分處理掉。

常見的資料問題主要有缺失資料、重複資料以及異常資料這麼幾種,在開始進行資料分析之前,我們需要先把這部分的資料處理掉。

缺失資料處理

缺失資料其實就是由於某些不為人知的原因導致的部分資料為空,關注點不要放在不為人知的原因是啥上哈,這種原因簡直多了去了,任何一位程式設計師都能舉出來無數種例子。

對於這種部分為空的資料我們通常有兩種處理方式,一種是直接刪除,還有一種是填充某種設定值。

當然,選用哪種方式完全是看具體的業務場景。

首先,第一步當然是把缺失的資料找出來, Pandas 找缺失資料可以使用 info()

這個方法(這裡選用的資料來源還是前面一篇文章所使用的 Excel ,小編這裡簡單的隨機刪除掉幾個資料):

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")
print(df)

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

print(df.info())

# 輸出結果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 408 entries, 0 to 407
Data columns (total 6 columns):
plantform      408 non-null object
read_num       406 non-null float64
fans_num       408 non-null int64
rank_num       407 non-null float64
like_num       408 non-null int64
create_date    408 non-null datetime64[ns]
dtypes: datetime64[ns](1), float64(2), int64(2), object(1)
memory usage: 19.2+ KB

從結果中可以看到,不為空的行數共計 408 行,而 read_num 這一行為 406 ,說明小編在這一列刪掉了 2 個數據,在 rank_num 這一列刪掉了 1 個數據。

我們還可以使用另一個更加直觀的方式來獲取缺失的資料 isnull() ,如果是缺失的值,會返回 True ,如果不是則會返回 False :

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")
print(df.isnull())

# 輸出結果
     plantform  read_num  fans_num  rank_num  like_num  create_date
0        False     False     False     False     False        False
1        False      True     False     False     False        False
2        False     False     False     False     False        False
3        False     False     False      True     False        False
4        False     False     False     False     False        False
..         ...       ...       ...       ...       ...          ...
403      False     False     False     False     False        False
404      False     False     False     False     False        False
405      False     False     False     False     False        False
406      False     False     False     False     False        False
407      False     False     False     False     False        False

[408 rows x 6 columns]

使用 isnull() 是比較直觀,那麼這裡存在一個問題,就是好像資料顯示不全啊,這種問題小 case ,只需一行程式碼輕鬆解決:

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

pd.set_option('display.max_rows', None)
print(df.isnull())

只需要對 pd 的顯示設定下最大行數就好,結果稍微有點長,小編就不貼了。

缺失資料刪除

我們找到了缺失的資料,接下來就是對這部分資料進行刪除操作了, Pandas 同樣為我們提供了一個現成的方法 dropna()

dropna() 這個方法會預設刪除缺失資料的行,就是這一行只要有缺失資料,整行都會刪除:

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df.dropna())

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
5        csdn    2202.0       129       0.0        37 2019-11-22 23:00:01
7        csdn    1621.0        76       0.0        27 2019-11-21 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[405 rows x 6 columns]

可以看到,這裡顯示的行數只剩 405 行了,其中有 3 行有缺失的資料已經刪除了。

在刪除缺失行的時候還會有一種情況,就是整行資料全都缺失,我們還可以只刪除整行資料全缺失,如果只是有缺失值的資料保留,這時我們可以用到 dropna() 的一個引數 how="any"

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df.dropna(how="any"))

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

因為小編的資料沒有整行缺失的,可以看到這裡又列印了所有的資料。

當然, dropna() 同時支援各種條件刪除,這裡篇幅原因小編就不一一列舉了,有需要的同學可以訪問官方文件檢視:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html 。

缺失資料填充

前面我們介紹了缺失資料的刪除,但是資料是很寶貴的,通常情況下肯定不能做簡單的刪除操作,更多的時候我們是希望能填充我們想要的預設值,這裡我們可以用到 fillna() 這個方法。

例如我們在剛才的資料中補充 0 :

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df.fillna(0))

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin       0.0         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       0.0         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

上面的示例是將所有的缺失資料全都填充成了 0 ,但是如果我們只想填充其中的一列資料呢?

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df.fillna({'read_num': 10}))

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      juejin      10.0         0      -2.0         1 2019-11-23 23:00:03
2        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
3      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
4      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
404      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
405    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
406    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
407      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

為了便於區分,小編這裡只補充了 read_num 這一列,將預設填充數值補充成了 10 。

重複資料處理

重複資料是指相同的記錄有多條,這裡一般簡單的做刪除操作。

Pandas 為我們提供了 drop_duplicates() 方法用作重複值處理,預設會對所有值進行判斷,並且會預設保留第一個值。

為了演示,小編將 Excel 中的資料第一行復制了一條。

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df)

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
1      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
3        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
..        ...       ...       ...       ...       ...                 ...
404    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
405      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
407    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[409 rows x 6 columns]

print(df.drop_duplicates())

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
3        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
5      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
404    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
405      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
407    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[408 rows x 6 columns]

可以看到第一個示例中共有 409 行資料,到了第二個結果,就只剩 408 行資料了。

這個示例是針對整體值進行判斷的,我們同樣可以只針對某一列進行去重,只需要在 drop_duplicates() 這個方法中指明要判斷的列即可:

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df.drop_duplicates(subset='read_num'))

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
0      cnblog     215.0         0     118.0         0 2019-11-23 23:00:10
2      juejin       NaN         0      -2.0         1 2019-11-23 23:00:03
3        csdn    1652.0        69       0.0        24 2019-11-23 23:00:02
4      cnblog     650.0         3       NaN         0 2019-11-22 23:00:15
5      juejin     272.0         3     -23.0         1 2019-11-22 23:00:02
..        ...       ...       ...       ...       ...                 ...
403    cnblog     140.0         0      37.0         0 2020-02-20 23:00:08
404    juejin     212.0         0      -1.0         2 2020-02-20 23:00:02
405      csdn    1602.0         1       0.0         1 2020-02-20 23:00:01
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

[342 rows x 6 columns]

可以看到這裡只剩下了 342 行記錄,當然對不對小編沒有區驗證,這個可以通過 sql 直接在資料庫中做查詢驗證或者在 Excel 中使用去重進行驗證(小編相信官方的 API 不會騙人)。

除了這些,還可以自定義刪除重複項時保留哪個,預設是保留第一個,也可以設定保留最後一個,還可以設定一個都不保留:

import pandas as pd

# 相對路徑
df = pd.read_excel("result_data.xlsx")

print(df.drop_duplicates(subset='plantform', keep='last'))

# 輸出結果
    plantform  read_num  fans_num  rank_num  like_num         create_date
406    cnblog      19.0         0      41.0         0 2020-02-21 23:00:05
407    juejin     125.0         1      -4.0         0 2020-02-21 23:00:02
408      csdn    1475.0         8       0.0         3 2020-02-21 23:00:02

小編這裡選擇通過 plantform 欄位進行去重篩選,從行號上看應該對的,保留了最後三條資料。

keep 的值預設是 first ,也就是隻保留第一個,除了 first , last 還有一個是 False ,它的含義是一個都不保留。

本篇的內容就到這裡結束了,希望各位同學能多動動手,多敲敲程式碼,雖然這是學程式碼最笨的辦法,但同時也是最有效的方法。

示例程式碼

老規矩,所有的示例程式碼都會上傳至程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例程式碼-Github

示例程式碼-Gi