數據處理:2.異常值處理 & 數據歸一化 & 數據連續屬性離散化


 1.異常值分析

異常值是指樣本中的個別值,其數值明顯偏離其余的觀測值。
異常值也稱離群點,異常值的分析也稱為離群點的分析。

異常值分析 → 3σ原則 / 箱型圖分析
異常值處理方法 → 刪除 / 修正填補

   1.1 3σ原則 / 箱型圖分析

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
% matplotlib inline
# 異常值分析
# (1)3σ原則:如果數據服從正態分布,異常值被定義為一組測定值中與平均值的偏差超過3倍的值 → p(|x - μ| > 3σ) ≤ 0.003

data = pd.Series(np.random.randn(10000)*100)
print(data.head())
# 創建數據

u = data.mean()  # 計算均值
std = data.std()  # 計算標准差
stats.kstest(data, 'norm', (u, std)) #正態分布的方式,得到 KstestResult(statistic=0.012627414595288711, pvalue=0.082417721086262413),P值>0.5
print('均值為:%.3f,標准差為:%.3f' % (u,std))
print('------')
# 正態性檢驗

fig = plt.figure(figsize = (10,6))
ax1 = fig.add_subplot(2,1,1)
data.plot(kind = 'kde',grid = True,style = '-k',title = '密度曲線')
plt.axvline(3*std,hold=None,color='r',linestyle="--",alpha=0.8) #3倍的標准差
plt.axvline(-3*std,hold=None,color='r',linestyle="--",alpha=0.8) 
# 繪制數據密度曲線 

error = data[np.abs(data - u) > 3*std]  #超過3倍差的數據(即異常值)篩選出來
data_c = data[np.abs(data - u) < 3*std] 
print('異常值共%i條' % len(error))
ax2 = fig.add_subplot(2, 1, 2)

plt.scatter(data_c.index, data_c, color = 'k', marker = '.', alpha = 0.3)
plt.scatter(error.index, error, color = 'r', marker = '.', alpha = 0.7)
plt.xlim([-10,10010])
plt.grid()
# 圖表表達

 1.2箱型圖分析 

# 異常值分析
# (2)箱型圖分析

fig = plt.figure(figsize = (10,6))
ax1 = fig.add_subplot(2,1,1)
color = dict(boxes='DarkGreen', whiskers='DarkOrange', medians='DarkBlue', caps='Gray')
data.plot.box(vert=False, grid = True,color = color,ax = ax1,label = '樣本數據')
# 箱型圖看數據分布情況
# 以內限為界

 

s = data.describe()
print(s)
print('------')
# 基本統計量

q1 = s['25%']
q3 = s['75%']
iqr = q3 - q1
mi = q1 - 1.5*iqr
ma = q3 + 1.5*iqr
print('分位差為:%.3f,下限為:%.3f,上限為:%.3f' % (iqr,mi,ma))
print('------')
# 計算分位差

ax2 = fig.add_subplot(2,1,2)
error = data[(data < mi) | (data > ma)]
data_c = data[(data >= mi) & (data <= ma)]
print('異常值共%i條' % len(error))
# 篩選出異常值error、剔除異常值之后的數據data_c

plt.scatter(data_c.index,data_c,color = 'k',marker='.',alpha = 0.3)
plt.scatter(error.index,error,color = 'r',marker='.',alpha = 0.5)
plt.xlim([-10,10010])
plt.grid()
# 圖表表達

 

2. 數據歸一化

數據歸一化/ 標准化

數據的標准化(normalization)是將數據按比例縮放,使之落入一個小的特定區間。
在某些比較和評價的指標處理中經常會用到,去除數據的單位限制,將其轉化為無量綱的純數值,便於不同單位或量級的指標能夠進行比較和加權

最典型的就是數據的歸一化處理,即將數據統一映射到[0,1]區間上 

0-1標准化 / Z-score標准化

(1)0 - 1標准化

 將數據的最大最小值記錄下來,並通過Max-Min作為基數(即Min=0,Max=1)進行數據的歸一化處理
 x = (x - Min) / (Max - Min)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
% matplotlib inline
# 數據標准化
# (1)0-1標准化
df = pd.DataFrame({"value1":np.random.rand(10)*20,
                  'value2':np.random.rand(10)*100})
print(df.head())
print('------')
# 創建數據

def data_norm(df,*cols):
    df_n = df.copy()
    for col in cols:
        ma = df_n[col].max()
        mi = df_n[col].min()
        df_n[col + '_n'] = (df_n[col] - mi) / (ma - mi)
    return(df_n)
# 創建函數,標准化數據
df_n = data_norm(df, 'value1',  'value2')
print(df_n.head())#標准化數據 

 (2)Z - score標准化

 Z分數(z-score),是一個分數與平均數的差再除以標准差的過程 → z=(x-μ)/σ,其中x為某一具體分數,μ為平均數,σ為標准差
 Z值的量代表着原始分數和母體平均值之間的距離,是以標准差為單位計算。在原始分數低於平均值時Z則為負數,反之則為正數
 數學意義:一個給定分數距離平均數多少個標准差?
