Python中的ANOVA测试

Python中的ANOVA测试

以下教程基于数据分析;我们将详细讨论 方差分析(ANOVA) ,以及在Python编程语言中进行方差分析的过程。ANOVA通常在 心理学 研究中使用。

在接下来的教程中,我们将了解如何利用 SciPy 库来进行ANOVA,并在Python中使用 PyyttblStatsmodels 进行 手动 评估。

了解ANOVA测试

我们可以将 方差分析 测试,也称为 ANOVA ,视为对多个组进行T检验的概括。通常情况下,我们使用独立的T检验来比较两组状态的均值。当我们需要比较两组以上状态的均值时,我们使用ANOVA测试。

ANOVA测试检查模型中的平均值是否存在差异(检查是否存在整体效应);然而,该方法并不告诉我们差异的位置(如果有差异的话)。我们可以通过进行事后检验来找出组之间的差异位置。

然而,为了进行任何测试,我们首先必须定义零假设和备择假设:

  1. 零假设: 组之间没有显著差异。
  2. 备择假设: 组之间存在显著差异。

我们可以通过比较两种变异来进行ANOVA测试。第一种变异是样本均值之间的变异,另一种是每个样本内的变异。下面显示的公式描述了单因素ANOVA测试统计量。

ANOVA公式的输出 F统计量 (也称为 F比率 ),可以用于分析多组数据以确定样本之间和样本内的变异性。

我们可以将单因素ANOVA测试的公式写成如下所示:

Python中的ANOVA测试

其中,

y i - 第 **i th ** 组的样本平均值

n i - 第 **i th ** 组的观察值数量

y – 数据的总平均值

k – 组的总数量

y ij - 第 **j th ** 个组之外的观察值

N – 总样本量

当我们制作ANOVA表时,可以以以下格式看到上述所有组成部分:

Python中的ANOVA测试

通常,如果F值对应的p值小于0.05,则可以排除零假设,维持备择假设。在零假设被拒绝的情况下,我们可以说所有组的均值不相等。

注意:如果被测试的组之间不存在真实差异,也就是被称为零假设,ANOVA测试的F比值将接近于1。

ANOVA测试的假设条件

在进行ANOVA测试之前,我们必须满足以下假设条件,如下所示:

  1. 我们可以随机独立地从由因素水平定义的总体中获取观察值。
  2. 每个因素水平的数据是普遍分布的。
  3. 独立性: 样本个案之间必须是相互独立的。
  4. 方差齐性: 齐性意味着组之间的方差大致相等。

我们可以通过类似Brown-Forsythe测试或Levene测试的帮助来测试方差齐性的假设。我们还可以通过直方图、峰度或偏度值,或者通过Kolmogorov-Smirnov、Shapiro-Wilk或Q-Q图等测试来测试评分分布的正态性。我们还可以从研究设计中确定独立性的假设。

值得注意的是,ANOVA测试在违反独立性假设时不具有鲁棒性。这意味着即使有人试图违反正态性或齐性的假设,他们仍然可以进行测试并信任结果。

然而,如果违反了独立性假设,ANOVA测试的结果是不可接受的。通常情况下,在我们有均等大小的组的情况下,即使存在齐性的违规,分析也被认为具有鲁棒性。如果样本量较大,即使存在正态性的违规,重新进行ANOVA测试通常也是可以接受的。

了解ANOVA测试的类型

ANOVA测试可以分为三种主要类型。这些类型如下所示:

  1. 单因素ANOVA测试
  2. 双因素ANOVA测试
  3. n因素ANOVA测试

单因素ANOVA测试

只有一个独立变量的方差分析测试被称为 单因素ANOVA测试

例如,一个国家可以评估冠状病毒病例的差异,而一个国家可以有多个用于比较的类别。

双因素ANOVA测试

具有两个独立变量的方差分析测试被称为 双因素ANOVA测试 。这个测试也被称为 因子方差分析测试

例如,扩展上面的示例,双向ANOVA可以考察 冠状病毒 (因变量)在 年龄组 (第一个自变量)和 性别 (第二个自变量)之间的差异。双向ANOVA可用于检查这两个自变量之间的交互作用。交互作用意味着差异在自变量的所有类别中不均匀存在。

假设 老年组 的冠状病毒病例总体上可能比 年轻组 更多;然而,这种差异可能在 欧洲 国家与 亚洲 国家之间存在差异。

n维ANOVA测试

如果研究人员使用了两个以上的自变量,那么方差分析(ANOVA)测试就被称为 n维ANOVA测试 。这里的n代表我们拥有的自变量数量。该测试也被称为 多元方差分析(MANOVA)测试

例如,我们可以同时使用诸如国家、年龄组、性别、种族等多个自变量来研究 冠状病毒 的潜在差异。

