數據預處理(重複值/異常值/數據離散化)——Python數據清洗實戰筆記(7)

導庫,讀取數據

import numpy as np
import pandas as pd
df = pd.read_csv('../data/MotorcycleData.csv',encoding='gbk',na_values='Na')

1.重複值處理·對價格和里程數數據進行處理

自定義函數,把價格中的美元符號、逗號、里程數逗號去掉;

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()))
數據是否存在重複觀測:
 True

查看重複數據

df[df.duplicated()]

計算重複數量

np.sum(df.duplicated())

刪除所有變量都重複的行,注意:這裏沒有inplace=True

df.drop_duplicates()

按照兩個變量重複來去重

df.drop_duplicates(subset=['Condition','Condition_Desc','Price','Location'],inplace=True)

2.缺失值處理

查看缺失比率

df.apply(lambda x : sum(x.isnull()) / len(x),axis=0)

刪除法——直接刪除(慎重)

df.dropna()

只要有缺失,就刪除這一列

df.dropna(how='any',axis=1)

只有有缺失,就刪除這一行

df.dropna(how='any',axis=1)

基於某些變量,有缺失值,就刪除行或者列;axis=0 或者1 代表的函數在數據集作用的方向,0代表沿着行的方向,1代表沿着列的方向;

df.dropna(axis=0,how='any',subset=['Condition','Price','Mileage'])

替換法——

在數據分析中,大部分按照行來刪除,很少基於列刪除;列代表變量,是否刪除列,很多時候取決於缺失比例

年量用均值填補

df.Mileage.fillna(df.Mileage.mean())

中位數填補

df.Mileage.fillna(df.Mileage.median())

衆數填補

df.Exterior_Color.fillna(df.Exterior_Color.mode()[0])

所有缺失值用20填補

df.fillna(20)

分類填補:車顏色-衆數,里程-均值

df.fillna(value={'Exterior_Color':df.Exterior_Color.mode()[0],'Mileage':df.Mileage.mean()})

前向填補

df['Exterior_Color'].fillna(method='ffill')

後向填補

df['Exterior_Color'].fillna(method='bfill')

3.異常值處理

  • 異常值檢測可以使用均值得倍標準差範圍,也可以使用上下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))

標準差法異常值上線檢測:
 True
標準差法異常值下線檢測:
 False

異常值檢測之箱線圖法

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))

標準差法異常值上線檢測:
 True
標準差法異常值下線檢測:
 False

繪圖

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

在這裏插入圖片描述

箱圖

#導入繪圖模塊
import matplotlib as plt
%matplotlib inline
df.Price.plot(kind='box')

在這裏插入圖片描述

#用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
#導入繪圖模塊
import matplotlib as plt
%matplotlib inline
#設置繪圖風格
plt.style.use('seaborn')
#繪製直方圖
df.Price_new.plot(kind='hist',bins=30,density=True)
#繪製核密度圖
df.Price_new.plot(kind='kde')
#圖形展現
plt.legend

在這裏插入圖片描述

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,布爾值。第一個區間的左端點是否包含
df['Price_bin'] = pd.cut(df['Price_new'],5,labels=range(5))
df['Price_bin'].hist()

在這裏插入圖片描述
自定義分段標準和標籤·cut

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

df['Price_bin1'].value_counts()
划算    1651
中等    1494
便宜    1421555235
Name: Price_bin1, dtype: int64
  • 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

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

在這裏插入圖片描述

先計算分位數的值

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

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

在這裏插入圖片描述

其它內容學習

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