python數據清洗實戰入門筆記(六)數據預處理


數據集地址:https://pan.baidu.com/s/1kMH1AhE8RUyaT73rvJsVPQ
提取碼:aai6
數據集介紹:

摩托車的銷售情況數據
Condition:摩托車新舊情況(new:新的 和used:使用過的)
Condition_Desc:對當前狀況的描述
Price:價格
Location:發獲地址
Model_Year:購買年份
Mileage:里程
Exterior_Color:車的顏色
Make:製造商(牌子)
Warranty:保修
Model:類型
Sub_Model:車輛類型
Type:種類
Vehicle_Title:車輛主題
OBO:車輛儀表盤
Watch_Count:表數
N_Reviews:評測次數
Seller_Status:賣家身份
Auction:拍賣(Ture或者False)
Buy_Now:現買
Bid_Count:出價計數

import numpy as np
import pandas as pd
import os
os.chdir(r'G:\pythonProject\pc\Python數據清洗\data')
df = pd.read_csv('MotorcycleData.csv',encoding = 'gbk',na_values='Na')

1 重複值處理

• 數據清洗一般先從重複值和缺失值開始處理
• 重複值一般採取刪除法來處理
• 但有些重複值不能刪除,例如訂單明細數據或交易明細數據等

image-20200518073420750

練習

df.head(5)

image-20200517225946903

對價格和里程數數據進行處理

# 自定義一個函數
def f(x):
    if '$' in str(x):
        x = str(x).strip('$')
        x = str(x).replace(',','')
    else:
        x = str(x).replace(',','')
    return float(x)
df['Price'] =  df['Price'] .apply(f)
df['Mileage'] = df['Mileage'].apply(f)
print ('數據集是否存在重複觀測: \n', any(df.duplicated()))

df[df.duplicated()] #查看那些數據重複

image-20200517230208134

np.sum(df.duplicated()) #計算重複數量

image-20200517230228203

df.drop_duplicates() #刪除所有變量都重複的行, 注意沒有加inplace = True

image-20200517230514103

df.drop_duplicates(subset= ['Condition','Condition_Desc','Price','Location'],inplace=True) #按照兩個變量重複來來去重
df.info()

image-20200517230443190

2 缺失值處理

• 缺失值首先需要根據實際情況定義
• 可以採取直接刪除法
• 有時候需要使用替換法或者插值法
• 常用的替換法有均值替換、前向、後向替換和常數替換

image-20200518073535106

image-20200518073722048

練習

df.apply(lambda x: sum(x.isnull())/len(x),axis= 0) #缺失比例

image-20200517230714224

#刪除法
df.dropna() #直接刪除法

image-20200517230901963

df.dropna(how='any',axis = 1 ) #只要有缺失,就刪除這一列

image-20200517231024769

df.dropna(how='any',axis = 0) #只要有缺失,就刪除這一行,等價於df.dropna()

image-20200517231107609

axis = 0 或者 1代表的函數在數據集作用的方向,0代表沿着行的方向,1代表沿着列的方向

df.dropna(axis = 0,how='any',subset=['Condition','Price','Mileage']) # 1代表列,0代表行,只要有缺失,就刪除這一行,基於三個變量

image-20200517231217785

在數據分析中,實際上大部分時候都是按照行來進行刪除的,很少會基於列來進行刪除 列代表的是變量,是否刪除刪除列很多時候主要取決於缺失比例

使用替換法進行缺失值的填補

替換法

df.head(5)

image-20200517231516910

df.Mileage.fillna(df.Mileage.mean()) # 年齡用均值填補

image-20200517231611671

df.Mileage.fillna(df.Mileage.median()) #中位數填補

image-20200517231650495

df[df['Exterior_Color'].isnull()]

image-20200517231721528

df.Exterior_Color.fillna(df.Exterior_Color.mode()[0]) #衆數填補

image-20200517231842499

df.fillna(20) # 所有缺失用20填補

image-20200517231909059

# 婚姻狀況使用衆數,年齡使用均值,農戶家庭人數使用中位數
df.fillna(value = {'Exterior_Color':df.Exterior_Color.mode()[0],'Mileage':df.Mileage.mean()})

image-20200517231945474

df['Exterior_Color'].fillna(method='ffill') #前向填補

image-20200517232015897

df['Exterior_Color'].fillna(method='bfill') #後向填補

image-20200517232046711

3 異常值處理

• 指那些偏離正常範圍的值,不是錯誤值
• 異常值出現頻率較低,但又會對實際項目分析造成偏差
• 異常值一般用過箱線圖法(分位差法)或者分佈圖(標準差法)來判斷
• 異常值往往採取蓋帽法或者數據離散化

