本作业内容来自Datawhale和GitModel,学习链接:https://github.com/Git-Model/Modeling-Universe/tree/main/Data-Story
感谢课程开发者的付出与贡献!
方法论与一元数值检验
1 问题描述
三台车床生产同一种滚珠,我们从中各抽取13、14、16个产品,测得直径分别为:
甲车床:15.0,14.5,15.2,15.5,14.8,15.1,15.2,14.8,13.9,16.0,15.1,14.5,15.2;
乙车床:15.2,15.0,14.8,15.2,15.0,15.0,14.8,15.1,14.8,15.0,13.7,14.1,15.5,15.9;
丙车床:14.6,15.0,14.7,13.9,13.8,15.5,15.5,16.2,16.1,15.3,15.4,15,9,15.2,16.0,14.8,14.9
假设显著性水平为𝛼=0.01,问:
- 甲/乙车床生产的滚珠直径是否服从正态分布?
- 甲/乙车床生产的滚珠直径的方差是否存在显著性差异?
- 甲/乙车床生产的滚珠直径是否存在显著性差异?
- 三台车床生产的滚珠直径是否存在显著性差异?在单因素方差分析中,本题的因素是什么?
2 问题解决
# 导入包
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
from IPython.display import display
# 创建数据
data1 = [15.0, 14.5, 15.2, 15.5, 14.8, 15.1, 15.2, 14.8, 13.9, 16.0, 15.1, 14.5, 15.2]
data2 = [15.2, 15.0, 14.8, 15.2, 15.0, 15.0, 14.8, 15.1, 14.8, 15.0, 13.7, 14.1, 15.5, 15.9]
data3 = [14.6, 15.0, 14.7, 13.9, 13.8, 15.5, 15.5, 16.2, 16.1, 15.3, 15.4, 15,9, 15.2, 16.0, 14.8, 14.9]
# Q1:甲/乙车床生产的滚珠直径是否服从正态分布?
# 分析思路:甲乙数据是数值型数据 > 一元数据 > 可利用正态性检验
# 单独画概率图
fig = plt.figure(figsize=(12,5))
ax1 = fig.add_subplot(1,2,1)
plot1 = stats.probplot(data1,plot=ax1)
ax2 = fig.add_subplot(1,2,2)
plot2 = stats.probplot(data2,plot=ax2)

# 两种正态性检验
from statsmodels.stats.diagnostic import lilliefors
from typing import List
def check_normality(data: np.ndarray, show_flag:bool=True) -> List[float]:
if show_flag:
_ = stats.probplot(data, plot=plt)
plt.show()
pVals = pd.Series(dtype='float64')
# D'Agostino's K-squared test
_, pVals['Omnibus'] = stats.normaltest(data)
# Shapiro-Wilk test
_, pVals['Shapiro-Wilk'] = stats.shapiro(data)
print(f'数据量为{len(data)}的数据集正态性假设检验的结果:')
print(pVals)
check_normality(data1,show_flag=True)

数据量为13的数据集正态性假设检验的结果:
Omnibus 0.487527
Shapiro-Wilk 0.717017
dtype: float64
D:\anaconda\envs\datanalysis\lib\site-packages\scipy\stats\stats.py:1542: UserWarning: kurtosistest only valid for n>=20 ... continuing anyway, n=13
"anyway, n=%i" % int(n))
check_normality(data2,show_flag=True)

