數據清洗之數據預處理 重復值 缺失值 異常值 數據離散化


數據清洗之數據預處理

 

摩托車的銷售情況數據

  • 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:出價計數
In [ ]:
import numpy as np import pandas as pd import os 
In [ ]:
os.chdir(r'F:\CSDN\課程內容\代碼和數據') 
In [ ]:
df = pd.read_csv('MotorcycleData.csv',encoding = 'gbk',na_values='Na') 
  na_values='Na'   對所有的空字符串做缺失值填充
na_values='used' 對所有的‘used’的數據寫成缺失值

1. 重復值處理

In [ ]:
df.head(5) 
 
  • 對價格和里程數數據進行處理
In [ ]:
# 自定義一個函數
def f(x): if '$' in str(x): x = str(x).strip('$') # 去除 x = str(x).replace(',','') # 替換 else: x = str(x).replace(',','') return float(x) 
In [ ]:
df['Price'] = df['Price'] .apply(f) 
In [ ]:
df['Mileage'] = df['Mileage'].apply(f) 
In [ ]:
print ('數據集是否存在重復觀測: \n', any(df.duplicated())) 
In [ ]:
df[df.duplicated()] #查看那些數據重復(全部) 
In [ ]:
np.sum(df.duplicated()) #計算重復數量 
In [ ]:
df.drop_duplicates() #刪除所有變量都重復的行, 注意沒有加inplace = True,只會是視圖上刪除,只有加了才對原始數據改動 
In [ ]:
df.drop_duplicates(subset= ['Condition','Condition_Desc','Price','Location'],inplace=True) #按照兩個變量重復 來 來去重 
In [ ]:
df.info() 
 

2. 缺失值處理

In [ ]:
df.apply(lambda x: sum(x.isnull())/len(x),axis= 0) #缺失比例,超過90%或95%就可以扔了 
In [ ]:
#刪除法
df.dropna() #直接刪除法 
In [ ]:
df.dropna(how='any',axis = 1 ) #只要有缺失,就刪除這一列
df.dropna(how='all',axis = 1 ) #只有全部缺失,才刪除這一列
In [ ]:
df.dropna(how='any',axis = 0) #只要有缺失,就刪除這一行,等價於df.dropna() 
 
  • axis = 0 或者 1代表的函數在數據集作用的方向,0代表沿着行的方向,1代表沿着列的方向
In [ ]:
df.dropna(axis = 0,how='any',subset=['Condition','Price','Mileage']) # 1代表列,0代表行,只要有缺失,就刪除這一行,基於三個變量 
 

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

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

 
  • 替換法
In [ ]:
df.head(10) 
In [ ]:
df.Mileage.fillna(df.Mileage.mean()) # 年齡這里列 用均值填補 
In [ ]:
df.Mileage.fillna(df.Mileage.median()) #中位數填補 
In [ ]:
df[df['Exterior_Color'].isnull()] 
In [ ]:
df.Exterior_Color.fillna(df.Exterior_Color.mode()[0]) #眾數填補mode()[0],眾數可能有好幾個,后面表示取第一個
In [ ]:
df.fillna(20) # 所有缺失用20填補 
In [ ]:
# 車的顏色使用眾數,里程樹使用均值
df.fillna(value = {'Exterior_Color':df.Exterior_Color.mode()[0],'Mileage':df.Mileage.mean()})

這里還是沒有加inplace=True,所以數據本身沒變,只是視圖變化了

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

3.異常值處理

df.Price和df['Price']的作用應該是一樣的
 
  • 異常值檢測可以使用均值的2倍標准差范圍,也可以使用上下4分位數差方法
In [ ]:
# 判斷年齡有什么異常值
# 剔除戶主姓名,戶主身份證號和年齡有缺失的樣本 df.dropna(axis = 0,how='any',subset=['戶主姓名','戶主身份證號','age'],inplace = True) #1代表列,0代表行,只要有缺失,就刪除這一行,基於三個變量 
In [ ]:
# 異常值檢測之標准差法
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)) 
In [ ]:
# 異常值檢測之箱線圖法
Q1 = df.Price.quantile(q = 0.25) 取25%為分位數 Q3 = df.Price.quantile(q = 0.75) IQR = Q3 - Q1 分位差 
In [ ]:
print('箱線圖法異常值上限檢測:\n',any(df.Price > Q3 + 1.5 * IQR)) print('箱線圖法異常值下限檢測:\n',any(df.Price < Q1 - 1.5 * IQR)) 
In [ ]:
df.Price.describe()# 對價格進行描述性統計 
In [ ]:
 
import matplotlib.pyplot as plt %matplotlib inline 
In [ ]:
df.Price.plot(kind ='box') 
In [ ]:
# 導入繪圖模塊
import matplotlib.pyplot as plt # 設置繪圖風格 plt.style.use('seaborn') # 繪制直方圖(30條柱子,密度以概率密度) df.Price.plot(kind = 'hist', bins = 30, density = True) # 繪制核密度圖 df.Price.plot(kind = 'kde') # 圖形展現 plt.show() 
In [ ]:
# 用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

回憶:
#注意loc是標簽 #注意iloc是位置


In [ ]:
df[['Price','Price_new']].describe() 
 

4.數據離散化

 

 

 

  • 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,布爾值。第一個區間的左端點是否包含
In [ ]:
df.head(5) 
In [ ]:
df['Price_bin'] = pd.cut(df['Price_new'],5,labels=range(5))
#切分五大類,把這五份分別取0~5的標簽 df['Price_bin'].hist()
 
  • 自定義分段標准和標簽
In [ ]:
df['Price_new'].describe() 
In [ ]:
w = [100,1000,5000,10000,20000,50000] 
In [ ]:
df['Price_bin'] = pd.cut(df['Price_new'], bins =w,labels=['低','便宜','划算','中等','高'],right=False) 
In [ ]:
df['Price_bin'].value_counts() 
 
 
cut的樣本是不平均的
q cu t的樣本划分下來基本是平均的
 
 
 
  • pandas.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)
  • 參數:
  • q,整數或分位數組成的數組。
  • q, 整數 或分位數數組 整數比如 4 代表 按照4分位數 進行切割 
  • labels, 用作結果箱的標簽。必須與結果箱相同長度。如果FALSE,只返回整數指標面元。
 
  • 原理都是基於分位數來進行離散化
In [ ]:
k = 5 w = [1.0*i/k for i in range(k+1)] w

這里w的作用就是分位
值為[0.0,0.2,0.4,0.6,0.8,1.0]
也就是“等頻”

In [ ]:等頻分段
df['Price_bin'] = pd.qcut(df['Price_new'],w,labels=range(k))
# 這里的w賦值的是q這個變量
In [ ]:
df['Price_bin'].hist() 
 
  • 或者先計算分位數的值
In [ ]:
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 # 將最大值增大一點, 目的是為了確保數據在這個范圍
In [ ]:
w1
In [ ]:
df['Price_bin'] = pd.cut(df['Price_new'],w1,labels=range(k)) df['Price_bin'].hist()



#在上面這個例子中,有兩種分的方法,其中w啊是先划分一個等頻段,w1是先計算了數據本身的等頻區間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM