[Python数据分析] 3-多因子探索性数据分析与复合分析

I.理论部分
1)假设检验与方差检验
i.假设检验: 根据一定假设条件由样本推断总体的一种方法,包括了:
    1.正态分布检验
    2.卡方检验: 实际观测值与理论推断值之间的偏离程度,检验两个因素建有没有联系
    3.独立t检验:判断两个平均数的差异是否显著(条件:n<30,总体标准差σ未知的正态分布)
    4.方差检验/F检验: 判断该模型中的全部或一部分参数是否适合用来估计母体(条件:正态分布的母体)
思路:
    A.建立原假设(包含等号)及备择假设
    B.选择检验统计量(根据数据的性质构造的转换函数,使其符合一个已知的格式)
    C.根据显著性水平(接受假设的最大失真限度,显著性水平+相似度=1,一般α=0.05),确定拒绝域
    D.计算p值或样本统计值,做出判断(p:原假设发生概率,p0.05,在95%置信水平下不能拒绝原假设。即no_list为正态分布

# 1-ii.卡方分布检验
# H0:观测与期望无显著差别
# H1:观测与期望有差别
chi2_list1 = [15,95]
chi2_list2 = [85,5]
chi2_test = ss.chi2_contingency([chi2_list1,chi2_list2])
print(chi2_test)
# (126.08080808080808, 2.9521414005078985e-29, 1, array([[55., 55.],[45., 45.]]))
# p<0.05,在95%置信水平下拒绝原假设。即观测与期望有差别


# 1-iii.独立t分布检验
# H0:两者无显著差别
# H1:两者有差别
t_list1 = ss.norm.rvs(size = 10)
t_list2 = ss.norm.rvs(size = 30)
t_test = ss.ttest_ind(t_list1, t_list2)
print(t_test)
# Ttest_indResult(statistic=-1.7227625227024566, pvalue=0.09306183239257176)
# p>0.05,在95%置信水平下不能拒绝原假设,两者无显著差别

# 1-iv.F检验/方差检验
# H0:多个样本总体均值相等
# H1:多个样本总体均值不相等或不全等
v_list1 = [49,50,39,40,43]
v_list2 = [28,32,30,26,34]
v_list3 = [38,40,45,42,48]
v_test = ss.f_oneway(v_list1,v_list2,v_list3)
print(v_test)
# F_onewayResult(statistic=17.619417475728156, pvalue=0.0002687153079821641)
# p<0.05,在95%置信水平下拒绝原假设。即多个样本总体均值不相等或不全等


# 2-i.相关系数(计算需要转化为pd.Series的格式)
s1 = pd.Series([0.1,0.2,1.1,2.4,1.3,0.3,0.5,0.9])
s2 = pd.Series([0.5,0.8,1.7,2.9,1.5,0.4,0.3,0.9])
# 查看是否符合正态分布,并选择核实的相关系数计算方式
norm_test_s1 = ss.normaltest(s1)
norm_test_s2 = ss.normaltest(s2)
print(norm_test_s1)
print(norm_test_s2)
# NormaltestResult(statistic=4.018454041318242, pvalue=0.13409228518547123)
# NormaltestResult(statistic=4.127040099338424, pvalue=0.1270061142896789)
# # p>0.05,在95%置信水平下不能拒绝原假设。即s1,s2为正态分布,选择皮尔逊相关系数
corr_test = s1.corr(s2)
print(corr_test)
# 0.9438499420873504
# 两者存在明显的正相关

# 3-i.线性回归
# 引入线性回归的包,岭回归和Lasso回归见8.利用Python进行数据分析-挖掘建模(监督学习)
from sklearn.linear_model import LinearRegression
# 指定x为0-9的浮点数,reshape的作用:将每个元素当成一个数组
x = np.arange(10).astype(np.float).reshape((10,1))
# 指定y = 3x + 4 + 噪声
y = x*3 + 4 + np.random.random((10,1))
# 拟合
reg = LinearRegression()
res = reg.fit(x,y)
# 求预测值
y_pred = reg.predict(x)
# 查看参数和截距
print(reg.coef_)
print(reg.intercept_)
# y=x * reg.coef_ + reg.intercept_

# 4-i.奇异值分解
data = np.array([np.array([2.5,0.5,2.2,1.9,3.1,2.3,2,1,1.5,1.5]),
                 np.array([2.4,0.7,2.9,2.2,3,2.7,1.6,1.1,1.6,0.9])]).T
# 使用sklearn的降维方法,此处的PCA实际为奇异值分解
from sklearn.decomposition import PCA
# 指定降到1维
low_dim = PCA(n_components=1)
# 拟合
low_dim.fit(data)
# 查看维度重要性
component_importance = low_dim.explained_variance_ratio_
print(component_importance)
# 0.94733855
# 查看转换后的数值
new_data = low_dim.fit_transform(data)
print(new_data)
# array([[-0.79719813],[ 1.80013324],[-0.97456799],[-0.25079417],[-1.64398332],
#       [-0.89041293],[ 0.13374212],[ 1.16957423],[ 0.4639199 ],[ 0.98958705]]).T

# 4-ii.传统PCA变换需要自己写
import pandas as pd
import numpy as np
def my_PCA(data,n_components = 1000): # 默认高维度,即不选的话默认全选
    mean_values = np.mean(data, axis = 0) # 计算均值,axis=0,以列计算
    mid = data - mean_values  # 计算mid
    cov_mat = np.cov(mid, rowvar =False)  # 计算mid的协方差,rowvar=Flase指定列进行协方差的计算
    from scipy import linalg  # 引入scipy的线性方程包,用作协方差矩阵计算的用途
    eig_values, eig_vects = linalg.eig(np.mat(cov_mat))
    eig_values_index = np.argsort(eig_values)  # 对特征值排序并得到其索引,即下标
    eig_values_index = eig_values_index[:-(n_components + 1):-1]  # 取出最大的值对应的特征值
    eig_vects = eig_vects[:, eig_values_index]  # 取出对应的特征向量
    low_dim_mat = np.dot(mid,eig_vects)  # 降维后的矩阵
    return  low_dim_mat,eig_values

data=np.array([np.array([2.5,0.5,2.2,1.9,3.1,2.3,2,1,1.5,1.5]),
               np.array([2.4,0.7,2.9,2.2,3,2.7,1.6,1.1,1.6,0.9])]).T
new_data = my_PCA(data,n_components=1)
print(new_data)
III.六大分析的编码实现
# 1)交叉分析
# 目的:研究离职率(left)这一项,想要看看各部门(department)之间的离职率是否有差异
# 思路:采用独立t检验。首先得到各个部门的离职分布,两两间求t检验统计量,并求出P值
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据并清洗
df = pd.read_csv(r"C:\Users\Administrator\sample_code\data\HR.csv")
df = df.dropna(axis=0, how="any")
df = df[df["last_evaluation"]<=1][df["salary"]!="nme"][df["department"]!="sale"]
# 根据部门(department)分组,通过indices得到分组后的索引,赋值为dp_indices
dp_indices = df.groupby(by="department").indices
# 1.此处取出sales,technical的离职率left
# iloc基于索引位来选取数据集,0:4就是选取 0,1,2,3这四行,需要注意的是这里是前闭后开集合
sales_values = df["left"].iloc[dp_indices["sales"]].values
technical_values = df["left"].iloc[dp_indices["technical"]].values
# 计算两者的t统计量
t_test_sales_technical = ss.ttest_ind(sales_values,technical_values)
print(t_test_sales_technical)
# Ttest_indResult(statistic=-1.0601649378624074, pvalue=0.2891069046174478)
# p>0.05,接受原假设,即sales和technical的离职率无显著差异
# 2.两两间求t检验统计量
# 取出indices的key,这里的话就是各个indice的名称,对应部门名,赋值为dp_keys,pyhton3这里要list一下转化为数组
dp_keys = list(dp_indices.keys())
# 初始化一个矩阵,长宽为dp_keys的长度
dp_t_mat = np.zeros([len(dp_keys),len(dp_keys)])
# 遍历矩阵的值
for i in range(len(dp_keys)):
    for j in range(len(dp_keys)):
        # 同上理
        i_values = df["left"].iloc[dp_indices[dp_keys[i]]].values
        j_values = df["left"].iloc[dp_indices[dp_keys[j]]].values
        p_values = ss.ttest_ind(i_values,j_values)[1]
        # 往对应的位置赋值
        # 为了让一会儿的作图更明显一些,对于过小的值进行边缘化处理
        if p_values < 0.05:
            dp_t_mat[i][j] = -1
        else:
            dp_t_mat[i][j] = p_values
sns.heatmap(dp_t_mat, xticklabels=dp_keys, yticklabels=dp_keys,cmap=sns.color_palette("gist_gray"))
# 或者可以做一个透视表,利用Pandas中的pivot_table(数据源,观测值values,横坐标index,纵坐标columns,聚合方法aggfunc)
f = plt.figure()
piv_tb=pd.pivot_table(df,values="left",index=["promotion_last_5years","salary"],columns=["Work_accident"],aggfunc=np.mean)
sns.heatmap(piv_tb,vmin=0,vmax=1,cmap=sns.color_palette("Reds",n_colors=1024))
plt.show()

# 2)分组分析
# 目的:将数据分组后进行分析,结合其他分析方法,一种辅助手段(分组与钻取)
#       将数据进行切分,组间差异性,组内同质性,对新数据进行组的划分(聚类)
#       钻取是改变维的层次,变换分析的力度。
#       连续数据在钻取之前要看一下数据分布,找分隔或者拐点,借此对数据进行离散化处理
#       或者可以通过衡量不纯度的指标(Gini系数)对其进行分组
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据并清洗
df = pd.read_csv(r"D:\Work\data\HR.csv")
df = df.dropna(axis=0, how="any")
df = df[df["last_evaluation"] <= 1][df["salary"] != "nme"][df["department"] != "sale"]
# 1.离散值的分组
# 此处以不同部门不同薪水下的离职率为例
f = plt.figure()
# sns.barplot(data=df,x="salary",y="left",hue="department")
# plt.show()
# 2.连续值的分组
# 此处以满意度为例
sl_s = df["satisfaction_level"]
f = plt.figure()
sns.barplot(x=list(range(len(sl_s))),y=sl_s.sort_values())
plt.show()

# 3)相关分析
# 1.用相关系数直接衡量连续值的相关性,会自动排除离散值的两列
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据并清洗
df = pd.read_csv(r"D:\Work\data\HR.csv")
df = df.dropna(axis=0, how="any")
df = df[df["last_evaluation"] <= 1][df["salary"] != "nme"][df["department"] != "sale"]
# 对其中两列进行分析用下面的格式
# df = pd.DataFrame({"last_evaluation":df["last_evaluation"],"satisfaction_level":df["satisfaction_level"]})
sns.set_context(font_scale=1.5)
sns.heatmap(df.corr(),vmin=-1,vmax=1,cmap=sns.color_palette("RdBu",n_colors=128))
plt.show()
# 2.离散属性的相关性
# i.二类离散:也就是(0,1),这类可以直接用皮尔逊相关系数进行计算
# ii.多类离散:如果是定序的,可以赋上(0,1,2……)用皮尔逊相关系数进行计算,或者有一种更通用的办法,涉及到几个概念
import numpy as np
import pandas as pd
import scipy.stats as ss
import matplotlib.pyplot as plt
s1 = np.array(["x1","x1","x2","x2","x2","x2"])
s2 = np.array(["y1","y1","y1","y2","y2","y2"])
# 2-1:计算熵
# 熵:事件的不确定性,H(X) = -SIGMA(Pi*log(Pi))
def getEntropy(s):
    # 判断是否是Series格式
    if not isinstance(s,pd.core.series.Series):
        s=pd.Series(s)
    # 计算分布,对自己groupby,计数,转化为np.array的结构/数量
    prt_ary=pd.groupby(s,by=s).count().values/float(len(s))
    # 熵的计算公式
    return -(prt_ary*np.log2(prt_ary)).sum()
print("Entropy:",getEntropy(s2))
# 2-2:计算条件熵
# H(Y|X) = SIGMA(Pxi)*H(Y|X=(xi))
def getCondEntropy(s1,s2):
    d=dict()
    for i in list(range(len(s1))):
        d[s1[i]]=d.get(s1[i],[])+[s2[i]]
    return sum([getEntropy(d[k])*len(d[k])/float(len(s1)) for k in d])
print("getCondEntropy:",getCondEntropy(s2,s1))
# 2-3:计算熵增益/信息增益/互信息
# 信息增益-ID3:I(X,Y)=H(Y)-H(Y|X)=H(X)-H(X|Y),X对Y的影响大小,值越大反应先应该进行X特征的切分
def getEntropyGain(s1,s2):
    return getEntropy(s2)-getCondEntropy(s1,s2)
print("getEntropyGain:",getEntropyGain(s2,s1))
print("getEntropyGain:",getEntropyGain(s1,s2))
# 2-4:计算熵的增益率/信息增益率
# 信息增益率-C4.5:GainRation(X->Y)=I(X,Y)/H(Y),在前者的基础上额外考虑了Y标志本身的影响,值越大反应先应该进行X特征的切分
import math
def getEntropyGainRation(s1,s2) :
    return getEntropyGain(s1,s2)/getEntropy(s2)
print("getEntropyGainRation:",getEntropyGainRation(s1,s2))
print("getEntropyGainRation:",getEntropyGainRation(s2,s1))
# 2-5:计算离散值的相关性
# 离散值的相关性-Corr(X,Y):I(X,Y)/Sqrt(H(X))(H(Y))
import math
def getDiscreteCorr(s1,s2):
    return getEntropyGain(s1,s2)/math.sqrt(getEntropy(s1)*getEntropy(s2))
print("getDiscreteCorr",getDiscreteCorr(s1,s2))
print("getDiscreteCorr",getDiscreteCorr(s2,s1))
# 2-6:Gini系数
# Gini系数-CART:Gini(D)=1-SIGMA(Ck/D)^2
def getProSS(s):
    if not isinstance(s, pd.core.series.Series):
        s = pd.Series(s)
    prt_ary = pd.groupby(s, by=s).count().values/float(len(s))
    return sum(prt_ary**2)
def getGini(s1,s2):
    d = dict()
    for i in list(range(len(s1))):
        d[s1[i]] = d.get(s1[i], []) + [s2[i]]
    return 1-sum([getProSS(d[k])*len(d[k])/float(len(s1)) for k in d])
print("Gini:",getGini(s1,s2))
print("Gini:",getGini(s2,s1))

# 4)因子分析/主成分分析:此处研究各个成分和离职率的关系
#     目的:从多个属性变量中分析共性,相关因子的分析方法
#     i.探索性因子分析:目的找出最有效的属性,降维(主成分分析)
#     ii.验证性因子分析:验证因子与属性之间是否有关联,关联程度等(假设检验,相关分析……)
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据并清洗
df = pd.read_csv(r"C:\Users\Administrator\sample_code\data\HR.csv")
df = df.dropna(axis=0, how="any")
df = df[df["last_evaluation"]<=1][df["salary"]!="nme"][df["department"]!="sale"]
# 引入主成分分析的包
from sklearn.decomposition import PCA
# 此处研究各个成分和离职率的关系,成分设为7个,因为要除掉他本身和另2个离散的属性
my_pca = PCA(n_components=7)
# 去掉对应的三行,默认删除行,这里要删除列,axis=1
new_df = df.drop(labels=["salary","department","left"],axis=1)
# fit_transform(x)用来训练模型,同时返回处理完的数据
low_mat = my_pca.fit_transform(new_df)
# 查看各成分的对重要程度
# 此处有个疑问,explained_variance_ratio_默认从大到小罗列重要程度,如何能对应上成分?
print("Ratio:",my_pca.explained_variance_ratio_)
# 设置作图
sns.set_context(font_scale=1.5)
sns.heatmap(pd.DataFrame(low_mat).corr(),vmin=-1,vmax=1,cmap=sns.color_palette("RdBu",n_colors=128))
plt.show()

IV.小结
数据类型对应的处理方法:
    1.连续-连续:相关系数,假设检验
    2.连续-离散(二值):相关系数,相关系数,连续二值化
    3.连续-离散(非二值):相关系数(定序)
    4.离散(二值)-离散(二值):相关系数,熵相关,F分值
    5.离散-离散(非二值):熵相关,Gini,相关系数(定序)

 

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