数据量为14的数据集正态性假设检验的结果:
Omnibus 0.127615
Shapiro-Wilk 0.111537
dtype: float64
D:\anaconda\envs\datanalysis\lib\site-packages\scipy\stats\stats.py:1542: UserWarning: kurtosistest only valid for n>=20 ... continuing anyway, n=14
"anyway, n=%i" % int(n))
根据结果 p > α p>\alpha p>α,甲/乙车床服从正态分布
# Q2:甲/乙车床生产的滚珠直径的方差是否存在显著性差异?
# 分析思路:数值型数据 > 一元数值 > 样本的方差检验 > 方差齐性检验(levene检验)
pVal = pd.Series(dtype='float64')
confidence = 0.01
# 先进行两组数据的方差齐性检验
_,pVal['levene']=stats.levene(data1, data2)
# 检验-滚珠直径的方差是否存在显著性差异
if pVal['levene'] < confidence:
print('在显著性水平{0:}下,两组样本的方差不相等(p={1:.4f}),因此甲 / 乙车床生产的滚珠直径的方差存在显著性差异'.format(confidence, pVal['levene']))
else:
print('在显著性水平{0:}下,两组样本的方差相等(p={1:.4f}),因此甲 / 乙车床生产的滚珠直径的方差不存在显著性差异'.format(confidence, pVal['levene']))
在显著性水平0.01下,两组样本的方差相等(p=0.8656),因此甲 / 乙车床生产的滚珠直径的方差不存在显著性差异
根据结果 𝑝>𝛼 ,甲/乙车床生产的滚珠直径的方差不存在显著性差异
# Q3:甲/乙车床生产的滚珠直径是否存在显著性差异?
# 分析思路:数值型数据 > 一元数据 > 样本均值的检验 > 两组样本的均值相等性检验 > 组别间独立
def unpaired_data(data1:np.ndarray,data2:np.ndarray,confidence=0.01,alternative='two-sided'):
pVal = pd.Series(dtype='float64')
# 先进行两组数据的方差齐性检验
_,pVal['levene'] = stats.levene(data1,data2)
# t检验-若数据服从正态分布
if pVal['levene'] < confidence:
print('在显著性水平{0:}下,两组样本的方差不相等(p={1:.4f}),因此需要使用方差不等的t检验'.format(confidence,pVal['levene']))
print('---------------------')
_, pVal['t-test'] = stats.ttest_ind(data1, data2, equal_val=False, alternative=alternative)
print('t检验p值:{}'.format(pVal['t']))
else:
print('在显著性水平{0:}下,不能拒绝两组样本方差相等的假设(p={1:.4f}),因此需要使用方差相等的t检验'.format(confidence,pVal['levene']))
print('---------------------')
_, pVal['t-test'] = stats.ttest_ind(data1, data2,equal_var=True,alternative=alternative)
print('t检验p值:{:.3f}'.format(pVal['t-test']))
# mannwhitneyu检验-数据不服从正态检验
_, pVal['mannwhitneyu'] = stats.mannwhitneyu(data1, data2,alternative=alternative)
print('Mann-Whitney检验p值:{:.3f}'.format(pVal['mannwhitneyu']))
# --- >>> STOP stats <<< ---
# 两组样本均值的散点图可视化
print('------------------------------------')
print('两组样本均值的散点图可视化')
plt.plot(data1, 'bx', label='甲机床')
plt.plot(data2, 'ro', label='乙机床')
plt.legend(loc=0)
plt.show()
return pVal
unpaired_data(data1, data2)
在显著性水平0.01下,不能拒绝两组样本方差相等的假设(p=0.8656),因此需要使用方差相等的t检验
---------------------
t检验p值:0.811
Mann-Whitney检验p值:0.769
------------------------------------
两组样本均值的散点图可视化
D:\anaconda\envs\datanalysis\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 30002 (\N{CJK UNIFIED IDEOGRAPH-7532}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
D:\anaconda\envs\datanalysis\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 26426 (\N{CJK UNIFIED IDEOGRAPH-673A}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
D:\anaconda\envs\datanalysis\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 24202 (\N{CJK UNIFIED IDEOGRAPH-5E8A}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)
D:\anaconda\envs\datanalysis\lib\site-packages\IPython\core\pylabtools.py:151: UserWarning: Glyph 20057 (\N{CJK UNIFIED IDEOGRAPH-4E59}) missing from current font.
fig.canvas.print_figure(bytes_io, **kw)

levene 0.865593
t-test 0.810862
mannwhitneyu 0.768655
dtype: float64
因为t检验和mannwhitneyu检验的p值都远大于0.01,甲/乙车床不存在显著性差异
# Q4:三台车床生产的滚珠直径是否存在显著性差异?在单因素方差分析中,本题的因素是什么?
# 分析思路:数值型数据 > 一元数值数据 > 样本均值的检验 > 多组样本的均值相等性检验:方差分析(单因素)
# 定义一个单组样本均值检验函数,使它可以同时输出t检验与mannwhitneyu检验的p值
from typing import Tuple
def anova_oneway() -> Tuple[float, float]:
pVal=pd.Series(dtype='float64')
# 先做方差齐性检验
_,pVal['levene'] = stats.levene(data1, data2, data3)
if pVal['levene'] < 0.05: #这里假设显著性水平为0.05
print('警告: 方差齐性检验的p值小于0.05: p={},方差分析结果在小样本下可能不准确'.format(pVal['levene']))
print('-------------------------------')
# 单因素方差分析-假设样本服从正态分布
_, pVal['anova_oneway_normal'] = stats.f_oneway(data1, data2, data3) # 在这里输入待分析的数据
print('若样本服从正态分布,单因素方差分析的p值为{}'.format(pVal['anova_oneway_normal']))
if pVal['anova_oneway_normal'] < 0.05:
print('检验在0.05的显著性水平下显著,多组样本中至少存在一组样本均值与其它样本的均值不相等。')
print('---------------------------------')
# 单因素方差分析-假设样本不服从正态分布
_, pVal['anova_oneway_notnormal'] = stats.mstats.kruskalwallis(data1, data2, data3) # 在这里输入待分析的数据
print('若样本不服从正态分布,单因素方差分析的p值为{}'.format(pVal['anova_oneway_notnormal']))
if pVal['anova_oneway_notnormal'] < 0.05:
print('检验在0.05的显著性水平下显著,多组样本中至少存在一组样本均值与其它样本的均值不相等。')
return pVal
anova_oneway()
若样本服从正态分布,单因素方差分析的p值为0.8350931874298759
---------------------------------
若样本不服从正态分布,单因素方差分析的p值为0.8624406173813932
levene 0.221198
anova_oneway_normal 0.835093
anova_oneway_notnormal 0.862441
dtype: float64
因为检验的p值都远大于0.01,三台车床的生产都不存在显著性差异。因素:车床生产工艺具有一致性