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

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

2)相关系数:
i.皮尔逊相关系数: 度量两个变量x和y之间的线性相关相关程度
ii.斯皮尔曼相关系数:
注:
连续数据,正态分布,线性关系,用pearson相关系数是最恰当
上述任一条件不满足,就用spearman相关系数,不能用pearson相关系数
两个定序测量数据之间也用spearman相关系数,不能用pearson相关系数

3)线性回归: 确定两种最小或两种以上的变量间相互依赖的定量关系的一种统计分析方法
i.线性回归效果判定:
    1.决定系数(R方)
    2.残差不相关(DW检验,0 - 4, dw = 2不相关)

4)主成分分析与奇异值分解
    目的:降维,排除多余维度


II.编码实现
import numpy as np
import pandas as pd
import scipy as s
import scipy.stats as ss

# 1-i.正态分布检验
# H0:服从正态分布
# H1:不服从正态分布
norm_list = ss.norm.rvs(size = 20)
norm_test = ss.normaltest(norm_list)
print(norm_test)
# NormaltestResult(statistic=2.6266998121429004, pvalue=0.2689176967933882)
# p>0.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,相关系数(定序)

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值