ANOVA测试将提供我们一个单一的(单变量)F值;然而,MANOVA测试将提供我们一个多元的F值。

理解ANOVA中的重复和非重复设计

通常,我们可能会听到关于ANOVA测试中的重复和非重复设计。让我们了解一下它们的含义:

带重复设计的双向ANOVA测试

带有重复设计的双向ANOVA测试是在两个组中进行多个任务操作的情况下进行的。

例如,假设冠状病毒疫苗仍在研发阶段。医生们正在对受感染的两组患者进行两种不同的治疗。

不带重复设计的双向ANOVA测试

在只有一个组的情况下进行不带重复设计的双向ANOVA测试,我们会对同一组进行两次测试。

例如,假设疫苗已成功研发,并且研究人员正在对一组志愿者进行疫苗接种前后的测试,以观察疫苗是否有效。

理解ANOVA后续测试

在进行ANOVA测试时,我们试图确定群体之间是否存在统计显著差异。如果存在,我们将需要测试差异的具体位置。

因此,研究人员使用事后检验来检查哪些群体之间存在差异。

我们可以进行事后检验,即t检验,检查群体之间的均值差异。我们可以进行多个多重比较测试以控制第一类错误率,包括Bonferroni、Dunnet、Scheffe和Turkey测试。

现在,我们将使用Python编程语言来解析仅涉及一元ANOVA测试。

使用Python理解一元ANOVA测试

我们将执行ANOVA测试的过程分为不同的部分。

导入所需的库

为了开始使用ANOVA测试,让我们导入一些项目所需的必要库和模块。

语法:

import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.formula.api import ols
import seaborn as sns
import numpy as np
import pandas.tseries
plt.style.use('fivethirtyeight')

假设

让我们考虑一个关于问题的假设:

“对于每一种饮食,人们的体重平均值是相同的。”

加载数据

在下面的问题中,我们将使用由谢菲尔德大学设计的一个饮食数据集。该数据集包含一个性别的二元变量,其中1表示男性,0表示女性。

让我们考虑以下相同的语法:

语法:

mydata = pd.read_csv('Diet_Dataset.csv')

了解数据集

成功导入数据集后,让我们打印一些数据以了解其情况。

示例

print(mydata.head())

输出:

   Person gender  Age  Height  pre.weight  Diet  weight6weeks
0      25          41     171          60     2          60.0
1      26          32     174         103     2         103.0
2       1      0   22     159          58     1          54.2
3       2      0   46     192          60     1          54.0
4       3      0   55     170          64     1          63.3

现在让我们打印出数据集中的总行数。

示例

print('The total number of rows in the dataset:', mydata.size)

输出:

The total number of rows in the dataset: 546

检查缺失值

现在,我们需要查看数据集中是否有任何缺失的值。我们可以使用以下语法来进行检查。

示例

print(mydata.gender.unique())
# displaying the person(s) having missing value in gender column
print(mydata[mydata.gender == ' '])

输出:

[' ' '0' '1']
   Person gender  Age  Height  pre.weight  Diet  weight6weeks
0      25          41     171          60     2          60.0
1      26          32     174         103     2         103.0

我们可以观察到’gender’列中有两个条目包含缺失值。现在让我们计算数据集中缺失值的总百分比。

示例

print('Percentage of missing values in the dataset: {:.2f}%'.format(mydata[mydata.gender == ' '].size / mydata.size * 100))

输出:

Percentage of missing values in the dataset: 2.56%

如我们所见,在数据集中大约有3%的缺失值。我们可以选择忽略、删除或者根据最接近的身高均值来分类性别。

理解体重的分布

在接下来的步骤中,我们将使用 distplot() 函数绘制一个图表,以了解样本数据中体重的分布情况。让我们考虑以下的代码片段。

示例

f, ax = plt.subplots( figsize = (11,9) )
plt.title( 'Weight Distributions among Sample' )
plt.ylabel( 'pdf' )
sns.distplot( mydata.weight6weeks )
plt.show()

输出:

Python中的ANOVA测试

我们还可以为数据集中的每个性别绘制分布图。以下是相应的语法:

示例

f, ax = plt.subplots( figsize = (11,9) )
sns.distplot( mydata[mydata.gender == '1'].weight6weeks, ax = ax, label = 'Male')
sns.distplot( mydata[mydata.gender == '0'].weight6weeks, ax = ax, label = 'Female')
plt.title( 'Weight Distribution for Each Gender' )
plt.legend()
plt.show()

输出:

Python中的ANOVA测试

我们还可以使用以下函数来显示每个性别的分布图。

示例:

def infergender(x):
    if x == '1': 
        return 'Male'

    if x == '0':
        return 'Female'

    return 'Other'

