Python數據預處理 - 連續數據離散化(等寬、等頻、聚類離散)

目錄

等寬離散

等頻離散

聚類離散

附錄:

rolling_mean函數解釋

cut函數解釋

其他數據預處理方法


一些數據挖掘算法中,特別是某些分類算法(eg:ID3算法、Aprioroi算法等),要求數據是分類屬性形式。因此常常需要將連續屬性變換成分類屬性,即離散化。

離散化就是在數據的取值範圍內設定若干個離散的花粉店,將取值範圍劃分爲一些離散化的區間,最後用不同的符號護着整數值代表落在每個區間中的數據值。所以離散化涉及兩個過程:確定分類數&將連續屬性值映射到n個分類值。

常用的離散化方法:等寬離散、等頻離散和聚類離散(一維)。

 

等寬離散

將屬性的值域從最小值到最大值分成具有相同寬度的n個區間,n由數據特點決定,往往是需要有業務經驗的人進行評估。

代碼實現:

#-*- coding:utf-8 -*-
#數據離散化-等寬離散
import pandas as pd

datafile = u'E:\\pythondata\\hk04.xlsx'
data = pd.read_excel(datafile)
data = data[u'回款金額'].copy()
k = 5 #設置離散之後的數據段爲5

#等寬離散
d1 = pd.cut(data,k,labels = range(k))#將回款金額等寬分成k類,命名爲0,1,2,3,4,5,data經過cut之後生成了第一列爲索引,第二列爲當前行的回款金額被劃分爲0-5的哪一類,屬於3這一類的第二列就顯示爲3


def cluster_plot(d,k):
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    plt.figure(figsize = (12,4))
    for j in range(0,k):
        plt.plot(data[d==j], [j for i in d[d==j]],'o')
        
    plt.ylim(-0.5, k-0.5)
    return plt

cluster_plot(d1, k).show()

離散結果:

由這個離散結果我們可以直觀的看出等寬離散的缺點,其缺點在於對噪點過於敏感,傾向於不均勻的把屬性值分佈到各個區間,導致有些區間的數值極多,而有些區間極少,嚴重損壞離散化之後建立的數據模型。

 

等頻離散

將相同數量的記錄放在每個區間,保證每個區間的數量基本一致。

代碼實現:

#-*- coding:utf-8 -*-
#數據離散化-等頻離散
import pandas as pd

datafile = u'E:\\pythondata\\hk04.xlsx'
data = pd.read_excel(datafile)
data = data[u'回款金額'].copy()
k = 5 #設置離散之後的數據段爲5

#等頻率離散化
w = [1.0*i/k for i in range(k+1)]
w = data.describe(percentiles = w)[4:4+k+1]
w[0] = w[0]*(1-1e-10)
d2 = pd.cut(data, w, labels = range(k))



def cluster_plot(d,k):
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    plt.figure(figsize = (12,4))
    for j in range(0,k):
        plt.plot(data[d==j], [j for i in d[d==j]],'o')
        
    plt.ylim(-0.5, k-0.5)
    return plt

cluster_plot(d2, k).show()

離散結果:

由離散結果看出,等頻離散不會像等寬離散一樣,出現某些區間極多或者極少的情況。但是根據等頻離散的原理,爲了保證每個區間的數據一致,很有可能將原本是相同的兩個數值卻被分進了不同的區間,這對最終模型的損壞程度一點都不亞於等寬離散。

 

聚類離散

一維聚類離散包括兩個過程:通過聚類算法(K-Means算法)將連續屬性值進行聚類,處理聚類之後的到的k個簇,得到每個簇對應的分類值(類似這個簇的標記)。

代碼實現:

#-*- coding:utf-8 -*-
#數據離散化-聚類離散
import pandas as pd

datafile = u'E:\\pythondata\\hk04.xlsx'
data = pd.read_excel(datafile)
data = data[u'回款金額'].copy()
k = 5 #設置離散之後的數據段爲5


#聚類離散
from sklearn.cluster import KMeans

