数学建模--相关性分析及Python实现

写在前面:
笔记为自行整理,内容出自课程《数学建模学习交流》,主讲人:清风


相关系数只是用来衡量两个变量线性相关程度的指标,因此,使用相关系数衡量相关性前需要确认变量间是线性相关的

相关系数

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
# 支持显示中文
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False
data = pd.read_excel('eighth_girl.xlsx')
data.head()
身高体重肺活量50米跑立定跳远坐位体前屈
01555116879.71589.3
11585218689.31629.6
21605919589.91789.5
31635917569.718310.1
41656015759.015610.4
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 591 entries, 0 to 590
Data columns (total 6 columns):
身高       591 non-null int64
体重       591 non-null int64
肺活量      591 non-null int64
50米跑     591 non-null float64
立定跳远     591 non-null int64
坐位体前屈    591 non-null float64
dtypes: float64(2), int64(4)
memory usage: 27.8 KB
统计信息
dsc = data.describe()
dsc
身高体重肺活量50米跑立定跳远坐位体前屈
count591.000000591.000000591.000000591.000000591.000000591.000000
mean156.00338446.7834182333.23350310.792014166.8257199.496616
std7.3894105.031473350.4361541.31087316.8135872.938186
min135.00000016.0000001450.0000007.80000052.0000000.500000
25%151.00000044.0000002109.0000009.800000156.0000007.800000
50%157.00000047.0000002391.00000010.700000167.0000009.600000
75%161.00000050.0000002570.00000011.500000178.00000011.600000
max171.00000065.0000003272.00000015.000000205.00000017.500000
相关系数矩阵图
pd.plotting.scatter_matrix(data, figsize=(20,10), alpha=0.75)
plt.show()

在这里插入图片描述

相关系数矩阵
cor = data.corr()  # 默认method='pearson'
cor
身高体重肺活量50米跑立定跳远坐位体前屈
身高1.00000.0665-0.2177-0.19200.04400.0951
体重0.06651.00000.09540.06850.0279-0.0161
肺活量-0.21770.09541.00000.28980.0248-0.0749
50米跑-0.19200.06850.28981.0000-0.0587-0.0019
立定跳远0.04400.02790.0248-0.05871.0000-0.0174
坐位体前屈0.0951-0.0161-0.0749-0.0019-0.01741.0000
import seaborn as sns
sns.set(font='SimHei')  # 支持中文显示
可视化矩阵
fig, ax = plt.subplots(figsize = (10,10))

# cor:相关系数矩阵
# cmap:颜色
# xticklabels:显示x轴标签
# yticklabels:显示y轴标签
# annot:方块中显示数据
# square:方块为正方形

sns.heatmap(cor, cmap='YlGnBu', xticklabels=True, yticklabels=True,
            annot=True, square=True)
<matplotlib.axes._subplots.AxesSubplot at 0x1c772aa7e88>

在这里插入图片描述

相关系数的假设检验

第一步:提出原假设和 H 0 H_0 H0和备择假设 H 1 H_1 H1;假设已得到一个皮尔逊相关系数 r r r要想检验它是否显著的异于0,可以设定: H 0 : r = 0 , H 1 : r ≠ 0 H_0:r=0,H_1:r{\ne}0 H0r=0H1r=0
第二步:在原假设成立的条件下,利用要检验的量构造出一个符合某一分布的统计量。对于皮尔逊相关系数 r r r而言,可以构造统计量:
t = r n − 2 1 − r 2 t=r\sqrt{\frac{n-2}{1-r^2}} t=r1r2n2
可以证明, t t t是服从自由度为 n − 2 n-2 n2 t t t分布。
第三步:将要检验的值带入这个统计量中,可以得到一个特性的值。假设计算出的相关系数为0.5,样本为30,则可以得到 t ∗ = 0.5 30 − 2 1 − 0. 5 2 = 3.05505 t^*=0.5\sqrt{\frac{30-2}{1-0.5^2}}=3.05505 t=0.510.52302 =3.05505
第四步:根据 t t t分布的定义可以得到置信水平为0.95的 t t t分布的置信区间。做比较即可。

