用pandas進行簡單的數據預處理

最在參加了一個機器學習的競賽,又開始頻繁的使用pandas做數據的處理。發現了一些之前沒有發現的pandas用法。在這裏做一個總結, 也算是學習筆記吧。本筆記大部分都會以下面的數據作爲例子。另外,推薦大家使用ipython來查看及處理數據。

首先看這樣的數據。

image.png

這是kaggle上的關於員工離職的數據,現在要根據滿意度,工作項目, 薪水等指標判斷一個員工是否會離職。 在進行機器學習之前,我們首先要進行數據的清理及預處理。數據下載

1. 查看統計數據

csv文件讀取

拿到數據以後,一般都要先看看數據長啥樣,有多大,都有什麼特徵,用pandas查看這些是非常方便的。針對本例子中的csv文件, 我們使用read_csv函數來讀取, 讀進來之後是pandas中的DataFrame格式。

import numpy as np
import pandas as pd
# 使用read_csv讀取數據
hr = pd.read_csv("HR.csv")

但有一點要注意,讀取的時候要先看一下csv文件中格式。主要看兩點,一是第一列(也有可能是前幾列)是不是索引,二是看第一行是數據還是feature的名稱。 read_csv方法默認會將第一行當成feature來解析。

# 如果第一列是索引
pd.read_csv('data.csv', index_col=0)
# 如果是純數據沒有feature的話
pd.read_csv('data.csv', header=None)

實際上如果你用的是ipython,可以直接輸入 pd.read_csv? 來查看這個函數的文檔,非常方便。

查看數據
# 查看數據的行數與列書, 一般來說行代表樣本數, 列代表feature數
hr.shape
# 查看數據的前5行
hr.head()
# 查看每一列的計數及數據類型等信息
hr.info()
# 查看統計信息
hr.describe()

一般來說我們都會看一下這些信息。 從而對數據有一定的概念。

2. 簡單的可視化

   pandas提供了一個簡單的函數讓我們可以非常簡單的查看各個column的分佈直方圖,當然僅限於該column的值的數字的時候,如果是離散值就沒有用這個辦法可視化了。值得注意的是該函數依賴於matplotlib, 須先導入該包。
import matplotlib.pyplot as plt
hr.hist(grid=False, figsize=(12,12))

有兩個參數值得一提

grid : True 或者 False; 就是設不設置網格, 這個就看個人的需求了
figsize: tuple;圖的大小, 當你繪製的直方圖有多個時, 就設置大一點,這個多嘗試幾次就好了

至於其他的參數,一般來說用的不多, 但如果有需求可以看一下文檔,強烈建議用ipython,這用就可以直接用 hr.hist? 來查看該函數的文檔了。

3. 去除重複項

pandas提供了duplicated 函數供我們查看是否有完全一樣的兩行,也就是重複的兩行,返回的是一個Boolean值的Series,重複項那裏就是True,無重複項的False

# 可以通過df.duplicated()查看是否有重複項
hr.duplicated(keep="last")

keep: "first", "last", False. 默認是"first". 非常重要的參數,first的意思就是重複項裏面第一個爲False, 剩下的事True, last的意思則正好相反,最後一項是False, 其他重複項爲True。指定爲False則表示把所有重複項都設置爲True
subset: list, 要檢查重複的項,默認是全部,也就是兩行完全一樣才判斷爲True。 如果只是像查看部分column是否一樣的話就可以用subset這個參數了。

除了查看重複的項,我們還可以去除重複項。drop_duplicates提供了這一功能。

hr = hr.drop_duplicates()

keep: "first", "last", False. 默認是“first”。 也就是默認保留最前面的重複項,將其他重複項去除。“last”則表示保留最後面的重複項,將其他重複項去除。False則表示將所有重複項全部去除。
subset: list, 默認是全部列。如果只是要將其中幾列相同就去除的話可以用這個參數。
inplace: True or False。 默認是False,也就是不修改原來的DataFrame。設置爲True則會改變原來的DataFrame。

4. 處理缺失值