image-20200518073752510

練習

異常值檢測可以使用均值的2倍標準差範圍,也可以使用上下4分位數差方法

# 異常值檢測之標準差法
xbar = df.Price.mean() 
xstd = df.Price.std()
print('標準差法異常值上限檢測:\n',any(df.Price> xbar + 2.5 * xstd))
print('標準差法異常值下限檢測:\n',any(df.Price< xbar - 2.5 * xstd))

image-20200518072415671

# 異常值檢測之箱線圖法
Q1 = df.Price.quantile(q = 0.25)
Q3 = df.Price.quantile(q = 0.75)
IQR = Q3 - Q1
print('箱線圖法異常值上限檢測:\n',any(df.Price > Q3 + 1.5 * IQR))
print('箱線圖法異常值下限檢測:\n',any(df.Price < Q1 - 1.5 * IQR))

image-20200518072448560

import matplotlib.pyplot as plt
%matplotlib inline
df.Price.plot(kind ='box')

image-20200518072612881

# 導入繪圖模塊
import matplotlib.pyplot as plt
# 設置繪圖風格
plt.style.use('seaborn')
# 繪製直方圖
df.Price.plot(kind = 'hist', bins = 30, density = True)
# 繪製核密度圖
df.Price.plot(kind = 'kde')
# 圖形展現
plt.show()

image-20200518072628979

# 用99分位數和1分位數替換
#計算P1和P99
P1 =df.Price.quantile(0.01); P99 = df.Price.quantile(0.99)
#先創建一個新變量,進行賦值,然後將滿足條件的數據進行替換
df['Price_new'] = df['Price']
df.loc[df['Price'] > P99,'Price_new']  = P99
df.loc[df['Price'] < P1,'Price_new']  = P1
df[['Price','Price_new']].describe()

image-20200518072645755

再次使用箱線圖可以發現離羣值已被剔除

df.Price.plot(kind ='box')

image-20200518072756244

4 數據離散化

• 數據離散化就是分箱
• 一般常用分箱方法是等頻分箱或者等寬分箱
• 一般使用pd.cut或者pd.qcut函數

image-20200518073813610

練習

pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)

參數:

x,類array對象,且必須爲一維,待切割的原形式

bins, 整數、序列尺度、或間隔索引。如果bins是一個整數,它定義了x寬度範圍內的等寬面元數量,但是在這種情況下,x的範圍在每個邊上被延長1%,以保證包括x的最小值或最大值。如果bin是序列,它定義了允許非均勻bin寬度的bin邊緣。在這種情況下沒有x的範圍的擴展。

right,布爾值。是否是左開右閉區間,right=True,左開右閉,right=False,左閉右開

labels,用作結果箱的標籤。必須與結果箱相同長度。如果FALSE,只返回整數指標面元。

retbins,布爾值。是否返回面元

precision,整數。返回面元的小數點幾位

include_lowest,布爾值。第一個區間的左端點是否包含

df.head(5)

image-20200518072851465

df['Price_bin'] =  pd.cut(df['Price_new'],5,labels=range(5))
df['Price_bin'].hist()

image-20200518072910841

這裏發現分佈不均勻,可以通過數據離散化讓數據更加均勻

自定義分段標準和標籤

df['Price_new'].describe()

image-20200518073016579

w = [100,1000,5000,10000,20000,50000]
df['Price_bin'] =  pd.cut(df['Price_new'], bins =w,labels=['低','便宜','划算','中等','高'],right=False)
df['Price_bin'].value_counts()

image-20200518073023739

pandas.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)

參數: x

q,整數或分位數組成的數組。

q, 整數 或分位數數組 整數比如 4 代表 按照4分位數 進行切割

labels, 用作結果箱的標籤。必須與結果箱相同長度。如果FALSE,只返回整數指標面元。

原理都是基於分位數來進行離散化

k = 5
w = [1.0*i/k for i in range(k+1)] 
w

image-20200518073102399

df['Price_bin'] = pd.qcut(df['Price_new'],w,labels=range(k))
df['Price_bin'].hist()

image-20200518073110104

或者先計算分位數的值

k = 5
w1 = df['Price_new'].quantile([1.0*i/k for i in range(k+1)])#先計算分位數,在進行分段
w1[0] = w1[0]* 0.95 # 最小值縮小一點
w[-1] = w1[1]* 1.05 # 將最大值增大一點, 目的是爲了確保數據在這個範圍內
w1

image-20200518073140199

df['Price_bin'] = pd.cut(df['Price_new'],w1,labels=range(k))
df['Price_bin'].hist()

image-20200518073154449

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