本文主要是個(gè)人的學(xué)習(xí)筆記總結(jié),數(shù)據(jù)預(yù)處理的基本思路和方法,包括一些方法的使用示例和參數(shù)解釋?zhuān)唧w的數(shù)據(jù)預(yù)處理案例case詳見(jiàn)其他文章。如有錯(cuò)誤之處還請(qǐng)指正!
- 數(shù)據(jù)的質(zhì)量評(píng)定
-
數(shù)據(jù)處理步驟
-
缺失值的處理
- 標(biāo)記缺失值
- 刪除缺失值
- 填充缺失值
- 重復(fù)值處理
- 異常值的處理
-
數(shù)據(jù)集合并
pandas.DataFrame.concat()
方法合并:pandas.DataFrame.merge()
方法合并:pandas.DataFrame.join()
方法:- 數(shù)據(jù)映射
map()
方法完成
- 分組聚合
-
數(shù)據(jù)轉(zhuǎn)換
- Z-Score 標(biāo)準(zhǔn)化
- Min-Max 標(biāo)準(zhǔn)化
- 獨(dú)熱編碼
- 數(shù)據(jù)離散化
-
數(shù)據(jù)規(guī)約
- 主成成分分析(Principal Components Analysis)
- 線性判別分析
- 皮爾遜相關(guān)系數(shù)
- 卡方檢驗(yàn)
- 數(shù)據(jù)抽樣
-
缺失值的處理
數(shù)據(jù)在進(jìn)行建模和分析前,對(duì)其進(jìn)行數(shù)據(jù)處理是必不可少的,這樣做能幫助我們從根本上保證數(shù)據(jù)質(zhì)量,提高數(shù)據(jù)的準(zhǔn)確性和可靠性。主要包括數(shù)據(jù)清洗、數(shù)據(jù)轉(zhuǎn)換、數(shù)據(jù)集成、數(shù)據(jù)降維等過(guò)程。
數(shù)據(jù)的質(zhì)量評(píng)定
從五個(gè)維度來(lái)對(duì)數(shù)據(jù)質(zhì)量進(jìn)行評(píng)定
維度 | 說(shuō)明 |
---|---|
有效性 Validity |
數(shù)據(jù)的有效性源于統(tǒng)計(jì)學(xué)概念,即符合數(shù)據(jù)收集時(shí)所制定的規(guī)則及約束條件的數(shù)據(jù)。 |
精確度 Accuracy |
精確度是衡量數(shù)據(jù)質(zhì)量的另一個(gè)重要條件。 一般情況下,通過(guò)數(shù)據(jù)清理很難改善數(shù)據(jù)的準(zhǔn)確度,這就對(duì)數(shù)據(jù)源質(zhì)量提出了較高的要求。 |
完整度 Completeness |
如果在采集數(shù)據(jù)的過(guò)程中造成了數(shù)據(jù)丟失,也就影響了其完整程度。 不完整的數(shù)據(jù),勢(shì)必會(huì)對(duì)分析結(jié)論造成影響,這需要進(jìn)一步采取措施來(lái)改善這種情況。 |
一致性 Consistency |
原始數(shù)據(jù)中,數(shù)據(jù)可能會(huì)存在不一致性。 例如:客戶(hù)在兩個(gè)不同的系統(tǒng)中提供了兩個(gè)不一樣的家庭地址,而正確的地址只有一個(gè)。 那么,就需要我們來(lái)判斷并消除這種不一致性。 |
均勻度 Uniformity |
數(shù)據(jù)的均勻度可能來(lái)源于度量單位的不一致,這就需要我們通過(guò)換算來(lái)解決,使得最終數(shù)據(jù)統(tǒng)一均勻。 |
數(shù)據(jù)處理步驟
數(shù)據(jù)處理的常見(jiàn)四個(gè)步驟:
序號(hào) | 步驟 | 說(shuō)明 |
---|---|---|
1 | 數(shù)據(jù)清理 Data Cleansing |
數(shù)據(jù)清理大致包括對(duì)空缺鍵值進(jìn)行填充操作, 對(duì)噪聲數(shù)據(jù)進(jìn)行相應(yīng)的平滑處理,對(duì)孤立點(diǎn)和異常點(diǎn)進(jìn)行刪除處理等。 |
2 | 數(shù)據(jù)集成 Data Integration |
將多個(gè)數(shù)據(jù)庫(kù)或者數(shù)據(jù)文件里面包含的數(shù)據(jù)進(jìn)行集成處理。 |
3 | 數(shù)據(jù)轉(zhuǎn)換 Data Transformation |
將數(shù)據(jù)進(jìn)行聚集或者規(guī)范化處理,從一種形式轉(zhuǎn)換成另外一種我們需要的形式。 |
4 | 數(shù)據(jù)規(guī)約 Data Reduction |
對(duì)龐大的數(shù)據(jù)集進(jìn)行壓縮處理,且盡量保證最終預(yù)測(cè)結(jié)果的一致性。 |
下面將詳細(xì)介紹常用的數(shù)據(jù)處理方法:
缺失值的處理
標(biāo)記缺失值
# 生成包含缺數(shù)據(jù)的示例
import numpy as np
import pandas as pd
null_data = {'A': [10, np.nan, 25, np.nan, 42, np.nan],
'B': [12, 15, np.nan, 14, 17, np.nan],
'C': [10, 13, 27, 13, 19, 40]}
df = pd.DataFrame(null_data)
-
空值也有不同類(lèi)型
數(shù)值型空值 :NaN (not a number)
空字符串 :None
-
定位缺失數(shù)據(jù):
- 使用 isnUll() 返回 True 代表缺失值
- notnull()則與之相反
刪除缺失值
- 直接刪除
- 缺失數(shù)據(jù)占全部數(shù)據(jù)比例非常低,可忽略不計(jì)且刪除后不會(huì)對(duì)整體數(shù)據(jù)分布產(chǎn)生影響
- 缺失數(shù)據(jù)因?yàn)楸旧硖匦詿o(wú)法填充,比如對(duì)于某些檢測(cè)指標(biāo),填充數(shù)值會(huì)對(duì)結(jié)果產(chǎn)生影響的寧愿刪除也不要進(jìn)行處理
# 刪除缺失值
import pandas as pd
# 創(chuàng)建一個(gè)示例數(shù)據(jù)框
data = {'A': [1, 2, None, 4],
'B': [5, None, 7, 8],
'C': [None, 10, None, 12]}
df = pd.DataFrame(data)
# 刪除包含缺失值的行
cleaned_df1 = df.dropna() # 默認(rèn)刪除包含缺失值的行
cleaned_df2 = df.dropna(axis=1) # 刪除包含缺失值的列
cleaned_df3 = df.dropna(how='all') # 當(dāng)所有值為缺失值時(shí)刪除行
cleaned_df4 = df.dropna(thresh=2) # 至少要有 2 個(gè)非缺失值才保留行
cleaned_df5 = df.dropna(subset=['B', 'C']) # 只有在 'B' 和 'C' 列中同時(shí)存在空值的情況下,對(duì)應(yīng)的行才會(huì)被刪除
print(cleaned_df1)
print(cleaned_df2)
print(cleaned_df3)
print(cleaned_df4)
print(cleaned_df5)
填充缺失值
-
固定值填充:人為指定,使用行/列均值、中位數(shù)等
# Pandas 提供的 replace t填充固定值 print(df.replace(np.nan,0)) # 缺失值填充為0 # 專(zhuān)門(mén)用于填充缺失值的函數(shù) fillna() print(df.fillna(0)) # 使用各列的平均值填充 print(df.fillna(df.mean())) # 使用格列中位數(shù)填充 print(df.fillna(df.median()))
-
臨近值填充:使用缺失值相臨近的數(shù)值填充
# 使用后一個(gè)臨近的數(shù)據(jù)向前填充 print(df.fillna(method='bfill')) # 使用前一個(gè)臨近的數(shù)據(jù)向后填充 print(df.fillna(method='ffill'))
-
數(shù)字填充:使用函數(shù)插值填充
數(shù)據(jù)缺失但能看出數(shù)據(jù)的變化趨勢(shì),更好的缺失值填充方法時(shí)是使用數(shù)據(jù)方法進(jìn)行插值Pandas中的
interpolate()
可以快速應(yīng)用一些常用的插值函數(shù)sample_data = {'A': [1, np.nan, 3, np.nan, 5, 6], 'B': [1, 4, np.nan, np.nan, 25, 36]} df = pd.DataFrame(sample_data) # 線性插值 print(df.interpolate(method='linear')) # 2次函數(shù)插值 print(df.interpolate(method='polynomial', order=2))
重復(fù)值處理
# 示例數(shù)據(jù)
df = pd.DataFrame({'name': ['amy', 'david'] * 3 +
['jam'], 'class': [2, 2, 2, 4, 3, 2, 4]})
-
duplicated()
判斷是否存在重復(fù)值print(df.duplicated()) # 判斷重復(fù)值 存在則返回True print(df.duplicated().sum()) # 統(tǒng)計(jì)判斷重復(fù)值
-
dropduplicates()
去除重復(fù)值
df.drop_duplicatep() #去除全部重復(fù)值
df.drop_duplicates(['name']) #去除name列的重復(fù)值
df.drop_duplicates(keep='last') # 默認(rèn)保留重復(fù)項(xiàng)前面的值,而去除后面的值,‘last’則為保留最后一個(gè)
異常值的處理
當(dāng)涉及 Pandas 應(yīng)用數(shù)學(xué)與統(tǒng)計(jì)學(xué)領(lǐng)域中的異常值檢測(cè)時(shí),有一些比較深入的方法,包括概率方法,矩陣分解,以及神經(jīng)網(wǎng)絡(luò)等。下面是一些具體示例展示:
-
概率方法 - 一元正態(tài)分布檢測(cè)異常值:
import pandas as pd import numpy as np # 創(chuàng)建一個(gè)示例數(shù)據(jù)集 data = pd.DataFrame({'value': [1, 2, 3, 4, 5, 1000]}) # 計(jì)算均值和標(biāo)準(zhǔn)差 mean = data['value'].mean() std = data['value'].std() # 設(shè)置異常值閾值,例如均值加減3倍標(biāo)準(zhǔn)差 threshold = 3 * std # 使用一元正態(tài)分布方法檢測(cè)異常值 data['is_outlier'] = np.abs(data['value'] - mean) > threshold print(data)
-
概率方法 - 多元高斯方法檢測(cè)異常值:
from scipy import stats # 創(chuàng)建一個(gè)示例數(shù)據(jù)集 data = pd.DataFrame({ 'feature1': [1, 2, 3, 4, 5], 'feature2': [2, 4, 6, 8, 10] }) # 計(jì)算多元高斯分布概率密度 multivariate_dist = stats.multivariate_normal(mean=data.mean(), cov=data.cov()) # 設(shè)置異常值閾值 threshold = 0.01 # 例如設(shè)置一個(gè)較小的閾值 # 使用多元高斯方法檢測(cè)異常值 data['is_outlier'] = multivariate_dist.pdf(data) < threshold print(data)
-
矩陣分解方法檢測(cè)異常值:
from sklearn.decomposition import PCA # 創(chuàng)建一個(gè)示例數(shù)據(jù)集 data = pd.DataFrame({ 'feature1': [1, 2, 3, 4, 5], 'feature2': [2, 4, 6, 8, 100] }) # 使用主成分分析(PCA)進(jìn)行矩陣分解 pca = PCA(n_components=2) pca.fit(data) # 計(jì)算重構(gòu)誤差 reconstruction_error = np.sum((data - pca.inverse_transform(pca.transform(data))) ** 2, axis=1) # 設(shè)置異常值閾值 threshold = 20 # 例如設(shè)置一個(gè)閾值 # 使用矩陣分解方法檢測(cè)異常值 data['is_outlier'] = reconstruction_error > threshold print(data)
-
神經(jīng)網(wǎng)絡(luò)方法檢測(cè)異常值:
from sklearn.neighbors import LocalOutlierFactor # 創(chuàng)建一個(gè)示例數(shù)據(jù)集 data = pd.DataFrame({'value': [1, 2, 3, 4, 5, 1000]}) # 使用局部異常因子(Local Outlier Factor)進(jìn)行異常值檢測(cè) lof = LocalOutlierFactor(n_neighbors=2, contamination=0.1) # 設(shè)置參數(shù) data['is_outlier'] = lof.fit_predict(data[['value']]) print(data)
數(shù)據(jù)集合并
這里主要是用pandas中的常見(jiàn)方法進(jìn)行數(shù)據(jù)集的連接合并。
pandas.DataFrame.concat()
方法合并:
pandas.concat(
objs, # 接受一個(gè)列表或字典,表示要連接的 pandas 對(duì)象(Series 或 DataFrame)
axis=0, # 沿指定軸進(jìn)行連接,0 表示沿第一個(gè)軸(行方向)連接,1 表示沿第二個(gè)軸(列方向)連接
join='outer', # 指定連接的方式,'outer'表示并集(union),'inner'表示交集(intersection)
ignore_index=False,# 如果為 True,將忽略原始索引并生成一個(gè)新的整數(shù)索引
keys=None, # 創(chuàng)建層次化索引,用于識(shí)別每個(gè)片段
levels=None, # 指定多級(jí)索引的級(jí)別(通常自動(dòng)推斷)
names=None, # 指定多級(jí)索引的級(jí)別名稱(chēng)
verify_integrity=False, # 如果為 True,在連接操作之前驗(yàn)證軸是否包含重復(fù)項(xiàng)
sort=False # 如果為 True,對(duì)非連接軸上的索引進(jìn)行排序
)
以下是對(duì)各個(gè)參數(shù)的詳細(xì)解釋?zhuān)?/p>
-
objs
:要連接的 pandas 對(duì)象列表??山邮芤粋€(gè)列表(或字典),其中包含要連接的 DataFrame 或 Series 對(duì)象。 -
axis
:指定連接的軸方向。0 表示在行方向上連接,1 表示在列方向上連接。 -
join
:指定連接的方式。默認(rèn)為 'outer',表示取并集進(jìn)行連接,也可以選擇 'inner',表示取交集進(jìn)行連接。 -
ignore_index
:如果為 True,將忽略原始索引并生成一個(gè)新的整數(shù)索引。 -
keys
:當(dāng)數(shù)組沿著連接軸堆疊時(shí),可以用 keys 參數(shù)創(chuàng)建一個(gè)層次化索引(MultiIndex),以便識(shí)別每個(gè)片段。 -
levels
:指定鍵的層次化級(jí)別,通常不需要手動(dòng)指定,會(huì)根據(jù) keys 推斷。 -
names
:指定多級(jí)索引的級(jí)別名稱(chēng)。 -
verify_integrity
:如果為 True,在連接操作之前驗(yàn)證軸是否包含重復(fù)項(xiàng),如果包含重復(fù)項(xiàng)則會(huì)拋出 ValueError 異常。 -
sort
:如果為 True,在連接操作之后對(duì)非連接軸上的索引進(jìn)行排序。
?
pandas.DataFrame.merge()
方法合并:
pandas.merge(
left, # 左側(cè)的 DataFrame 對(duì)象
right, # 右側(cè)的 DataFrame 對(duì)象
how='inner', # 合并方式,默認(rèn)為 'inner',表示取兩個(gè) DataFrame 的交集
on=None, # 指定列名或索引級(jí)別作為合并的鍵,默認(rèn)為 None,表示自動(dòng)根據(jù)列名的交集進(jìn)行合并
left_on=None, # 指定左側(cè) DataFrame 中的列名或索引級(jí)別作為合并的鍵
right_on=None, # 指定右側(cè) DataFrame 中的列名或索引級(jí)別作為合并的鍵
left_index=False, # 如果為 True,在左側(cè) DataFrame 中使用索引作為合并鍵
right_index=False, # 如果為 True,在右側(cè) DataFrame 中使用索引作為合并鍵
sort=False, # 如果為 True,根據(jù)合并鍵對(duì)結(jié)果進(jìn)行排序
suffixes=('_left', '_right'), # 如果列名沖突,為列名添加后綴來(lái)區(qū)分,默認(rèn)為 '_left' 和 '_right'
copy=True # 如果為 True,在執(zhí)行合并操作時(shí)復(fù)制數(shù)據(jù)
)
以下是對(duì)各個(gè)參數(shù)的詳細(xì)解釋?zhuān)?/p>
-
left
:左側(cè)的 DataFrame 對(duì)象。 -
right
:右側(cè)的 DataFrame 對(duì)象。 -
how
:指定合并的方式,默認(rèn)為'inner'
,即取兩個(gè) DataFrame 的交集。還可以選擇'outer'
,表示取兩個(gè) DataFrame 的并集;'left'
,表示以左側(cè) DataFrame 的鍵為基準(zhǔn)進(jìn)行合并;'right'
,表示以右側(cè) DataFrame 的鍵為基準(zhǔn)進(jìn)行合并。 -
on
:指定列名或索引級(jí)別作為合并的鍵。默認(rèn)為 None,表示自動(dòng)根據(jù)列名的交集進(jìn)行合并。 -
left_on
:指定左側(cè) DataFrame 中的列名或索引級(jí)別作為合并的鍵。 -
right_on
:指定右側(cè) DataFrame 中的列名或索引級(jí)別作為合并的鍵。 -
left_index
:如果為 True,在左側(cè) DataFrame 中使用索引作為合并鍵。 -
right_index
:如果為 True,在右側(cè) DataFrame 中使用索引作為合并鍵。 -
sort
:如果為 True,根據(jù)合并鍵對(duì)結(jié)果進(jìn)行排序。 -
suffixes
:如果列名沖突,為列名添加后綴來(lái)區(qū)分,默認(rèn)為('_left', '_right')
。 -
copy
:如果為 True,在執(zhí)行合并操作時(shí)復(fù)制數(shù)據(jù)。
pandas.DataFrame.join()
方法:
DataFrame.join(
other, # 合并的另一個(gè) DataFrame 對(duì)象
on=None, # 指定列名或索引級(jí)別作為合并的鍵,默認(rèn)為 None,表示根據(jù)索引進(jìn)行合并
how='left', # 合并方式,默認(rèn)為 'left',表示以左側(cè) DataFrame 為基準(zhǔn)進(jìn)行左外連接
lsuffix='', # 左側(cè) DataFrame 列名相同時(shí)的后綴,默認(rèn)為 '',不添加任何后綴
rsuffix='', # 右側(cè) DataFrame 列名相同時(shí)的后綴,默認(rèn)為 '',不添加任何后綴
sort=False # 如果為 True,根據(jù)合并鍵對(duì)結(jié)果進(jìn)行排序
)
以下是對(duì)各個(gè)參數(shù)的詳細(xì)解釋?zhuān)?/p>
-
other
:合并的另一個(gè) DataFrame 對(duì)象。 -
on
:指定列名或索引級(jí)別作為合并的鍵。默認(rèn)為 None,表示根據(jù)索引進(jìn)行合并。 -
how
:指定合并的方式,默認(rèn)為'left'
,即以左側(cè) DataFrame 為基準(zhǔn)進(jìn)行左外連接。還可以選擇'inner'
,表示取兩個(gè) DataFrame 的交集;'outer'
,表示取兩個(gè) DataFrame 的并集;'right'
,表示以右側(cè) DataFrame 為基準(zhǔn)進(jìn)行右外連接。 -
lsuffix
:表示左側(cè) DataFrame 中列名相同時(shí)的后綴,默認(rèn)為 '',即不添加任何后綴。 -
rsuffix
:表示右側(cè) DataFrame 中列名相同時(shí)的后綴,默認(rèn)為 '',即不添加任何后綴。 -
sort
:如果為 True,根據(jù)合并鍵對(duì)結(jié)果進(jìn)行排序。
數(shù)據(jù)映射 map()
方法完成
df = pd.DataFrame({'name': ['amy', 'david', 'jam'], 'age': [14, 13, 12]})
name_to_gender = {'amy': 'girl', 'david': 'boy', 'jam': 'boy'} # 建立映射字典
df['gender'] = df['name'].map(name_to_gender)
分組聚合
pandas.DataFrame.groupby()
對(duì)數(shù)據(jù)集進(jìn)行分組聚合
df = pd.DataFrame({'key1': ['A', 'B', 'C', 'A', 'B', 'C'],
'key2': ['X', 'Y', 'X', 'Y', 'X', 'Y'],
'data': [1, 2, 3, 4, 5, 6]})
df.groupby(by='key1').sum()
df.groupby(by=['key1', 'key2']).mean() # 替換為count().mean()等其它函數(shù)
數(shù)據(jù)轉(zhuǎn)換
不僅是數(shù)據(jù)格式或類(lèi)型的轉(zhuǎn)換,更多的是通過(guò)一些統(tǒng)計(jì)學(xué)方法對(duì)數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化或離散化處理。
特征工程:需要去設(shè)計(jì)數(shù)據(jù)特征,以幫助訓(xùn)練得到性能更加優(yōu)異的模型。
標(biāo)準(zhǔn)化 Normalization(無(wú)量綱化)是數(shù)據(jù)預(yù)處理中的常用手段。標(biāo)準(zhǔn)化的目的主要是消除不同特征之間的量綱和取值范圍不同造成的差異。這些差異,不僅會(huì)造成數(shù)據(jù)偏重不均,還會(huì)在可視化方面造成困擾
import numpy as np
import pandas as pd
%matplotlib inline
np.random.seed(10) # 隨機(jī)數(shù)種子
df = pd.DataFrame({'A': np.random.random(
20), 'B': np.random.random(20) * 10000})
print(df.plot()) # 繪圖
此時(shí),B列數(shù)據(jù)太大,A列已經(jīng)無(wú)法看出趨勢(shì),近似一條直線.
Z-Score 標(biāo)準(zhǔn)化
Z-Score 標(biāo)準(zhǔn)化 是常用的標(biāo)準(zhǔn)化手段之一,其公式為:
其中, ??
為樣本數(shù)據(jù)的均值, ??
為樣本數(shù)據(jù)的標(biāo)準(zhǔn)差。Z-Score 標(biāo)準(zhǔn)化之后的數(shù)據(jù)的均值為 0,方差為 1。
通過(guò)Z-Score 標(biāo)準(zhǔn)化,可以使不同數(shù)據(jù)集之間的數(shù)據(jù)具有可比性,同時(shí)可以減小異常值對(duì)數(shù)據(jù)分析和模型建立的影響。
# 使用Z-Score標(biāo)準(zhǔn)化對(duì)上面的DataFrame進(jìn)行標(biāo)準(zhǔn)化處理并繪圖
df_z_score = (df - df.mean()) / df.std() # Z-Score 標(biāo)準(zhǔn)化
df_z_score.plot()
Z-Score 標(biāo)準(zhǔn)化方法在 Scipy
中有一個(gè)對(duì)應(yīng)的APIscipy.stats.zscore
可以使用
from scipy import stats
stats.zscore(df)
也可以將 DataFrame
處理從 NumPy
數(shù)組再運(yùn)算
(df.values - df.values.mean(axis=0)) / df.values.std(axis=0) # NumPy 數(shù)組運(yùn)算
除了 SciPy
,scikit-learn
也提供了 Z-Score 標(biāo)準(zhǔn)化API sklearn.preprocessing.StandardScaler()
Min-Max 標(biāo)準(zhǔn)化
該方法可以將數(shù)據(jù)轉(zhuǎn)化到一個(gè)特定的區(qū)間范圍內(nèi),通常是[0, 1]或者[-1, 1]之間。這種標(biāo)準(zhǔn)化方法適用于以下場(chǎng)景:
-
數(shù)據(jù)需要落入特定區(qū)間范圍內(nèi):例如神經(jīng)網(wǎng)絡(luò)的輸入層,很多情況下都要求輸入數(shù)據(jù)的范圍在[0, 1]或者[-1, 1]之間。
-
需要保留原始數(shù)據(jù)的相對(duì)性質(zhì):Min-Max 標(biāo)準(zhǔn)化會(huì)保持原始數(shù)據(jù)中不同數(shù)值之間的相對(duì)大小關(guān)系,不會(huì)改變數(shù)據(jù)的分布形態(tài)。
-
異常值較少:Min-Max 標(biāo)準(zhǔn)化對(duì)異常值比較敏感,如果數(shù)據(jù)中存在較多的異常值,可能會(huì)導(dǎo)致標(biāo)準(zhǔn)化后的數(shù)據(jù)集不夠均衡。
公式為:
其中, ????????為樣本數(shù)據(jù)的最大值, ????????為樣本數(shù)據(jù)的最小值, ?????????????????為極差。
# 使用Min-Max標(biāo)準(zhǔn)化對(duì)上面的DataFrame進(jìn)行標(biāo)準(zhǔn)化處理
df_min_max = (df - df.min()) / (df.max() - df.min()) # Min-Max 標(biāo)準(zhǔn)化
df_min_max.plot()
同樣,scikit-learn 也提供了 Min-Max 標(biāo)準(zhǔn)化的 API sklearn.preprocessing.MinMaxScaler()
,使用方法如下:
from sklearn.preprocessing import MinMaxScaler
MinMaxScaler().fit_transform(df)
獨(dú)熱編碼
在對(duì)數(shù)據(jù)的預(yù)處理過(guò)程中,我們會(huì)遇到有一些特征列中的樣本并不是連續(xù)存在的,而是以分類(lèi)形式存在的情況。例如,某一裝置的狀態(tài)有三種情況,分別為:正常、機(jī)械故障、電路故障。如果我們要將這些數(shù)據(jù)運(yùn)用到后續(xù)的預(yù)測(cè)分析中,就需要對(duì)文字狀態(tài)進(jìn)行轉(zhuǎn)換。一般情況下,可以用 0 表示正常,1 代表機(jī)械故障,2 代表電路故障。
所以,對(duì)于以分類(lèi)形式存在的特征變量,我們會(huì)采用一種叫 獨(dú)熱編碼 One-Hot Encoding 的方式將其轉(zhuǎn)換成二元特征編碼,進(jìn)一步對(duì)特征進(jìn)行了稀疏處理。獨(dú)熱編碼采用位狀態(tài)寄存器來(lái)對(duì)個(gè)狀態(tài)進(jìn)行編碼,每個(gè)狀態(tài)都由它獨(dú)立的寄存器位,并且在任意時(shí)候只有一位有效。
# Pandas 中,可以使用 get_dummies 很方便地完成獨(dú)熱編碼。
df = pd.DataFrame({'fruits': ['apple', 'banana', 'pineapple']*2}) # 示例裝置狀態(tài)表
pd.get_dummies(df) # 獨(dú)熱編碼
數(shù)據(jù)離散化
數(shù)據(jù)離散化有時(shí)候是為了算法實(shí)施需要,也有可能離散數(shù)據(jù)更適合數(shù)據(jù)的信息表達(dá)。當(dāng)我們對(duì)連續(xù)數(shù)據(jù)進(jìn)行按區(qū)間離散化時(shí),你可以通過(guò)編寫(xiě)代碼實(shí)現(xiàn)。不過(guò),這里介紹 Pandas 中一個(gè)非常方便的區(qū)間離散化方法 pd.cut
(適用于等寬離散化)
# 將數(shù)組等間距分割為3部分
pd.cut(np.array([1, 2, 7, 8, 5, 4, 12, 6, 3]), bins=3) # bins 指定劃分?jǐn)?shù)量
此時(shí),如果我們按照 3 個(gè)區(qū)間對(duì)數(shù)據(jù)添加類(lèi)別標(biāo)簽 "small", "medium", "large",只需要指定 labels= 參數(shù)即可
pd.cut(np.array([1, 2, 7, 8, 5, 4, 12, 6, 3]),
bins=3, labels=["small", "medium", "large"])
一般情況下,區(qū)間返回會(huì)以最大值為準(zhǔn),向最小值方向擴(kuò)展 0.1% 以保證元素被有效分割。所以上面的區(qū)間不是以最小值 1 開(kāi)始,而是 0.989。其中
當(dāng)然,也可以自行指定劃分區(qū)間:
pd.cut(np.array([1, 2, 7, 8, 5, 4, 12, 6, 3]),
bins=[0, 5, 10, 15], labels=["small", "medium", "large"])
數(shù)據(jù)規(guī)約
主成成分分析(Principal Components Analysis)
通過(guò)對(duì)協(xié)方差矩陣進(jìn)行特征分解,從而得出主成分(特征向量)與對(duì)應(yīng)的權(quán)值(特征值)。然后剔除那些較小特征值(較小權(quán)值)對(duì)應(yīng)的特征,從而達(dá)到降低數(shù)據(jù)維數(shù)的目的。
PCA
最便捷方式通過(guò)scikit-learn
完成
下面以常見(jiàn)的鳶尾花示例數(shù)據(jù)集作為示例:
# 加載鳶尾花實(shí)例數(shù)據(jù)集
import pandas as pd
from sklearn.datasets import load_iris
from matplotlib import pyplot as plt
%matplotlib inline
iris = load_iris() # 加載原始數(shù)據(jù)
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names) # 處理為 DataFrame
數(shù)據(jù)集包含有4列,代表鳶尾花的4個(gè)特征。若想將上面的數(shù)據(jù)繪制成數(shù)據(jù)點(diǎn)圖(平面散點(diǎn)圖),就無(wú)法實(shí)現(xiàn),此時(shí)就需要對(duì)數(shù)據(jù)進(jìn)行降維處理
介紹以下 sklearn.decomposition.PCA
方法中的幾個(gè)參數(shù):
-
n_components=
表示需要保留主成分(特征)的數(shù)量。 -
copy=
表示針對(duì)原始數(shù)據(jù)降維還是針對(duì)原始數(shù)據(jù)副本降維。當(dāng)參數(shù)為 False 時(shí),降維后的原始數(shù)據(jù)會(huì)發(fā)生改變,這里默認(rèn)為 True。 -
whiten=
白化表示將特征之間的相關(guān)性降低,并使得每個(gè)特征具有相同的方差。 -
svd_solver=
表示奇異值分解 SVD 的方法。有 4 參數(shù),分別是:auto
,full
,arpack
,randomized
。
# 續(xù)上段代碼, 進(jìn)行PCA
iris_pca = PCA(n_components=2).fit_transform(iris_df) # PCA 降 2 維
iris_pca = pd.DataFrame(iris_pca, columns=['pca_x', 'pca_y']) # 整理 DataFrame
iris_pca.plot.scatter(x='pca_x', y='pca_y') # 繪制數(shù)據(jù)點(diǎn)
iris_pca.plot.scatter(x='pca_x', y='pca_y',
c=iris.target, cmap='plasma') # 數(shù)據(jù)點(diǎn)著色
PCA在很多情況下是非常有用的, 上述是從可視化角度進(jìn)行,以下是常見(jiàn)使用:
-
降低數(shù)據(jù)維度:高維數(shù)據(jù)集會(huì)增加分析數(shù)據(jù)的復(fù)雜性,而PCA可以將高維數(shù)據(jù)投影到低維空間中,同時(shí)保留了大部分?jǐn)?shù)據(jù)的變異性。這有助于簡(jiǎn)化數(shù)據(jù)集、減少存儲(chǔ)空間和計(jì)算成本。
-
消除數(shù)據(jù)間的相關(guān)性:在許多數(shù)據(jù)集中,不同特征之間存在相關(guān)性。PCA可以消除或減輕這些特征之間的相關(guān)性,從而更好地反映數(shù)據(jù)之間的獨(dú)立性,減少重復(fù)信息。
-
提高模型的性能:在一些機(jī)器學(xué)習(xí)任務(wù)中,高維數(shù)據(jù)可能會(huì)導(dǎo)致過(guò)擬合,而PCA可以有效減少數(shù)據(jù)的維度,幫助改善模型的泛化能力,并提高預(yù)測(cè)的準(zhǔn)確性。
-
數(shù)據(jù)可視化:通過(guò)PCA技術(shù),可以將高維數(shù)據(jù)轉(zhuǎn)換為二維或三維,從而更好地將數(shù)據(jù)可視化展現(xiàn),以便更好地理解數(shù)據(jù)的結(jié)構(gòu)和特征。
-
去除噪聲:在某些數(shù)據(jù)集中可能會(huì)存在噪聲或不重要的信息,而PCA可以幫助排除這些噪聲,提取出數(shù)據(jù)中最重要的信號(hào)和特征。
-
特征提取:PCA可以幫助識(shí)別和提取主要的特征,從而更好地描述數(shù)據(jù)的內(nèi)在結(jié)構(gòu),有助于模式識(shí)別、數(shù)據(jù)挖掘和預(yù)測(cè)任務(wù)。
線性判別分析
線性判別分析(Linear Discriminant Analysis,英文:LDA)同樣可以用于特征降維。LDA 本來(lái)是一種分類(lèi)模型,它試圖找到兩類(lèi)物體或事件的特征的一個(gè)線性組合,以便能夠特征化或區(qū)分它們。
LDA 和 PCA 的本質(zhì)相似,都會(huì)將原始的樣本映射到維度更低的樣本空間中。不過(guò),PCA 映射后的樣本具有更大的發(fā)散性,而 LDA 映射后的樣本具有更明顯的類(lèi)別區(qū)分。
scikit-learn
同樣提供了可以用于 LDA 處理的 API:sklearn.discriminant_analysis.LinearDiscriminantAnalysis
,使用方法如下:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
iris_lda = LinearDiscriminantAnalysis(
n_components=2).fit_transform(iris_df, iris.target) # lda 降 2 維
iris_lda = pd.DataFrame(iris_lda, columns=['lda_x', 'lda_y']) # 整理 DataFrame
通過(guò)繪制子圖來(lái)對(duì)比PCA和LDA兩種方法降維之后的數(shù)據(jù)分布:
fig, axes = plt.subplots(ncols=2, nrows=1, figsize=(12, 3))
iris_lda.plot.scatter(x='lda_x', y='lda_y', c=iris.target,
cmap='plasma', ax=axes[0]) # 數(shù)據(jù)點(diǎn)著色
iris_pca.plot.scatter(x='pca_x', y='pca_y', c=iris.target,
cmap='plasma', ax=axes[1]) # 數(shù)據(jù)點(diǎn)著色
可以從上圖看出二者的區(qū)別。PCA 和 LDA 是兩種不同的降維方法,沒(méi)有方法的好壞之說(shuō)。一般情況下,PCA 會(huì)使用多一些,你可以看到 LDA 需要輸入目標(biāo)值,而 PCA 則無(wú)需這一點(diǎn)
皮爾遜相關(guān)系數(shù)
在統(tǒng)計(jì)學(xué)中, 皮爾遜積矩相關(guān)系數(shù)(英語(yǔ):Pearson product-moment correlation coefficient)用于度量?jī)蓚€(gè)變量 ?? 和 ?? 之間的相關(guān)(線性相關(guān)),其值介于 -1 與 1 之間。在自然科學(xué)領(lǐng)域中,該系數(shù)廣泛用于度量?jī)蓚€(gè)變量之間的相關(guān)程度。它是由卡爾·皮爾遜從弗朗西斯·高爾頓在 19 世紀(jì) 80 年代提出的一個(gè)相似卻又稍有不同的想法演變而來(lái)。這個(gè)相關(guān)系數(shù)也稱(chēng)作「皮爾遜相關(guān)系數(shù)」。
兩個(gè)變量之間的皮爾遜相關(guān)系數(shù)定義為兩個(gè)變量之間的協(xié)方差和標(biāo)準(zhǔn)差的商:
有了皮爾遜相關(guān)性系數(shù),我們就可以評(píng)估不同特征與目標(biāo)值直接的相關(guān)性,從而剔除那些相關(guān)性弱的特征,達(dá)到特征壓縮的目的。接下來(lái),我們使用 SciPy
提供的皮爾遜相關(guān)性系數(shù)計(jì)算方法 scipy.stats.pearsonr
來(lái)求解 iris 示例數(shù)據(jù)集各特征與目標(biāo)值之間的相關(guān)系數(shù)。
from scipy.stats import pearsonr
for i in range(4):
p = pearsonr(iris_df.iloc[:, i], iris.target)[0] # 求解每個(gè)特征與目標(biāo)值的相關(guān)性
print("{}: {}".format(iris.feature_names[i], p)) # 輸出
上文說(shuō)過(guò),皮爾遜相關(guān)系數(shù)介于 -1 與 1 之間,越接近 1 則代表越正相關(guān)。所以,iris 示例數(shù)據(jù)集中與目標(biāo)值更為相關(guān)的特征是 sepal length
,petal length
和 petal width
。
這里再補(bǔ)充一種計(jì)算數(shù)據(jù)集特征和目標(biāo)之間皮爾遜相關(guān)性系數(shù)的方法,你可以直接在 DataFrame
后添加 corr()
屬性獲得。更為常用的是通過(guò) Seaborn
可視化工具繪制熱圖。
import seaborn as sns
# 得到特征和目標(biāo)拼合后的 DataFrame
iris_full_df = pd.concat([pd.DataFrame(iris.data, columns=iris.feature_names),
pd.DataFrame(iris.target, columns=['iris_target'])], axis=1)
sns.heatmap(iris_full_df.corr(), square=True, annot=True) # corr() 函數(shù)計(jì)算皮爾遜相關(guān)系數(shù)
區(qū)別于手動(dòng)計(jì)算各特征和目標(biāo)之間的相關(guān)系數(shù),上方熱圖還計(jì)算了特征之間的相關(guān)系數(shù)。觀察熱圖最后一行,不難發(fā)現(xiàn)與通過(guò) scipy.stats.pearsonr
計(jì)算的結(jié)果一致。
卡方檢驗(yàn)
在 1900 年,皮爾遜發(fā)表了著名的關(guān)于 卡方檢驗(yàn)( Chi-Squared Test)的文章,該文章被認(rèn)為是現(xiàn)代統(tǒng)計(jì)學(xué)的基石之一。簡(jiǎn)單來(lái)講,實(shí)際觀測(cè)值與理論推斷值之間的偏離程度就決定卡方值的大小。若卡方值越小,代表偏差越小,越趨于符合。
scikit-learn
提供了 sklearn.feature_selection.SelectKBest
可以返回 k
個(gè)最佳特征,不過(guò)我們需要使用 sklearn.feature_selection.chi2
來(lái)計(jì)算卡方值。接下來(lái),同樣使用 iris
數(shù)據(jù)集來(lái)進(jìn)行卡方檢驗(yàn)。
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
kafang = SelectKBest(score_func=chi2, k=3) # 保留 3 個(gè)最佳特征,并使用卡方檢驗(yàn)
kafang.fit_transform(iris_df, iris.target)
transformer
輸出了需要保留的最佳特征,與 iris_df
對(duì)比后你會(huì)發(fā)現(xiàn),它保留了與皮爾遜相關(guān)系數(shù)結(jié)果一致的 sepal length
,petal length
和 petal width
特征。你可以通過(guò) scores_
屬性輸出卡方值的計(jì)算結(jié)果。
kafang.scores_ # 各特征與目標(biāo)值之間的卡方值
這里要補(bǔ)充一點(diǎn)是,實(shí)際使用中卡方檢驗(yàn)和皮爾遜相關(guān)系數(shù)的評(píng)估結(jié)果并不會(huì)都像 IRIS 數(shù)據(jù)集上一致,往往會(huì)得到不同的結(jié)果。這其實(shí)也就反映出選取最好的特征往往取決于評(píng)估指標(biāo),而沒(méi)有唯一答案。
上面我們介紹依據(jù)皮爾遜相關(guān)系數(shù)和卡方檢驗(yàn)進(jìn)行特征選擇的方法在特征工程中又被歸類(lèi)于 Filter 過(guò)濾法,它主要側(cè)重于單個(gè)特征跟目標(biāo)變量的相關(guān)性。這種方法的優(yōu)點(diǎn)在于計(jì)算速度快,且有較高的魯棒性。但是,F(xiàn)ilter 方法的缺點(diǎn)在于不考慮特征之間的相關(guān)性。因?yàn)?,有可能某一個(gè)特征自身不具備代表性,但是它和某些其它特征組合起來(lái)會(huì)使得模型會(huì)得到不錯(cuò)的效果。這一點(diǎn)就是 Filter 方法無(wú)法考慮到的了。
除此之外,從特征工程的角度來(lái)講,還可以使用 Wrapper 封裝法和 Embeded 集成方法來(lái)完成特征選擇。
數(shù)據(jù)抽樣
數(shù)據(jù)抽樣是通過(guò)減少樣本而非特征的數(shù)據(jù)來(lái)達(dá)到數(shù)據(jù)規(guī)約的效果。數(shù)據(jù)抽樣通過(guò)從原始數(shù)據(jù)集中隨機(jī)采集樣本構(gòu)成子集,從而降低數(shù)據(jù)規(guī)模。
最簡(jiǎn)單的抽樣當(dāng)然就是「隨機(jī)抽樣」了,我們可以生成一組隨機(jī)索引,然后從數(shù)據(jù)集中抽取到相應(yīng)的數(shù)據(jù)。這里,我們使用上方的 IRIS 數(shù)據(jù)集來(lái)完成。
import numpy as np
chosen_idx = np.random.choice(
len(iris_df), replace=False, size=10) # 從 IRIS 數(shù)據(jù)集中抽取 10 條數(shù)據(jù)
iris_df.iloc[chosen_idx] # 抽取相應(yīng)索引的數(shù)據(jù)
還可以直接使用 Pandas 提供的 pandas.DataFrame.sample
方法完成隨機(jī)抽樣過(guò)程,其中只需要指定抽樣數(shù)目即可。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-758791.html
iris_df.sample(n=10)
注意:數(shù)據(jù)抽樣雖然在這里被歸入數(shù)據(jù)規(guī)約,但實(shí)際上更多用于前面的環(huán)節(jié)中。一般情況下,會(huì)從清洗后的數(shù)據(jù)中抽樣,使用抽樣數(shù)據(jù)來(lái)完成特征工程和建模,以探索方法實(shí)施的可能性。最終再使用完整數(shù)據(jù)集進(jìn)行建模分析文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-758791.html
到了這里,關(guān)于數(shù)據(jù)分析--數(shù)據(jù)預(yù)處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!