[Python数据分析] 4-预处理理论

I.理论部分
数据和特征决定了机器学习的上线,而模型和算法只是逼近这个上限而已
1)特征工程
i.特征使用:数据选择,数据可用性
ii.特征获取:特征来源,特征存储
iii.特征处理:数据清洗,特征预处理
  1.数据清洗:抽样,异常值处理
  2.特征预处理:特征选择,特征变换,特征降维,特征延伸
iv.特征监控:现有特征,新特征

II.编码实现
# 1)特征预处理:
# 概念:标注(标记,标签,label):和目的直接相关的,我们所关注的,通常来说是不容易直接获得的,其他的称之为特征
# i.特征选择:剔除与标注不相关或冗余的特征,数据规约的思路之一(另一个为抽样),三个思想:
#   1.过滤思想:剩余个数结合多因子探索性数据分析与复合分析
#   2.包裹思想(RFE算法):特征集合中选择标注,构造简单模型,根据系数去掉弱特征,余下的特征重复过程,直到评价指标下降较大或低于阈值停止
#   3.嵌入思想:根据简单的模型对标注进行建模,对特征的系数正则化,剔除系数小的特征,但有风险,建议嵌入思想选择的模型与最终使用的模型有比较强的关联
#   *每次特征选择后都需要用模型进行验证*
import numpy as np
import pandas as pd
import scipy.stats as ss
# 调用SVR回归器和决策树回归器
from sklearn.svm import SVR
from sklearn.tree import DecisionTreeRegressor
df = pd.DataFrame({"A":ss.norm.rvs(size=10),"B":ss.norm.rvs(size=10),
                   "C":ss.norm.rvs(size=10),"D":ss.norm.rvs(size=10)})
print(df)
# 利用loc纵向切割,设定特征和标注
X = df.loc[:,["A","B","C"]]
Y = df.loc[:,["D"]]
# 调用特征选择的三个方法,分别对应:过滤思想,包裹思想,嵌入思想
from sklearn.feature_selection import SelectKBest,RFE,SelectFromModel
# 1.过滤思想,k为选择的特征个数,拟合转换
skb = SelectKBest(k=2)
skb_ft = skb.fit_transform(X,Y)
print("skb:",skb_ft)
# 2.包裹思想,estimator选择回归器,n_features_to_select为选择的特征个数,step为每迭代1次去除多少个特征,拟合转换
rfe = RFE(estimator=SVR(kernel="linear"),n_features_to_select=2,step=1)
rfe_ft = rfe.fit_transform(X,Y)
print("rfe:",rfe_ft)
# 3.嵌入思想,estimator选择回归器,threshold特征选择的阈值,默认为均值,拟合转换
sfm = SelectFromModel(estimator=DecisionTreeRegressor(),threshold=0.1)
sfm_ft = sfm.fit_transform(X,Y)
print("sfm:",sfm_ft)
# 具体保留哪两个可以对照df的三列看留下来的是那两列即为保留哪两个特征

# ii.特征变换:根据特征的特点对其进行转换,以发挥其特点 
#   1.对指化:对数据进行缩放,numpy.log(),np.exp()
#   2.数据离散化:将连续变量分成几段(bins):
#     离散化主要指的分箱操作(箱的深度:数据个数,箱的宽度:数据区间),使用前提:先从小大排序,目的:
#       1)克服数据缺陷(噪声) 解决方案:等频离散-等频分箱(等深分箱)
#       2)某些算法要求(贝叶斯算法) 解决方案:等距离散-等距分箱(等宽分箱)
#       3)数据非线性映射需求 解决方案:自因变量优化,找到拐点
#   3.归一化:将数据转化到范围在0-1的数:X=(X-Xmin)/(Xmax-Xmin)
#   4.标准化:将数据转化为标准化,标准化的口径千差万别,此处将数值转化为均值为0,标准差为1的尺度上的数:X=(X-Xmean)/Xstd
#     标准化的意义:体现单数据与该特征下其他数据的相对大小的差距关系
#   5.数值化:将非数值数据转化为数值数据的过程
#     数值化:针对定类数据(男女),采用独热(扩维的思路),针对定序数据(低中高)采用标签化
#     归一化:针对定距数据(温度)
#   6.规范化/正规化:将一个向量的长度正规到单位1
#       1)直接用在特征上(用的少)
#       2)用在每个对象的各个特征的表示(体现一个对象各个特征之间的相对影响特点)
#       3)回归模型的参数上(回归模型上用的多, l2)
import numpy as np
import pandas as pd
# ii-1:对指化
lst = [1,10,100,10000,10000]
new_lst = np.log(lst)
# ii-2:数据离散化
lst = [6,8,10,15,16,24,25,40,67]
# 等深分箱(分箱对象,区间数,区间对应标签)
q_cut = pd.qcut(lst,q=3,labels=["low","medium","high"])
# 等宽分箱(分箱对象,区间,区间对应标签)
cut = pd.cut(lst,bins=3,labels=["low","medium","high"])
# ii-3:归一化,数据格式需转化为np.array()
from sklearn.preprocessing import MinMaxScaler
lst = [3,5,7,8,9,10,15]
new_lst = np.array(lst)
mms_ftr = MinMaxScaler().fit_transform(np.array(lst).reshape(-1,1))
# ii-4:标准化,数据格式需转化为np.array()
from sklearn.preprocessing import StandardScaler
lst = [3,5,7,8,9,10,15]
new_lst = np.array(lst)
ss_ftr = StandardScaler().fit_transform(np.array(lst).reshape(-1,1))
# ii-5:数值化,数据格式需转化为np.array()
# 可排序的默认按首字母排序并赋值
from sklearn.preprocessing import LabelEncoder
lst = ["Low","Medium","High","Medium","Low"]
le = LabelEncoder()
le_ftr = le.fit_transform(np.array(lst)).reshape(-1,1)
# 不可排序的按OneHotEncoder形式
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
lst = ["Red","Yellow","Blue","Green"]
le = LabelEncoder()
lb_ft = le.fit_transform(np.array(lst))
ohe = OneHotEncoder()
ohe_ftr = ohe.fit_transform(le.transform(np.array(["Red","Yellow","Blue","Green"])).reshape(-1,1))
ohe_ft_t = ohe_ftr.toarray()
# ii-6:规范化/正则化,数据格式需转化为np.array()
# 规范化是对行进行规范化,所以要np.array([[1,1,3,-1,2]]),使其成为行,此处也不用reshape
from sklearn.preprocessing import Normalizer
lst = [3,5,7,8,9,10,15]
N = Normalizer(norm="l1")  # 可指定正则化方法,默认l2
N_ft = N.fit_transform(np.array([lst]))