缺失值的處理一直是數據處理的一個重點工作。根據數據的不同會做出不同的選擇,有用均值填充的,中位數填充的,用0填充的,甚至直接去除的。再複雜一點的可以用autoencoder來訓練預測缺失值,關於缺失值的處理可以寫一本厚厚的書了。這裏就簡單的說明一下常見的處理方法。注意我這個數據沒有缺失值,大家可以找找其他數據試一下。

# 用均值填充
hr.fillna(hr.mean())
# 用中位數填充
hr.fillna(hr.median())
# 用0填充
hr.fillna(0)

5. 離散的feature處理

包含離散的feature的數據無法直接作爲輸入進行機器學習。例如性別,男跟女,例如工資,low,medium,high。 需要做一個向量化處理。有人說不能直接用0,1,2來表示嗎,例如0表示low,1表示medium, 2表示high。emmmm,當然不行。怎麼向量化呢?以該數據中的工作崗位與工資爲例, 001 表示low ,010表示medium,100表示表示high。

categorical_features = ['sales', 'salary']
hr_cat = pd.get_dummies(hr[categorical_features])
hr = hr.drop(categorical_features, axis=1)
hr = pd.concat([hr, hr_cat], axis=1)

很簡單的代碼,值得一提的事get_dummies這個函數。該函數的作用是將離散的變量轉化爲向量化,一兩句說不清,這裏只告訴你可以這麼處理離散變量,想要細細瞭解看一下文檔就明白了,我把文檔貼過來也沒有意思。

6. 數據歸一化

向量歸一化也是非常重要的。最常見的歸一化方法有兩種,一種是min-max歸一化,就是每一個值除以最大值減去最小值的差,這樣可以把數據歸一化到[0,1]之間。另一種是z-score標準化,也就是經過處理後的數據符合標準正態分佈,即均值爲0,標準差爲1。這兩種都非常常見,具體使用哪種得看數據。可以用sklearn來進行處理,這樣就不用自己來實現了。

from sklearn.preprocessing import StandardScaler
# 使用z-score標準化數據
ss = StandardScaler()
scale_features = ['number_project', 'average_monthly_hours', 'time_spend_company']
hr[scale_features] = ss.fit_transform(hr[scale_features])

如果是想用min-max歸一化的話,sklearn也有現有的類實現。

from sklearn.preprocessing import MinMaxScaler
ss = MinMaxScaler()
scale_features = ['number_project', 'average_monthly_hours', 'time_spend_company']
hr[scale_features] = ss.fit_transform(hr[scale_features])

7. 去除缺失比例超過50%的行/列

這是我在處理其他數據的時候遇到的問題, 就是有時候並不只是單純的根據一部分column來去除數據,而是要根據缺失比例來進行取捨。有可能是缺失比例超過30%,或者70%。我查了一下pandas好像沒有現有的函數直接實現的。但不打緊,我寫了兩個函數來實現。

  • 去除缺失值比例超過一定程度的列
def drop_col(df, cutoff=0.4):
    n = len(df)
    for column in df.columns:
        cnt = df[column].count()
        if (float(cnt) / n) < cutoff:
            df = df.drop(column, axis=1)
    return df
hr = drop_col(hr)

當然本文中數據是沒有缺失值的,因此沒有什麼效果。注意cutoff指的是有數據的比例。

  • 去除缺失值超過一定比例的行
def drop_row(df, cutoff=0.8):
    n = df.shape[1]
    for row in df.index:
        cnt = df.loc[row].count()
        if cnt / n < cutoff:
            df = df.drop(row, axis=0)
    return df
hr  = drop_row(hr)

同樣的,這裏的cutoff也是隻有數據的比例

8. 根據條件給列數據重新賦值

這個應該也是非常常見的功能。舉個簡單的例子,現在要把Work_accident中大於2的值改爲True,小於等於2的值改爲False。例子要求可能不太合理,但意思應該表達出來了。這種要求怎麼實現呢。非常簡單,一句就可以搞定了。

hr['Work_accident'] = hr['Work_accident'].apply(lambda x: False if x<2 else True)

如果要求比較複雜,就不要用匿名函數了,自己寫一個函數,然後像上面那樣子就成了。非常簡單的。

大致應該講完了常見的數據預處理,如果再工作中遇到新的需求,我會不定期的更新本文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章