from scipy import stats
np.set_printoptions(suppress=True)  # 不使用用科学计数法
pd.set_option('display.float_format',lambda x : '%.4f' % x)  # 保留小数点后4位有效数字
# 0.975分位数
tp = stats.t.isf(1-0.975, 28)
x = np.linspace(-5,5,100)
y = stats.t.pdf(x, 28)
plt.plot(x,y)
plt.vlines(-tp, 0, stats.t.pdf(-tp, 28), colors='orange')
plt.vlines(tp, 0, stats.t.pdf(tp, 28), colors='orange')
plt.fill_between(x, 0, y, where=abs(x)>tp, interpolate=True, color='r')
<matplotlib.collections.PolyCollection at 0x1c7054dd9c8>

在这里插入图片描述

更简便的方法:求p值
# 自定义求解p值矩阵的函数
def my_pvalue_pearson(x):
    col = x.shape[1]
    col_name = x.columns.values
    p_val = []
    for i in range(col):
        for j in range(col):
            p_val.append(stats.pearsonr(x[col_name[i]], x[col_name[j]])[1])
    p_val = pd.DataFrame(np.array(p_val).reshape(col, col), columns=col_name, index=col_name)
    p_val.to_csv('p_val_pearson.csv')  # 此处实则为多此一举,目的是借助带有excel格式的数据使得输出更美观
    p_val = pd.read_csv('p_val_pearson.csv', index_col=0)
    return p_val
my_pvalue_pearson(data)
身高体重肺活量50米跑立定跳远坐位体前屈
身高0.00000.10610.00000.00000.28590.0208
体重0.10610.00000.02040.09600.49780.6963
肺活量0.00000.02040.00000.00000.54690.0687
50米跑0.00000.09600.00000.00000.15420.9637
立定跳远0.28590.49780.54690.15420.00000.6728
坐位体前屈0.02080.69630.06870.96370.67280.0000

将p值与0.05做比较即可

正态分布检验
Jarque-Bera检验(n>30)
x = stats.norm.rvs(2, 3, 100)    
skewness = stats.skew(x)  # 偏度
kurtosis = stats.kurtosis(x)  # 峰度
jbtext = stats.jarque_bera(x)
print('偏度为:',skewness)
print('峰度为:',kurtosis)
print('J-B值:',jbtext[0])
print('p-value:',jbtext[1])
偏度为: 0.05657245566213502
峰度为: -0.135509867406316
J-B值: 0.1298528963460595
p-value: 0.9371363889360985
def my_jbtext(x):
    col_name = x.columns.values
    col_cnt = x.shape[1]
    h_mat = np.zeros(col_cnt)
    p_mat = np.zeros(col_cnt)
    for i in range(col_cnt):
        p_val = stats.jarque_bera(data[col_name[i]])[1]
        p_mat[i] = p_val
        if p_val >= 0.05:
            h_mat[i] = 0  # 通过原假设
        else:
            h_mat[i] = 1  # 拒绝原假设
    print(h_mat)
    print(p_mat)  # 各列的p值
my_jbtext(data)
[1. 1. 1. 1. 1. 1.]
[0.00602083 0.         0.00853    0.         0.         0.03949912]

1代表拒绝原假设,0代表接受

Shapiro-wilk检验(3<=n<=50)
stats.shapiro(data['身高'])  # 单个变量
(0.9839125275611877, 4.196843292447738e-06)
def my_shaptext(x):
    col_name = x.columns.values
    col_cnt = x.shape[1]
    h_mat = np.zeros(col_cnt)
    p_mat = np.zeros(col_cnt)
    for i in range(col_cnt):
        p_val = stats.shapiro(data[col_name[i]])[1]
        p_mat[i] = p_val
        if p_val >= 0.05:
            h_mat[i] = 0  # 通过原假设
        else:
            h_mat[i] = 1  # 拒绝原假设
    print(h_mat)
    print(p_mat)  # 各列的p值
my_shaptext(data)
[1. 1. 1. 1. 1. 1.]
[0.0000042  0.         0.00000207 0.         0.         0.00005767]
Q-Q图(大样本时使用)
stats.probplot(data['身高'], dist="norm", plot=plt)
plt.show()

在这里插入图片描述

斯皮尔曼相关系数

定义: X X X Y Y Y为两组数据,其斯皮尔曼相关系数:
r s = 1 − 6 ∑ i = 1 n d i 2 n ( n 2 − 1 ) r_s=1-\frac{6\sum_{i=1}^n{d_{i}^{2}}}{n\left( n^2-1 \right)} rs=1n(n21)6i=1ndi2
其中, d i d_i di X i X_i Xi Y i Y_i Yi之间的等级差。(一个数的等级是指,将其所在的一列数按照从小到大的顺序排列后,这个数作在的位置;若有相同的数值,则他们的等级为所在位置的算数平均)
可以证明: r s r_s rs位于 − 1 -1 1 1 1 1之间。