# iii.特征降维
#     1.PCA,奇异值分解等线性降维:未考虑标注,只考虑特征之间关系,是一种无监督的降维方法,见前章
#       思路:
#         A.求特征协方差矩阵
#         B.求协方差矩阵的特征值和特征向量
#         C.将特征值按照从大到小的顺序排序,选择其中最大的K个
#         D.将样本点投射到选取的特征向量上
#     2.LDA降维:线性判别式分析,考虑标注
#       核心思想:投影变化后同一标注内的距离尽可能的小,不同标注间距离尽可能大
# LDA降维
import numpy as np
import pandas as pd
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# 设定二维特征及标注
X = np.array([[-1,-1],[-2,-1],[-3,-2],[1,1],[2,1],[3,2]])
Y = np.array([1,1,1,2,2,2])
# 指定降到一维并拟合
lda = LinearDiscriminantAnalysis(n_components=1)
lda_ft = lda.fit_transform(X,Y)
# 另外:可以将其作为判别器(Fisher Classifier)使用
lda_f = lda.fit(X,Y)
# 设定一个二维(要和给定的特征个数一致)的数组,让其分类
sample = np.array([[0.8,1]])
lda_f_p = lda_f.predict(sample)
print(lda_f_p)
# [2],即被分到了第二类

# iv.特征衍生
#     1.四则运算
#     2.求导或者高阶求导
#     3.人工归纳
III.结合HR表的综合操作,以HR表中的left作为标注,其余的作为特征
import numpy as np
import pandas as pd
pd.set_option("display.max_columns",None)
from sklearn.preprocessing import MinMaxScaler,StandardScaler  # 归一化,标准化
from sklearn.preprocessing import LabelEncoder,OneHotEncoder  # 标签化,独热化
from sklearn.preprocessing import Normalizer  # 规范化/正规化
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis  # LDA降维
from sklearn.decomposition import PCA  # PCA降维

