之前博客将各个小节分开发现有些不合理,故以后尽可能同一内容将总结在一篇内。
一、交叉分析
(仅仅横向、纵向分析,会忽略数据之间的关系,导致数据失真)
例:查看各个部门离职率之间是否存在差异
利用独立t分布进行检验。
效果图:
(颜色越深,越接机0,说明和离职率之间没关系)
代码如下(备注很详细):
#实例:查看各个部门离职率之间是否有明显差异
#使用独立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
#设置图形的字体为1.5倍
sns.set_context(font_scale=1.5)
df = pd.read_csv("/Users/ren/PycharmProjects/untitled7/data/HR.csv")
#按部门分组,用indices得到索引
dp_indices = df.groupby(by="department").indices
#print(dp_indices)
#关注离职率
sales_values = df["left"].iloc[dp_indices["sales"]].values
technical_values = df["left"].iloc[dp_indices["technical"]].values
#打印p统计量
print(ss.ttest_ind(sales_values,technical_values))
#只打印p统计量
print(ss.ttest_ind(sales_values,technical_values)[1])
#两两求p值,热力图
#取出indices的keys
dp_keys = list(dp_indices.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)):
p_value = ss.ttest_ind(df["left"].iloc[dp_indices[dp_keys[i]]].values,\
df["left"].iloc[dp_indices[dp_keys[j]]].values)[1]
#如果p值小于0.05,直接赋值为黑
if p_value<0.05:
dp_t_mat[i][j]=-1
else:
dp_t_mat[i][j] = p_value
#print(dp_t_mat)
#颜色越深,越接机0,说明和离职率之间没关系
sns.heatmap(dp_t_mat,xticklabels=dp_keys,yticklabels=dp_keys)
plt.show()
#透视表,index横坐标,columns列坐标,aggfunc聚合方法,0代表否,1代表是
piv_tb = pd.pivot_table(df,values="left",index=["promotion_last_5years","salary"],columns=["Work_accident"],aggfunc=np.mean)
#颜色越深,越接机0,说明和离职率之间没关系
sns.heatmap(piv_tb,vmin=0,vmax=1,cmap=sns.color_palette("Reds"))
plt.show()
二、因子分析
探索性因子分析:通过协方差矩阵、相关性矩阵进行分析。(主成分分析)
验证性因子分析:通过相关、卡方、覆盖、Anova、熵、F-值、自定等方法进行验证。
代码如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import math
sns.set_context(font_scale=1.5)
df = pd.read_csv("./data/HR.csv")
from sklearn.decomposition import PCA
#分析七个成分
my_pca=PCA(n_components=7)
#axis默认为0,从行处理
#刚刚一直报错,最后分析一下数据发现许多空数据,在此直接使用dropna删掉空数据即可
lower_mat=my_pca.fit_transform(df.drop(labels=["salary","department","left"],axis=1).dropna())
#重要性所占比例
print("Ratio",my_pca.explained_variance_ratio_)
#相关图
sns.heatmap(pd.DataFrame(lower_mat).corr(),vmin=-1,vmax=1,cmap=sns.color_palette("RdBu",n_colors=128))
plt.show()
可以看出,第一个的影响是最大的。
三、分组与钻取
有两种含义:第一种:顾名思义,对数据进行分组后再进行比较。第二种:根据数据的特征,将数据进行切分,分成不同的组,使组内成员尽可能靠拢,组间成员尽可能远离。
分类、聚类以后学。
常用手段:钻取
钻取:改变维的层次,变换分析的粒度
钻取分为:向上钻取,向下钻取。
离散属性分组比较容易,连续属性需要先离散化。
离散化之前,需要先观察数据有没有明显分隔(一阶差分)或者拐点(二阶差分)---》可以直接使用
也可以使用聚类的方法进行连续分组。
不存度(gin系数i):
(D为目标属性,例如是否离职,Ck为比较属性)
例:
则:
(图二中有两个明显拐点,可以根据拐点进行分组)
代码如下:
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("/Users/ren/PycharmProjects/untitled7/data/HR.csv")
#离散值:观察工资和离职率,柱状图
#属性hue,向下根据部门钻取分组
sns.barplot(x="salary",y="left",hue="department",data=df)
plt.show()
#连续值:根据满意度观察
sl_s = df["satisfaction_level"]
sns.barplot(list(range(len(sl_s))),sl_s.sort_values())
#根据拐弯的点进行分组
plt.show()
四、相关分析
定义:衡量两组数据或者两组样本,分布趋势或者变化趋势的分析方法,
最常用项关系数来衡量。
相关系数
使用相关系数衡量连续属性相关性:
import pandas as pd
import scipy.stats as ss
import matplotlib.pyplot as plt
import seaborn as sns
import math
sns.set_context(font_scale=1.5)
df = pd.read_csv("/Users/ren/PycharmProjects/untitled7/data/HR.csv")
#连续情况下:
#表里有很多离散属性,计算相关性会自动去除离散属性
sns.heatmap(df.corr(),vmin=-1,vmax=1,cmap=sns.color_palette("RdBu",n_colors=128))
plt.show()
离散属性相关性的衡量:
特例:二类离散属性(只有0,1)相关性分析,可以皮尔逊相关系数来直接衡量大小。
多类离散属性比较麻烦,如果都是定序数据(可以转换为0、1、2、3等)进行比尔逊相关系数进行计算(会有一定的失贞)
更为一般的,可以使用熵进行离散属性的相关系数计算
代码如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import math
sns.set_context(font_scale=1.5)
df = pd.read_csv("./data/HR.csv")
sns.heatmap(df.corr(),vmax=1,vmin=-1,cmap=sns.color_palette("RdBu",n_colors=128))
plt.show()
#离散相关性度量
s1 = pd.Series(["X1", "X1", "X2", "X2", "X2", "X2"])
s2 = pd.Series(["Y1", "Y1", "Y1", "Y2", "Y2", "Y2"])
#熵
def getEntropy(s):
prt_ary = np.array(pd.groupby(s, by=s).count().values / float(len(s)))
return -(np.log2(prt_ary) * prt_ary).sum()
#条件熵
def getCondEntropy(s1, s2):
assert (len(s1) == len(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])
#熵增益
def getEntropyGain(s1, s2):
return getEntropy(s2) - getCondEntropy(s1, s2)
#熵增益率
def getEntropyGainRatio(s1, s2):
return getEntropyGain(s1, s2) / getEntropy(s2)
#相关度
def getDiscreteRelation(s1, s2):
return getEntropyGain(s1, s2) / math.sqrt(getEntropy(s1) * getEntropy(s2))
#求概率平方和
def getProbSS(s):
if not isinstance(s,pd.core.series.Series):
s = pd.Series(s)
prt_ary = np.array(pd.groupby(s, by=s).count().values / float(len(s)))
return sum(prt_ary ** 2)
#Gini系数
def getGini(s1, s2):
assert (len(s1) == len(s2))
d = dict()
for i in list(range(len(s1))):
d[s1[i]] = d.get(s1[i], []) + [s2[i]]
return 1 - sum([getProbSS(d[k]) * len(d[k]) / float(len(s1)) for k in d])
#离散相关性度量
s1 = pd.Series(["X1", "X1", "X2", "X2", "X2", "X2"])
s2 = pd.Series(["Y1", "Y1", "Y1", "Y2", "Y2", "Y2"])
print(getEntropy(s1))
print(getEntropy(s2))
print(getCondEntropy(s1, s2))
print(getCondEntropy(s2, s1))
print(getEntropyGain(s1, s2))
print(getEntropyGain(s2, s1))
print(getEntropyGainRatio(s1, s2))
print(getEntropyGainRatio(s2, s1))
print(getDiscreteRelation(s1, s2))
print(getDiscreteRelation(s2, s1))
五、聚类分析(后续更新)
六、回归分析(后续更新)
总结: