一、數據說明
本次演練的數據集為某企業(yè)業(yè)務部門的客戶數據,將對該數據集進行數據預處理等操作。
二、缺失值判斷及處理
# 設置cell多行輸出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默認為'last'
# 導入相關庫
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
os.chdir(r'E:\python_learn\data\python_book_v2\chapter4')
file_name = 'cluster.txt'
data = pd.read_table(file_name,sep=',')
print(data.head())
USER_ID AVG_ORDERS AVG_MONEY IS_ACTIVE SEX
0 1 3.58 40.43 活躍 1
1 2 4.71 41.16 不活躍 1
2 3 3.80 39.49 不活躍 2
3 4 2.85 38.36 不活躍 1
4 5 3.71 38.34 活躍 1
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 5 columns):
USER_ID 1000 non-null int64
AVG_ORDERS 1000 non-null float64
AVG_MONEY 1000 non-null float64
IS_ACTIVE 1000 non-null object
SEX 1000 non-null int64
dtypes: float64(2), int64(2), object(1)
memory usage: 39.1+ KB
從返回信息可知,數據結構為(1000,5),1000條數據,5個字段,分別是:
- 用戶ID(USER_ID)
- 平均用戶訂單數量(AVG_ORDERS)
- 平均訂單價值(AVG_MONEY)
- 是否活躍(IS_ACTIVE)
- 性別(SEX),0(未知),1(男),2(女)
通過以上數據說明,可以發(fā)現有幾個字段需要做相關預處理
- USER_ID字段,不參與計算分析,分割出來
- AVG_ORDERS,AVG_MONEY這兩個字段,單位不一樣,也就是存在量綱差異,不能直接參與分析,需要標準化處理
- IS_ACTIVE字段,是字符串類型,為方便后面分析計算,需對其進行轉換為分類類型數據
- SEX字段,其實際應屬于分類類型數據
# 缺失值判斷(其實就data.info()返回信息看出不存在缺失值)
data.isna().sum() # 不存在缺失值,不需要處理缺失值
data.isna().sum().sum()
USER_ID 0
AVG_ORDERS 0
AVG_MONEY 0
IS_ACTIVE 0
SEX 0
dtype: int64
0
三、分割數據,提取需要處理的字段
# 分割數據
data_id = data['USER_ID']
data_numeric = data.iloc[:,1:3]
四、數據標準化處理
1、z-score標準化
z-socre標準化,又稱為零均值標準化。
公式:(x-x.mean)/x.std
z-score標準化后的數據集是以0為均值,1為標準差的正態(tài)分布。
但是z-score標準化是一種去中心化的方法會改變原數據的分布結構,不適用于稀疏數據使用。
print(data_numeric.head())
AVG_ORDERS AVG_MONEY
0 3.58 40.43
1 4.71 41.16
2 3.80 39.49
3 2.85 38.36
4 3.71 38.34
方法1 → 創(chuàng)建匿名函數直接使用公式,并用apply()函數將公式映射到DataFrame的每一列
f1 = lambda x :(x-x.mean())/x.std()
data_1 = data_numeric.apply(f1)
print(data_1.head())
AVG_ORDERS AVG_MONEY
0 0.255318 0.754353
1 1.388814 1.473263
2 0.475998 -0.171366
3 -0.476941 -1.284200
4 0.385720 -1.303896
方法2 → 使用sklearn.preprocessing的StandarScaler方法做z-score標準化處理
from sklearn import preprocessing
zscore = preprocessing.StandardScaler() # 創(chuàng)建StandarScaler對象
data_scaler_1 = zscore.fit_transform(data_numeric) # 用fit_transform方法轉換
data_scaler_1 = pd.DataFrame(data_scaler_1,columns=['AVG_ORDERS','AVG_MONEY'])
print(data_scaler_1.head())
AVG_ORDERS AVG_MONEY
0 0.255445 0.754731
1 1.389509 1.474000
2 0.476236 -0.171452
3 -0.477180 -1.284842
4 0.385913 -1.304548
2、Max-Min歸一標準化
Max-Min歸一標準化又稱為最大-最小標準化。
公式:(x-x.min)/(x.max-x.min)
Max-Min標準化后的數據會落入[0,1]區(qū)間內,并且Max-Min標準化最大優(yōu)點是保持原數據的結構,適合用于稀疏數據
print(data_numeric.head())
AVG_ORDERS AVG_MONEY
0 3.58 40.43
1 4.71 41.16
2 3.80 39.49
3 2.85 38.36
4 3.71 38.34
1.方法1 → 創(chuàng)建匿名函數直接使用公式,并用apply()函數將公式映射到DataFrame的每一列
f2 = lambda x : (x-x.min())/(x.max()-x.min())
data_2 = data_numeric.apply(f2)
print(data_2.head())
AVG_ORDERS AVG_MONEY
0 0.642005 0.625917
1 0.911695 0.804401
2 0.694511 0.396088
3 0.467780 0.119804
4 0.673031 0.114914
方法2 → 使用sklearn.preprocessing的MinMaxScaler方法做Max-Min標準化處理
minmaxscaler = preprocessing.MinMaxScaler() # 創(chuàng)建MinMaxScaler對象
data_scaler_2 = minmaxscaler.fit_transform(data_numeric) # 標準化處理
data_scaler_2 = pd.DataFrame(data_scaler_2,columns=['AVG_ORDERS','AVG_MONEY'])
print(data_scaler_2.head())
AVG_ORDERS AVG_MONEY
0 0.642005 0.625917
1 0.911695 0.804401
2 0.694511 0.396088
3 0.467780 0.119804
4 0.673031 0.114914
3、MaxAbs最大值絕對值標準化
MaxAbs標準化與Max-Min標準化類似。
公式:x/|x.max()|
MaxAbs標準化后的數據也是落入一個區(qū)間,但區(qū)間為[-1,1],并且MaxAbs標準化也能保持數據原有分布結構,因而能用于稀疏數據
方法1 → 創(chuàng)建匿名函數直接使用公式,并用apply()函數將公式映射到DataFrame的每一列
f3 = lambda x : x/abs(x.max())
data_3 = data_numeric.apply(f3)
print(data_3.head())
AVG_ORDERS AVG_MONEY
0 0.704724 0.963537
1 0.927165 0.980934
2 0.748031 0.941134
3 0.561024 0.914204
4 0.730315 0.913727
2.方法2 → 使用sklearn.preprocessing的MaxAbsScaler方法做MaxAbs標準化處理
maxabsscaler = preprocessing.MaxAbsScaler() # 創(chuàng)建MaxAbsScaler對象
data_scaler_3 = maxabsscaler.fit_transform(data_numeric) # 標準化處理
data_scaler_3 = pd.DataFrame(data_scaler_3,columns=['AVG_ORDERS','AVG_MONEY'])
print(data_scaler_3.head())
AVG_ORDERS AVG_MONEY
0 0.704724 0.963537
1 0.927165 0.980934
2 0.748031 0.941134
3 0.561024 0.914204
4 0.730315 0.913727
4、RobustScaler標準化
RobustScaler是針對離群點的標準化方法。
當需要最大限度保留數據中的異常值時,可以使用該方法進行標準化
# 僅使用data_numeric數據作為演示RobustScaler的使用,不代表data_numeric的數據屬于離群點
robustscaler = preprocessing.RobustScaler()
data_scaler_4 = robustscaler.fit_transform(data_numeric)
data_scaler_4
array([[-0.07212205, 0.63355705],
[ 0.55478502, 1.02550336],
[ 0.04993065, 0.12885906],
...,
[-0.81553398, -0.35973154],
[-0.58807212, -0.05369128],
[-0.0554785 , 0.1557047 ]])
5、數據標準化處理-總結
-
實際運用種應選擇何種方法進行標準化處理?
- 要做中心化處理,并且對數據分布有正態(tài)分布的需求時 ---->>> z-score標準化
- 要指定標準化后的數據范圍時 ---->>> Max-Min和MaxAbs標準化都適用,但前者更好
- 要對稀疏數據進行處理時 ---->>> Max-Min和MaxAbs標準化都是理想的選擇
- 要最大限度保留數據中的異常值時 ---->>> RobustScaler標準化
五、分類數據轉換為標志變量
- 1、分類數據:沒有內在數學意義的數據,僅用于區(qū)分事物類別
- 2、分類數據轉換為標志變量的方法:用pandas的pd.get_dummies()方法轉換
- pd.get_dummies(data,prefix=None,prefix_sep='_',dummy_na=False,columns=None,sparse=False,drop_first=False,dtype=None)
- data,需要轉換的對象,Series或DataFrame
- prefix_sep,轉換后列名前綴的分隔符,默認下劃線_
- dummy_na,是否增加一列表示NaN值,默認False,忽略NaN
- columns,可以指定需要轉換的列名,默認所有數據類型為category,object的類型列都會被轉換
- sparse,是否為稀疏矩陣,默認False
# 提取分類數據
data_category = data.iloc[:,3:]
print(data_category.head())
IS_ACTIVE SEX
0 活躍 1
1 不活躍 1
2 不活躍 2
3 不活躍 1
4 活躍 1
# sex列應為category類型數據,先查看其一共有多是個唯一值
data_category['SEX'].unique()
array([1, 2, 0], dtype=int64)
# 將sex字段轉換為分類類型
data_category['SEX'] = data_category['SEX'].astype('category')
data_category.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 2 columns):
IS_ACTIVE 1000 non-null object
SEX 1000 non-null category
dtypes: category(1), object(1)
memory usage: 9.0+ KB
# 用pd.get_dummies()將兩個分類數據轉換為標志數據
data_category = pd.get_dummies(data_category)
print(data_category.head())
IS_ACTIVE_不活躍 IS_ACTIVE_活躍 SEX_0 SEX_1 SEX_2
0 0 1 0 1 0
1 1 0 0 1 0
2 1 0 0 0 1
3 1 0 0 1 0
4 0 1 0 1 0
# 為了方便辨認,給其列標簽修改名字
data_category = data_category.rename(columns={'SEX_0':'SEX_未知','SEX_1':'SEX_男','SEX_2':'SEX_女'})
print(data_category.head())
IS_ACTIVE_不活躍 IS_ACTIVE_活躍 SEX_未知 SEX_男 SEX_女
0 0 1 0 1 0
1 1 0 0 1 0
2 1 0 0 0 1
3 1 0 0 1 0
4 0 1 0 1 0
六、數據接拼重塑
data_clean = pd.concat([data_id,data_1,data_category],axis=1)
print(data_clean.head())
# data_1是上面已經使用z-score進行標準化后的數據
USER_ID AVG_ORDERS AVG_MONEY IS_ACTIVE_不活躍 IS_ACTIVE_活躍 SEX_未知 SEX_男 \
0 1 0.255318 0.754353 0 1 0 1
1 2 1.388814 1.473263 1 0 0 1
2 3 0.475998 -0.171366 1 0 0 0
3 4 -0.476941 -1.284200 1 0 0 1
4 5 0.385720 -1.303896 0 1 0 1
SEX_女
0 0
1 0
2 1
3 0
4 0
知識補充 --->>> 什么是稀疏數據?
稀疏數據是指絕大多數數值缺失或為0的數據。但稀疏數據絕不是無用數據,通過適當的手段能夠挖掘出大量有用的信息。在一些情況下,稀疏數據達到95%以上