def showdistribution(df, gender, column, group):
    f, ax = plt.subplots( figsize = (11, 9) )
    plt.title( 'Weight Distribution for {} on each {}'.format(gender, column) )
    for groupmember in group:
        sns.distplot(df[df[column] == groupmember].weight6weeks, label='{}'.format(groupmember))
    plt.legend()
    plt.show()

uniquediet = mydata.Diet.unique()
uniquegender = mydata.gender.unique()

for gender in uniquegender:
    if gender != ' ':
        showdistribution(mydata[mydata.gender == gender], infergender(gender), 'Diet', uniquediet)

输出:

图表 1:

Python中的ANOVA测试

图表2:

Python中的ANOVA测试

现在,我们将根据下面给出的代码片段计算’gender’列的均值、中位数、非零计数和标准差:

示例

print(mydata.groupby('gender').agg(
    [ np.mean, np.median, np.count_nonzero, np.std ]
).weight6weeks)

输出:

             mean  median  count_nonzero        std
gender
        81.500000    81.5            2.0  30.405592
0       63.223256    62.4           43.0   6.150874
1       75.015152    73.9           33.0   4.629398

正如我们所观察到的,我们已经根据性别估计了所需的统计测量。我们还可以根据性别和饮食对这些统计测量进行分类。

示例

print(mydata.groupby(['gender', 'Diet']).agg(
    [np.mean, np.median, np.count_nonzero, np.std]
).weight6weeks)

输出:

                  mean  median  count_nonzero        std
gender Diet
       2     81.500000   81.50            2.0  30.405592
0      1     64.878571   64.50           14.0   6.877296
       2     62.178571   61.15           14.0   6.274635
       3     62.653333   61.80           15.0   5.370537
1      1     76.150000   75.75           10.0   5.439414
       2     73.163636   72.70           11.0   3.818448
       3     75.766667   76.35           12.0   4.434848

我们可以观察到饮食对女性的体重产生了轻微影响,但似乎对男性没有影响。

执行单因素方差分析检验

单因素方差分析的零假设为

Python中的ANOVA测试

并且这个测试尝试检查这个假设是否成立。

我们首先要考虑确定置信水平为95%,这也意味着我们只接受5%的错误率。

示例

mymod = ols('Height ~ Diet', data = mydata[mydata.gender == '0']).fit()
# performing type 2 anova test
aovtable = sm.stats.anova_lm(mymod, typ = 2)
print('ANOVA table for Female')
print('----------------------')
print(aovtable)
print()

mod = ols('Height ~ Diet', data = mydata[mydata.gender=='1']).fit()
# performing type 2 anova test
aovtable = sm.stats.anova_lm(mymod, typ = 2)
print('ANOVA table for Male')
print('----------------------')
print(aovtable)

输出:

ANOVA table for Female
----------------------
               sum_sq    df        F    PR(>F)
Diet       559.680764   1.0  7.17969  0.010566
Residual  3196.086677  41.0      NaN       NaN

ANOVA table for Male
----------------------
               sum_sq    df        F    PR(>F)
Diet       559.680764   1.0  7.17969  0.010566
Residual  3196.086677  41.0      NaN       NaN

在上面的输出中,我们可以观察到两个p值(PR (> F)):男性和女性。 对于男性来说,我们不能在95%的置信水平下接受零假设,因为p值大于alpha值,即0.05 < 0.512784。因此,在提供这三种类型的饮食后,男性的体重没有发现差异。 对于女性来说,由于p值PR (> F)低于错误率,即0.05 > 0.010566,我们可以拒绝零假设。这个陈述表明,我们对于女性在饮食方面的体重差异非常有信心。 因此,现在我们了解了饮食对女性的影响;然而,我们不清楚不同饮食之间的差异。因此,我们将利用图基HSD(Honest Significant Difference)测试进行事后分析。 让我们考虑以下代码片段。示例

from statsmodels.stats.multicomp import pairwise_tukeyhsd, MultiComparison
# using the female data only
mydf = mydata[mydata.gender == '0']

# comparing the height between each diet, using 95% confidence interval 
multiComp = MultiComparison(mydf['Height'], mydf['Diet'])
tukeyres = multiComp.tukeyhsd(alpha = 0.05)

print(tukeyres)
print('Unique diet groups: ', multiComp.groupsunique)

输出:

Multiple Comparison of Means - Tukey HSD, FWER=0.05
=====================================================
group1 group2 meandiff p-adj   lower    upper  reject
-----------------------------------------------------
     1      2  -3.5714 0.5437 -11.7861  4.6432  False
     1      3  -8.7714 0.0307  -16.848 -0.6948   True
     2      3     -5.2 0.2719 -13.2766  2.8766  False
-----------------------------------------------------
Unique diet groups:  [1 2 3]

如上所示,我们可以观察到,我们只能在第一种和第三种类型的饮食中拒绝零假设,这意味着饮食1和饮食3的体重存在统计学上的显著差异。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程