# 數據標准化
# (2)Z-score標准化
df = pd.DataFrame({"value1":np.random.rand(10) * 100,
                  'value2':np.random.rand(10) * 100})
print(df.head())
print('------')
# 創建數據

def data_Znorm(df, *cols):
    df_n = df.copy()
    for col in cols:
        u = df_n[col].mean()
        std = df_n[col].std()
        df_n[col + '_Zn'] = (df_n[col] - u) / std #平均值/標准差
    return(df_n)
# 創建函數,標准化數據

df_z = data_Znorm(df,'value1','value2')
u_z = df_z['value1_Zn'].mean()
std_z = df_z['value1_Zn'].std()
print(df_z)
print('標准化后value1的均值為:%.2f, 標准差為:%.2f' % (u_z, std_z))
# 標准化數據
# 經過處理的數據符合標准正態分布,即均值為0,標准差為1

# 什么情況用Z-score標准化:
# 在分類、聚類算法中,需要使用距離來度量相似性的時候,Z-score表現更好 

 案例應用

# 案例應用
# 八類產品的兩個指標value1,value2,其中value1權重為0.6,value2權重為0.4
# 通過0-1標准化,判斷哪個產品綜合指標狀況最好

df = pd.DataFrame({"value1":np.random.rand(10) * 30,
                  'value2':np.random.rand(10) * 100},
                 index = list('ABCDEFGHIJ'))
#print(df.head())
#print('------')
# 創建數據"

df_n1 = data_norm(df,'value1','value2')
# 進行標准化處理

df_n1['f'] = df_n1['value1_n'] * 0.6 + df_n1['value2_n'] * 0.4
df_n1.sort_values(by = 'f',inplace=True,ascending=False)
df_n1['f'].plot(kind = 'line', style = '--.k', alpha = 0.8, grid = True)
df_n1
# 查看綜合指標狀況

 

3.數據連續屬性離散化

連續屬性變換成分類屬性,即連續屬性離散化。
在數值的取值范圍內設定若干個離散划分點,將取值范圍划分為一些離散化的區間,最后用不同的符號或整數值代表每個子區間中的數據值

等寬法 / 等頻法

(1)等寬法

 將數據均勻划分成n等份,每份的間距相等
 cut方法
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
% matplotlib inline
# 等寬法 → cut方法
ages=[20,22,25,27,21,23,37,31,61,45,41,32]
# 有一組人員年齡數據,希望將這些數據划分為“18到25”,“26到35”,“36到60”,“60以上”幾個面元,分成4個區間。

bins = [18,25,35,60,100]
cats = pd.cut(ages,bins)
print(cats)
print(type(cats))
print('---’) ## 返回的是一個特殊的Categorical類對象 → 一組表示面元名稱的字符串

 

print(cats.codes, type(cats.codes))  # 0-3對應分組后的四個區間,用代號來注釋數據對應區間,結果為ndarray;可以查看里邊的等級
print(cats.categories, type(cats.categories))  # 四個區間,結果為index
print(pd.value_counts(cats))  # 按照區間計數
print('-------')
# cut結果含有一個表示不同分類名稱的層級數組以及一個年齡數據進行標號的代號屬性 

 

print(pd.cut(ages,[18,26,36,61,100],right=False))
print('-------')
# 通過right函數修改閉端,默認為True

group_names=['Youth','YoungAdult','MiddleAged','Senior']
print(pd.cut(ages,bins,labels=group_names))
print('-------')
# 可以設置自己的區間名稱,用labels參數

 

df = pd.DataFrame({'ages':ages})
group_names=['Youth','YoungAdult','MiddleAged','Senior']
s = pd.cut(df['ages'],bins)  # 也可以 pd.cut(df['ages'],5),將數據等分為5份
df['label'] = s
cut_counts = s.value_counts(sort=False) 
print(df)
print(cut_counts)
# 對一個Dataframe數據進行離散化,並計算各個區間的數據計數

plt.scatter(df.index,df['ages'],cmap = 'Reds',c = cats.codes)
plt.grid()
# 用散點圖表示,其中顏色按照codes分類 
# 注意codes是來自於Categorical對象

 

 (2)等頻法 

以相同數量的記錄放進每個區間
qcut方法
# 等頻法 → qcut方法

data = np.random.randn(1000)
s = pd.Series(data)
cats = pd.qcut(s,4)  # 按四分位數進行切割,可以試試 pd.qcut(data,10)
print(cats.head())
print(pd.value_counts(cats))
print('------')
# qcut → 根據樣本分位數對數據進行面元划分,得到大小基本相等的面元,但並不能保證每個面元含有相同數據個數
# 也可以設置自定義的分位數(0到1之間的數值,包含端點) → pd.qcut(data1,[0,0.1,0.5,0.9,1])

plt.scatter(s.index,s,cmap = 'Greens',c = pd.qcut(data,4).codes)
plt.xlim([0,1000])
plt.grid()
# 用散點圖表示,其中顏色按照codes分類
# 注意codes是來自於Categorical對象

 


免責聲明!

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



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