| 数据科学、数据分析、人工智能必备知识汇总-----主目录-----持续更新(进不去说明我没写完):https://blog.youkuaiyun.com/grd_java/article/details/140174015 |
|---|
相关性分析,是指对
两个或多个具备相关性的变量元素进行分析,从而衡量两个变量因素的相关密切程度
相关性的元素之间
需要存在一定的联系或概率才可以进行相关性分析
一般的分析套路
- 图示初判,主要有正相关(一个变量增大,另一个变量也增大)和负相关(一个变量增大,另一个缩小)。而如果涉及多个变量的比较,就需要用到散点矩阵进行两两比较了
- Pearson相关系数(皮尔逊相关系数)
- Sperman秩相关系数(斯皮尔曼相关系数)
1. 图示初判
如果图示初判,发现数据存在一定相关性,可以进阶使用Pearson相关系数(皮尔逊相关系数)或Sperman秩相关系数(斯皮尔曼相关系数)
| 数据准备 |
|---|
我们要颜色正负相关,所以data1和data2是升序,data3是降序,那么data1和data2一定正相关,data1和data3一定负相关
data1 = pd.Series(np.random.randn(50)*100).sort_values() # 生成包含50个0-100随机数的升序有序序列
data2 = pd.Series(np.random.randn(50)*50).sort_values() # 0-50的随机数,升序
data3 = pd.Series(np.random.randn(50)*500).sort_values(ascending=False) # 0-500的,降序
画图即可
fig = plt.figure(figsize=(10,4))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
# data1和data2是正相关
ax1.set_title("正相关")
ax1.scatter(data1,data2)
ax1.grid()
# data1 和 data3是负相关
ax2.set_title("负相关")
ax2.scatter(data1,data3)
ax2.grid()
| 如果数据较多,就画散点矩阵 |
|---|
# 生成200行4列 0-100 随机数,四列的列名分别是ABCD
data = pd.DataFrame(np.random.randn(200,4)*100,columns=['A','B','C','D'])
data
pd.plotting.scatter_matrix(data,figsize=(8,8),
color='k',
marker='.',
diagonal='hist',
alpha=0.8,
range_padding=0.1)
下图可见,数据呈现正态分布性,因为是使用随机生成的,因此没有拟合出线性关系,这里只是介绍生成的方式
2. Pearson相关系数(皮尔逊相关系数)
皮尔森相关系数(Pearson correlation coefficient)又称皮尔森积矩相关系数(Pearson product-moment correlation coefficient),是一种线性相关系数
| 数据准备 |
|---|
data1 = pd.Series(np.random.rand(100)*100).sort_values() # 第一个自变量取值为0-100的100个数
data2 = pd.Series(np.random.rand(100)*50).sort_values() # 第二个事0-50的100个数
# 上面两个都是升序,可能是正相关,而且因为使用rand函数生成,满足正态分布条件
data = pd.DataFrame({'value1':data1.values,'value2':data2.values})
data
| pandas直接求出皮尔逊相关性系数 |
|---|
# pandas相关性方法corr(),默认使用皮尔逊,也就是默认情况下是data.corr(method='pearson',min_periods=1),会直接给出数据字段的相关系数矩阵
data.corr()
结果会以矩阵形式给出,代表data中每个变量和其他变量之间的皮尔逊相关系数
这么一行代码就求出来了,是不是很空虚,接下来介绍原理,和纯代码实现
| 原理和公式 |
|---|
衡量向量相似度的一种方法。
输出范围为-1到+1,0代表无相关性,负值为负相关,正值为正相关
0 < ∣ r ∣ < 1 0 < |r| < 1 0<∣r∣<1:表示存在不同程度线性相关
- ∣ r ∣ ≤ 0.3 |r| \le 0.3 ∣r∣≤0.3:不存在线性相关
- 0.3 < ∣ r ∣ ≤ 0.5 0.3 < |r| \le 0.5 0.3<∣r∣≤0.5:低度线性相关
- 0.5 < ∣ r ∣ ≤ 0.8 0.5 < |r| \le 0.8 0.5<∣r∣≤0.8:显著线性相关
- ∣ r ∣ > 0.8 |r| > 0.8 ∣r∣>0.8:高度线性相关
前提条件:正态分布:这是使用Pearson相关系数唯一要满足的条件
ρ ( X , Y ) = E [ ( X − μ X ) ( Y − μ Y ) ] σ X σ Y = = = = = = = = = = = = = = = 分割线 = = = = = = = = = = = = = = = = = = E [ ( X − μ X ) ( Y − μ Y ) ] ∑ i = 1 n ( X i − μ X ) 2 ∑ i = 1 n ( Y i − μ Y ) 2 \rho(X,Y)=\dfrac{E[(X-\mu_{X})(Y-\mu_Y)]}{\sigma_X\sigma_Y}\\\\===============分割线=================\\\\=\dfrac{E[(X-\mu_{X})(Y-\mu_Y)]}{\sqrt{\sum_{i=1}^n(X_i-\mu_X)^2}\sqrt{\sum_{i=1}^n(Y_i-\mu_Y)^2}} ρ(X,Y)=σXσYE[(X−μX)(Y−μY)]===============分割线==================∑i=1n(Xi−μX)2∑i=1n(Yi−μY)2E[(X−μX)(Y−μY)]公式还是挺简单的,一个均值一个标准差,都是本科概率论和数理统计会学到的东西,计算出的结果就是一个r,取值范围0-1
- μ X \mu_{X} μX:是样本X的均值
- E[]:这里指对[]里面的内容求和
| 正态性检验 |
|---|
判断数据是否满足正态性分布,需要用到scipy库kstest方法
from scipy import stats
u1,u2 = data['value1'].mean(),data['value2'].mean() # 计算两个自变量的均值
std1,std2 = data['value1'].std(),data['value2'].std() # 计算两个自变量的标准差
'''
stats.kstest是SciPy库中的一个函数,用于执行Kolmogorov-Smirnov检验,
主要用于检验数据是否符合某个特定的分布,如正态分布、均匀分布等。
该检验是一种非参数统计方法,通过比较数据的累积分布函数与理论分布函数,计算两者之间的最大差异(D值)和p值来进行判断。
'''
kstest1 = stats.kstest(data['value1'],'norm',(u1,std1))
kstest2 = stats.kstest(data['value2'],'norm',(u2,std2))
print('value1正态性检验\n',kstest1)
print('value2正态性检验\n',kstest2)
# 正态性检验:pvalue>0.05
if kstest1[1]>0.05 and kstest2[1]>0.05:
print("正态性检验通过")
'''
====================输出结果如下========================
value1正态性检验
KstestResult(statistic=0.09840759849171876, pvalue=0.2693873903765962, statistic_location=64.2293272377449, statistic_sign=-1)
value2正态性检验
KstestResult(statistic=0.097298660499746, pvalue=0.2814766593803092, statistic_location=37.49195062366543, statistic_sign=-1)
正态性检验通过
'''
| 将公式中的值都算出来 |
|---|
ρ ( X , Y ) = E [ ( X − μ X ) ( Y − μ Y ) ] σ X σ Y = E [ ( X − μ X ) ( Y − μ Y ) ] ∑ i = 1 n ( X i − μ X ) 2 ∑ i = 1 n ( Y i − μ Y ) 2 \rho(X,Y)=\dfrac{E[(X-\mu_{X})(Y-\mu_Y)]}{\sigma_X\sigma_Y}=\dfrac{E[(X-\mu_{X})(Y-\mu_Y)]}{\sqrt{\sum_{i=1}^n(X_i-\mu_X)^2}\sqrt{\sum_{i=1}^n(Y_i-\mu_Y)^2}} ρ(X,Y)=σXσYE[(X−μX)(Y−μY)]=∑i=1n(Xi−μX)2∑i=1n(Yi−μY)2E[(X−μX)(Y−μY)]
# 制作Pearson相关系数求值表
data['(x-u1)*(y-u2)'] = (data['value1'] - u1) * (data['value2']-u2)
data['(x-u1)**2'] = (data['value1']-u1)**2
data['(x-u2)**2'] = (data['value2']-u2)**2
data
| 最后用公式把Pearson相关系数求出来即可 |
|---|
E [ ( X − μ X ) ( Y − μ Y ) ] ∑ i = 1 n ( X i − μ X ) 2 ∑ i = 1 n ( Y i − μ Y ) 2 \dfrac{E[(X-\mu_{X})(Y-\mu_Y)]}{\sqrt{\sum_{i=1}^n(X_i-\mu_X)^2}\sqrt{\sum_{i=1}^n(Y_i-\mu_Y)^2}} ∑i=1n(Xi−μX)2∑i=1n(Yi−μY)2E[(X−μX)(Y−μY)]
r = data['(x-u1)*(y-u2)'].sum()/(np.sqrt(data['(x-u1)**2'].sum()*data['(x-u2)**2'].sum()))
print('Pearson相关系数为:%.4f' % r)
'''
输出结果为:
Pearson相关系数为:0.9964
'''
达到了0.9964, ∣ r ∣ > 0.8 |r| > 0.8 ∣r∣>0.8:就已经是高度线性相关了。说明相关性极高,我们生成散点图看一下
plt.scatter(data['value1'],data['value2'])
3. Sperman秩相关系数(斯皮尔曼相关系数)
皮尔逊相关系数是通过值来计算,而斯皮尔曼相关系数是通过秩来计算的
主要用于服从正态分布的连续变量,不服从正态分布的变量、分类的关联性可采用Speraman秩相关系数,也称
等级相关系数
- 对两个变量成对的取值按照从小到大顺序编秩, R x R_x Rx代表 X i X_i Xi的秩次, R y R_y Ry代表 Y i Y_i Yi的秩次
如果两个值大小一样,则秩次为 ( i n d e x 1 + i n d e x 2 ) / 2 (index1 + index2)/2 (index1+index2)/2
注意:秩次就是当前值在自己列按升序排列的所在位置
Spearman系数和Pearson系数在效率上等价
ρ s = 1 − 6 ∑ d i 2 n ( n 2 − 1 ) \rho_s = 1 - \dfrac{6\sum d_i^2}{n(n^2-1)} ρs=1−n(n2−1)6∑di2
d i = R x − R y di = R_x - R_y di=Rx−Ry
| 数据准备 |
|---|
# 样本数据
data = pd.DataFrame({'智商':[106,86,100,101,99,103,97,113,112,110],
'每周看电视小时数':[7,0,27,50,28,29,20,12,6,17]})
data
| 同样也可以直接通过pandas中的corr方法指定参数method='spearman’求出来 |
|---|
data.corr(method='spearman')
| 自己求 |
|---|
- 两个字段的秩次保存到range1和range2
# '智商'和'每周看电视小时数'重新按照升序排列,设定秩次index
data.sort_values(by='智商',inplace=True) # 按智商升序排列
data['range1'] = np.arange(1,len(data)+1) # 记录智商的顺序
data.sort_values(by='每周看电视小时数',inplace=True) # 按每周看电视小时数排序
data['range2'] = np.arange(1,len(data)+1) # 记录它的顺序到range2字段
data # 此时两个字段都有一个range字段记录它的升序位置
- 求出 d i 和 d i 2 d_i和d_i^2 di和di2
# data['d2'] = (data['range1'] - data['range2']) ** 2
# 求出di和di^2,分两步求方便大家理解
data['d'] = data['range1'] - data['range2']
data['d2'] = data['d']**2
data
- 列公式计算
#手敲公式求出rs
n = len(data)
rs = 1 - 6*(data['d2'].sum())/(n*(n**2 - 1))
print("Sperman秩相关系数: %.4f" %rs)














9648

被折叠的 条评论
为什么被折叠?