kmodel = KMeans(n_clusters = k, n_jobs = 4)#n_jobs是並行數,一般等於CPU數
kmodel.fit(data.reshape((len(data), 1)))
c = pd.DataFrame(kmodel.cluster_centers_, columns=list('a')).sort_values(by='a')
#rolling_mean表示移動平均,即用當前值和前2個數值取平均數,
#由於通過移動平均,會使得第一個數變爲空值,因此需要使用.iloc[1:]過濾掉空值。
w = pd.rolling_mean(c, 2).iloc[1:]#此處w=[2174.1003996693553, 8547.46386803177, 22710.538501243103, 48516.861774600904]
w = [0] + list(w[0]) + [data.max()]#把首末邊界點加上,首邊界爲0,末邊界爲data的最大值120000,此處w=[0, 2174.1003996693553, 8547.46386803177, 22710.538501243103, 48516.861774600904, 120000.0]
d3 = pd.cut(data, w, labels = range(k))#cut函數實現將data中的數據按照w的邊界分類。


def cluster_plot(d,k):
    import matplotlib.pyplot as plt
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    
    plt.figure(figsize = (12,4))
    for j in range(0,k):
        plt.plot(data[d==j], [j for i in d[d==j]],'o')
        
    plt.ylim(-0.5, k-0.5)
    return plt

cluster_plot(d3, k).show()

離散結果:

三種離散化方法中,最得本宮心意的便是最後這個聚類離散,但是即便是這般如花似玉,也有她的弊端:無法自己學習得知離散後簇的個數,依然需要內閣大學士來決定。

 

附錄:

rolling_mean函數解釋

pandas.rolling_mean(arg, window, min_periods=None, freq=None, center=False, how=None, **kwargs)

rolling_mean函數表示通過移動窗口求平均值,即用當前值和前[window]個數值取平均數,得到新的數值。

import pandas as pd

data = [3, 60, 83, 100, 52, 36]#源數據
data = pd.DataFrame(data).sort_values(0)  
w2 = pd.rolling_mean(data, 2)#設置移動窗口爲2,即用當前值和前2個數值取平均數
w3 = pd.rolling_mean(data, 3)#用當前值和前3個數值取平均數
print("源數據:\n", data)
print("移動窗口數爲2:\n", w2)
print("移動窗口數爲3:\n", w3)

運行結果:

源數據:
      0
0    3
5   36
4   52
1   60
2   83
3  100
移動窗口數爲2:
       0
0   NaN
5  19.5
4  44.0
1  56.0
2  71.5
3  91.5
移動窗口數爲3:
            0
0        NaN
5        NaN
4  30.333333
1  49.333333
2  65.000000
3  81.000000

rolling的一系列函數中,除了rolling_mean(移動窗口的均值),還有rolling_median(移動窗口的中位數)、rolling_var (移動窗口的方差)、rolling_std (移動窗口的標準差)、rolling_cov (移動窗口的協方差)、rolling_sum (移動窗口的和)、rolling_min (移動窗口的最小值)、rolling_max (移動窗口的最大值)、rolling_corr (移動窗口的相關係數)、rolling_count (計算各個窗口中非NA觀測值的數量)。最常用的還是rolling_mean了,作用類似時間序列中提到的移動平滑。

 

cut函數解釋

cut()函數可以將一個數組中的數據切分成幾個部分。兩種用法:可以設置分類的邊界,也可以僅規定分類後的個數。 cut([被分割的數據],[將數據分爲幾個部分])

import pandas as pd

data = [3, 60, 83, 100, 52, 36]#源數據
w = [0, 25, 50, 75, 100]#規定了分類的邊界
v = 4 #僅規定分類的個數,不規定邊界值
data_cut1 = pd.cut(data, w)
data_cut2 = pd.cut(data, v)
print("規定了分類的邊界:\n", data_cut1)
print("\n規定了分類的個數:\n", data_cut2)

運行結果:

規定了分類的邊界:
 [(0, 25], (50, 75], (75, 100], (75, 100], (50, 75], (25, 50]]
Categories (4, interval[int64]): [(0, 25] < (25, 50] < (50, 75] < (75, 100]]

規定了分類的個數:
 [(2.903, 27.25], (51.5, 75.75], (75.75, 100.0], (75.75, 100.0], (51.5, 75.75], (27.25, 51.5]]
Categories (4, interval[float64]): [(2.903, 27.25] < (27.25, 51.5] < (51.5, 75.75] < (75.75, 100.0]]

 

其他數據預處理方法

拉格朗日插值法補充缺失值

清洗重複數據

數據預處理 - 歸一化與標準化

 

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