# III-i:主体部分
# sl:satisfaction_level---False:MinMaxScaler,True:StandardScaler
# le:last_evaluation---False:MinMaxScaler,True:StandardScaler
# npr:number_project---False:MinMaxScaler,True:StandarScaler
# amh:average_monthly_hours---False:MinMaxScaler,True:StandarScaler
# tsc:time_spend_company---False:MinMaxScaler,True:StandarScaler
# wa:Work_accident---False:MinMaxScaler,True:StandarScaler
# pl5:promotion_last_5years---False:MinMaxScaler,True:StandarScaler
# dp;department---False:LabelEncodering,True:OneHotEncodering
# slr:salary---False:LabelEncodering,True:OneHotEncodering
def hr_preprocessing(sl=False,le=False,npr=False,amh=False,tsc=False,wa=False,
                     pl5=False,dp=False,slr=False,low_d=False,ld_n=1):
    # 1.导入数据并清洗
    df = pd.read_csv(r"C:\Users\Administrator\sample_code\data\HR.csv")
    df = df.dropna(subset=["satisfaction_level","last_evaluation"])  # 删除这两列中的空值
    df = df[df["satisfaction_level"]<=1][df["salary"]!="nme"]  # 删除这两列中的异常值
    # 2.选取标注,并分离标注和特征
    label = df["left"]
    df = df.drop("left",axis=1)
    # 3.特征选择(写一个计算相关系数的查询)
    # 可以参考附件进行筛选,此处特征数量较少,就不剔除了
    # 4.特征处理:
    # 1.sl,le,npr,amh,tsc,wa,pl5,dp,slr考虑归一化或标准化
    # 2.dp和slr要进行数值化处理
    # sl,le,npr,amh,tsc,wa,pl5,dp,slr:False:MinMaxScaler,True:StandardScaler
    scaler_list = [sl,le,npr,amh,tsc,wa,pl5]
    column_list = ["satisfaction_level","last_evaluation","number_project",
                   "average_monthly_hours","time_spend_company","Work_accident",
                   "promotion_last_5years"]
    for i in range(len(scaler_list)):  # 遍历scaler_list
        if not scaler_list[i]:  # 如果为假时,归一化
            df[column_list[i]] = \
                MinMaxScaler().fit_transform(df[column_list[i]].values.reshape(-1,1)).reshape(1,-1)[0]  # 二维取第0个
        else:  # 如果为真时,标准化
            df[column_list[i]] = \
                StandardScaler().fit_transform(df[column_list[i]].values.reshape(-1,1)).reshape(1,-1)[0]
    # dp,salary:False:LabelEncodering,True:OneHotEncodering
    scaler_list = [dp,slr]
    column_list = ["department","salary"]
    for j in range(len(scaler_list)):
        if not scaler_list[j]:
            # 此处再加一个判断是否为salary的条件,LabelEncoder默认按照字母顺序排,这边要修改一下
            if column_list[j] == "salary":
                df[column_list[j]] = [map_salary(s) for s in df["salary"].values]
            else:
                df[column_list[j]] = \
                    LabelEncoder().fit_transform(df[column_list[j]])
            # 对上述结果归一化处理
            column_list[j] = \
                MinMaxScaler().fit_transform(df[column_list[j]].values.reshape(-1,1)).reshape(1,-1)[0]
        else:
            # 采用pandas中的一个方法简单的解决OneHotEncoder,对应数据源,列
            df = pd.get_dummies(df,columns=[column_list[j]])
    # 4.最后考虑是否降维,low_d=True为选择降维,此处标注left已经分离,只能采用采用PCA降维
    if low_d:
        return PCA(n_components=ld_n).fit_transform(df.values),label
    return df,label

# III-ii:salary调整数值化对应的顺序部分
# 或者这样: d = {'low':0,'medium':1,'high':2}
# 默认return第0个
d = dict([("low",0),("medium",1),("high",2)])
def map_salary(s):
    return d.get(s,0)

# III-iii:触发器
def main():
    print(hr_preprocessing(sl=True,dp=True))
if __name__ == "__main__":
    main()
# IV.附件1:特征选择
import numpy as np
import pandas as pd
pd.set_option("display.max_columns",None)
import seaborn as sns
import matplotlib.pyplot as plt
import scipy.stats as ss
df = pd.read_csv(r"D:\Work\data\HR.csv")
df = df.dropna(subset=["satisfaction_level","last_evaluation"])  # 删除这两列中的空值
df = df[df["satisfaction_level"]<=1][df["salary"]!="nme"]  # 删除这两列中的异常值
df = df.drop(["department","salary"],axis=1)

# 1.直接做图
sns.heatmap(df.corr(),vmin=-1,vmax=1,cmap=sns.color_palette("RdBu",n_colors=16))
plt.show()

# 2-1.pandas计算相关系数
print(df.corr())

# 2-2.numpy计算相关系数
sl = df["satisfaction_level"]
le = df["last_evaluation"]
npr = df["number_project"]
amh = df["average_monthly_hours"]
tsc = df["time_spend_company"]
wa = df["Work_accident"]
l = df["left"]
corr = np.corrcoef([sl,le,npr,amh,tsc,wa,l])
print(corr)


# 附件2:归一化和标准化的计算
# list中的数值要转化为float格式,不然做除法的时候会只保留整数部分,加减倒是没影响,方差也是
# 归一化
import numpy as np
import pandas as pd
list = [3,5,7.2,8,9,10,15]
float_list = [float(i) for i in list]
Xmin = np.min(float_list)
Xmax = np.max(float_list)
for i in range(len(float_list)):
    float_list[i] = (float_list[i]-Xmin)/(Xmax-Xmin)
    # 对结果保留两位小数
    float_list[i] = round(float_list[i],2)
print(float_list)

# 标准化
import numpy as np
import pandas as pd
list = [3,5,7,8,9,10,15]
float_list = [float(i) for i in list]
Xmean = np.mean(float_list)
Xstd = np.std(float_list)
for i in range(len(float_list)):
    float_list[i] =(float_list[i]-Xmean)/Xstd
    float_list[i] = round(float_list[i], 2)
print(float_list)

 

你可能感兴趣的:(数据挖掘,数据分析)