data.corr(method='spearman')
身高体重肺活量50米跑立定跳远坐位体前屈
身高1.00000.0301-0.2430-0.19900.06240.1099
体重0.03011.00000.13050.08980.0216-0.0488
肺活量-0.24300.13051.00000.26260.0219-0.0801
50米跑-0.19900.08980.26261.0000-0.0910-0.0029
立定跳远0.06240.02160.0219-0.09101.0000-0.0399
坐位体前屈0.1099-0.0488-0.0801-0.0029-0.03991.0000

斯皮尔曼相关系数的假设检验

# 自定义求解p值矩阵的函数
def my_pvalue_spearman(x):
    col = x.shape[1]
    col_name = x.columns.values
    p_val = []
    for i in range(col):
        for j in range(col):
            p_val.append(stats.spearmanr(x[col_name[i]], x[col_name[j]])[1])
    p_val = pd.DataFrame(np.array(p_val).reshape(col, col), columns=col_name, index=col_name)
    p_val.to_csv('p_val_spearman.csv')  # 此处实则为多此一举,目的是借助带有excel格式的数据使得输出更美观
    p_val = pd.read_csv('p_val_spearman.csv', index_col=0)
    return p_val
my_pvalue_spearman(data)
身高体重肺活量50米跑立定跳远坐位体前屈
身高0.00000.46470.00000.00000.12950.0075
体重0.46470.00000.00150.02900.59960.2362
肺活量0.00000.00150.00000.00000.59440.0517
50米跑0.00000.02900.00000.00000.02700.9436
立定跳远0.12950.59960.59440.02700.00000.3330
坐位体前屈0.00750.23620.05170.94360.33300.0000
斯皮尔曼相关系数和皮尔逊相关系数的选择:

1.连续数据,正态分布,线性关系,用pearson相关系数是最恰当,当然用spearman相关系数也可以, 就是效率没有pearson相关系数高。
2.上述任一条件不满足,就用spearman相关系数,不能用pearson相关系数。
3.两个定序数据之间也用spearman相关系数,不能用pearson相关系数。
定序数据是指仅仅反映观测对象等级、顺序关系的数据,是由定序尺度计量形成的,表现为类别,可以进行排序,属于品质数据。
例如:优、良、差;
我们可以用1表示差、 2表示良、 3表示优,但请注意,用2除以1得出的2并不
代表任何含义。定序数据最重要的意义代表了一组数据中的某种逻辑顺序。
注:斯皮尔曼相关系数的适用条件比皮尔逊相关系数要广,只要数据满足单调关系
(例如线性函数、指数函数、对数函数等)就能够使用。

  • 12
    点赞
  • 136
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2012年数学建模比赛的葡萄酒原题,可以用Python语言进行求解。Python是一种高级编程语言,它具有简洁易懂的语法和强大的数学计算库,非常适合用于数学建模方面的问题。 首先,我们需要读取提供的数据文件,包括葡萄酒的各项指标和评价结果。可以使用Python的文件读取函数来完成这个任务,并将数据存储在适当的数据结构中,比如列表或字典。 接下来,我们需要对葡萄酒的指标进行分析和处理。可以使用Python的数学计算库,如NumPy或Pandas,进行数据分析和统计。我们可以计算葡萄酒的平均值、标准差、最大值、最小值等指标,以及进行相关性分析等。 然后,我们可以根据指标和评价结果之间的关系,建立数学模型。根据原题的要求,可以选择线性回归、多项式回归或其他适合的模型来进行建模。Python拥有丰富的机器学习库,如Scikit-Learn,可以使用这些库来建立模型,并进行模型的训练和预测。 最后,我们可以使用模型对新的葡萄酒数据进行评价。根据模型的训练结果,我们可以预测新葡萄酒的评价结果。同时,我们可以对模型的准确性进行评估,比如计算模型的均方差、R平方值等。 总之,通过使用Python语言,我们可以对2012年数学建模比赛的葡萄酒原题进行全面的分析和建模,并对新的数据进行预测和评估。Python的强大功能和易用性使得数学建模过程更加简单和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值