Skip to content

Files

Latest commit

03035da · Jan 9, 2022

History

History
600 lines (437 loc) · 28.3 KB

08.md

File metadata and controls

600 lines (437 loc) · 28.3 KB

七、联合统计

在第 6 章中,我们探索了可视化两个变量之间关联的方法。在本章中,我们将通过讨论描述二元关联的统计过程来补充这些分析。本章包括一些最常见的推断统计:相关、回归、两个样本和配对观察的 t 检验、方差的单因素分析、比较多个比例的检验以及独立性的卡方检验。

相关性

相关性是统计分析的支柱。r 提供了几种关联方法,外部包提供了几乎无限的过程选择。在本节中,我们将从 R 中的默认相关函数cor()开始。我们将使用 R 的datasets包中的swiss数据。该数据包含 1888 年瑞士 47 个法语省份的生育率和社会经济变量。(详见?swiss。)

样本:样本 _7_1。R

          # LOAD DATA
          require(“datasets”)  # Load the datasets package.
          data(swiss)

一旦数据加载到 R 中,我们就可以简单地对整个数据帧调用cor()函数。另外,为了使打印输出不那么繁忙,我们可以用round()函数包装cor()函数,将输出四舍五入到两位小数。

          # CORRELATION MATRIX
          cor(swiss)
          round(cor(swiss), 2)  # Rounded to 2 decimals

该输出的前几行和前几列是:

                           Fertility Agriculture Examination Education Catholic
          Fertility             1.00        0.35       -0.65     -0.66     0.46
          Agriculture           0.35        1.00       -0.69     -0.64     0.40

打印输出中缺少概率值。r 没有内置函数来获取相关矩阵的 p 值,甚至没有星号来表示统计意义。相反,我们可以用cor.test()分别测试每个相关性。这个函数将给出相关值、假设检验和相关的置信区间。

          # INFERENTIAL TEST FOR SINGLE CORRELATION
          cor.test(swiss$Fertility, swiss$Education)

                  Pearson's product-moment correlation
          data:  swiss$Fertility and swiss$Education
          t = -5.9536, df = 45, p-value = 3.659e-07
          alternative hypothesis: true correlation is not equal to 0
          95 percent confidence interval:
           -0.7987075 -0.4653206
          sample estimates:
                 cor
          -0.6637889

这是有用的信息,但是一次测试一个相关性是很麻烦的。外包装Hmisc提供了一个替代方案,可以一次得到两个矩阵:一个矩阵有相关值,第二个矩阵有双尾 p 值。第一步是安装加载Hmisc包。

          # INSTALL AND LOAD "HMISC" PACKAGE
          install.packages("Hmisc")
          require("Hmisc")

当您加载Hmisc时,您将收到消息,R 也在加载其他几个包— gridlatticesurvivalsplinesFormulaHmisc所依赖的包。您可能还会收到一条消息,一些功能,如format.pvalround.POSIXttrunc.POSIXtunits,被package:base屏蔽了。发生这种情况是因为Hmisc暂时覆盖了那些功能,这是应该发生的,所以你可以忽略那些消息。

然而,在我们可以从Hmisc运行rcorr()功能之前,我们需要对我们的数据进行更改。swiss数据是一个数据帧,但Hmisc对矩阵进行操作。我们所需要做的就是用as.matrix()函数包装swiss,然后可以将其嵌套在rcorr()中。

          # COERCE DATA FRAME TO MATRIX
          # GET R & P MATRICES
          rcorr(as.matrix(swiss))

以下是每个结果矩阵的前几行和前几列。第一个矩阵由相关系数组成,与我们从 R 的cor()函数得到的舍入矩阵相同。

                           Fertility Agriculture Examination Education Catholic
          Fertility             1.00        0.35       -0.65     -0.66     0.46
          Agriculture           0.35        1.00       -0.69     -0.64     0.40

第二个矩阵由双尾概率值组成,对角线上有空格:

          P
                           Fertility Agriculture Examination Education Catholic
          Fertility                  0.0149      0.0000      0.0000    0.0010  
          Agriculture      0.0149                0.0000      0.0000    0.0052

使用pT2【05】的标准标准,所有这些相关性都具有统计学意义。

有关Hmisc的更多信息,请输入help(package = "Hmisc")。和以前一样,当我们完成时,我们应该卸载外部包并清除我们创建的任何变量或对象。

          # CLEAN UP
          detach("package:datasets", unload=TRUE)  # Unload the package.
          detach("package:Hmisc", unload=TRUE)  # Unload the package.
          rm(list = ls())  # Remove the objects.

二元回归

二元回归——即两个变量之间的线性回归——是一个非常常见、灵活和强大的过程。r 具有优秀的二元回归内置函数,可以提供大量信息。

对于这个例子,我们将使用来自 R 的datasets包的trees数据。(详见?trees。)

样品:样品 _7_2。R

          # LOAD DATA
          require(“datasets”)  # Load the datasets package.
          data(trees)  # Load data into the workspace.
          trees[1:5, ]  # Show the first 5 lines.
            Girth Height Volume
          1   8.3     70   10.3
          2   8.6     65   10.3
          3   8.8     63   10.2
          4  10.5     72   16.4
          5  10.7     81   18.8

我们将使用二元回归来看看一棵树的周长如何预测它的高度。但是首先,用图形检查变量总是一个好主意,看看它们在多大程度上符合我们预期过程的假设。

          # GRAPHICAL CHECK
          hist(trees$Height)
          hist(trees$Girth)
          plot(trees$Girth, trees$Height)

为了节省空间,我不会在这里打印这些图表,但我会提到,这两个变量近似正态分布,围长有一些正偏斜,散点图看起来近似线性。这些变量似乎非常适合回归分析。

线性回归的命令是lm()。它只需要两个参数:结果变量和预测变量,中间带有颚化符操作符~。在这个例子中,它显示为lm(Height ~ Girth, data = trees)。这里的第三个参数data = trees,是可选的。它用于指定从中提取变量的数据集。需要注意的是,也可以给出每个变量的完整地址,如trees$Heighttrees$Girth。单独的data声明只是为了方便。

在这个例子中,我将回归模型保存到 reg1 中。通过将模型保存到一个对象中,我就能够在模型上调用几个函数,而不必再次指定它。在接下来的代码中,我首先运行 l m(),然后用summary()获取模型的信息。

          # BASIC REGRESSION MODEL
          reg1 <- lm(Height ~ Girth, data = trees)  # Save the model.
          summary(reg1)  # Get regression output.
          Call:
          lm(formula = Height ~ Girth, data = trees)

          Residuals:
               Min       1Q   Median       3Q      Max
          -12.5816  -2.7686   0.3163   2.4728   9.9456

          Coefficients:
                      Estimate Std. Error t value Pr(>|t|)   
          (Intercept)  62.0313     4.3833  14.152 1.49e-14 ***
          Girth         1.0544     0.3222   3.272  0.00276 **
          ---
          Signif. codes:  0***0.001**0.01*0.05.0.1 ‘ ’ 1

          Residual standard error: 5.538 on 29 degrees of freedom
          Multiple R-squared:  0.2697,   Adjusted R-squared:  0.2445
          F-statistic: 10.71 on 1 and 29 DF,  p-value: 0.002758

summary()函数给出了大多数分析所需的几乎所有信息:回归系数、它们的统计显著性、整个模型的 R 2 和调整后的 R 2F 值和 p 值,以及关于残差的信息。(详见?lm?summary。)

也可以用confint()函数得到回归系数的置信区间:

          # CONFIDENCE INTERVALS
          confint(reg1)
                           2.5 %    97.5 %
          (Intercept) 53.0664541 70.996174
          Girth        0.3953483  1.713389

评估回归模型时可能有用的其他函数有:

  • predict(),给出预测器上不同值的结果变量的预测值(见?predict)。
  • lm.influence(),给出了用于形成各种诊断的基本量,以检查回归拟合的质量(参见?lm.influence)。
  • influence.measures(),给出残差、离差、帽子值等信息(见?influence.measures)。

我们可以通过卸载包装和清洁工作区来完成:

          # CLEAN UP
          detach("package:datasets", unload = TRUE)  # Unloads data sets package.
          rm(list = ls())  # Remove all objects from workspace.

双样本 t 检验

如果你想比较两个不同组的平均值,那么最常见的选择是双样本 t 检验。r 为这个测试提供了几个选项和几种组织数据进行分析的方法。在这个例子中,我们将使用来自 R 的datasets包的sleep数据。这个数据集是由 t 检验的创造者威廉·戈塞特收集的,他以化名“学生”发表了这篇文章,显示了两种催眠药物对 10 名患者的效果。数据集有三列:extra,是睡眠时间的增加;group,表示给药;还有ID,也就是患者 ID。为了使分析更简单,我们将打开数据,删除 ID 变量,并将其保存为名为sd的新数据框,用于“睡眠数据”

样品:样品 _7_3。R

          # LOAD DATA & SELECT VARIABLES
          require(“datasets”)  # Load the datasets package.
          sleep[1:5, ]  # Show the first 5 cases.
          sd <- sleep[, 1:2]  # Save just the first two variables.
          sd[1:5, ]  # Show the first 5 cases.

一旦数据被加载到新的数据框中,我们就可以创建一些基本的图表,一个直方图和一个箱线图,来检查分布的形状以及它在多大程度上符合 t 检验的统计假设。

          # GRAPHICAL CHECKS
          hist(sd$extra)  # Histogram of extra sleep.
          boxplot(extra ~ group, data = sd)  # Boxplots by group.

为了节省空间,我不会在这里重新打印图形,但我会说直方图是近似正常的,用组分隔的箱线图不会显示任何异常值。完成这一初步检查后,我们可以使用 R 的t.test()功能进行默认 t 检验。

          # TWO-SAMPLE T-TEST WITH DEFAULTS
          t.test(extra ~ group, data = sd)
                  Welch Two Sample t-test
          data:  extra by group
          t = -1.8608, df = 17.776, p-value = 0.07939
          alternative hypothesis: true difference in means is not equal to 0
          95 percent confidence interval:
           -3.3654832  0.2054832
          sample estimates:
          mean in group 1 mean in group 2
                     0.75            2.33

这些结果表明,尽管两组的平均值之间存在差异(2.33 vs. 0.75),但这种差异并不符合统计学显著性的常规水平,因为观察到的 p 值 0.08 大于标准的 0.05 临界值。值得注意的是,默认情况下,R 使用韦尔奇双样本 t 检验,这通常用于方差不相等的样本。这种选择的一个结果是自由度是一个小数值,在这种情况下是 17.776。对于更常见的等方差 t 检验,只需在函数调用中添加参数var.equal = TRUE(更多信息请参见?t.test)。

r 的t.test()函数还提供了许多选项,比如单尾测试和不同的置信水平,如下面的代码所示。

          # TWO-SAMPLE T-TEST WITH OPTIONS
          t.test(extra ~ group,  # Same: Specifies variables.
                 data = sd,  # Same: Specifies data set.
                 alternative = "less",  # One-tailed test.
                 conf.level = 0.80)  # 80% CI (vs. 95%)

                  Welch Two Sample t-test
          data:  extra by group
          t = -1.8608, df = 17.776, p-value = 0.0397
          alternative hypothesis: true difference in means is less than 0
          80 percent confidence interval:
                 -Inf -0.8478191
          sample estimates:
          mean in group 1 mean in group 2
                     0.75            2.33

不出所料,当对同一数据进行单尾或方向假设检验时,结果具有统计学意义,p 值为. 04(正好是双尾检验 p 值的一半)。

在前面关于睡眠数据的例子中,结果变量在一列,分组变量在第二列。但是,也可以将每个组的数据放在单独的列中。在下面的例子中,我们将使用 R 的rnorm()函数创建模拟数据,该函数从正态分布中提取数据。使用模拟数据的一个优点是可以精确地指定各组之间的差异。还需要注意的是,每次运行代码时,本例中的数据都会略有不同,因此您的结果不应该与这些完全匹配。

在这种情况下,两个组的数据在差异变量中,函数调用更简单:只需将两个变量的名称作为参数给t.test(),如下代码所示。

          # SIMULATED DATA IN TWO VARIABLES
          x <- rnorm(30, mean = 20, sd = 5)
          y <- rnorm(30, mean = 24, sd = 6)
          t.test(x, y)

                  Welchs Two Sample t-test
          data:  x and y
          t = -2.6208, df = 56.601, p-value = 0.01124
          alternative hypothesis: true difference in means is not equal to 0
          95 percent confidence interval:
           -6.8721567 -0.9186296
          sample estimates:
          mean of x mean of y
           20.18359  24.07898

这种情况下的结果表明,p 值为. 01 时,差异具有统计学意义。最后,我们应该通过删除本节中使用的包和对象来整理。

          # CLEAN UP
          detach("package:datasets", unload = TRUE)  # Unloads data sets package.
          rm(list = ls())  # Remove all objects from workspace.

配对 t 检验

t 检验是一种灵活的检验,有几种变化。在前一节中,我们使用 t 检验来比较两组的平均值。在本节中,我们将使用 t 检验来检查一组受试者的分数如何随时间变化。这被称为配对 t 检验,因为每个参与者在时间 2 的观察与他们自己在时间 1 的观察是配对的。配对 t 检验也称为匹配受试者 t 检验或受试者内 t 检验。

在这个例子中,我们将使用模拟数据。在下面的代码中,使用rnorm()函数为时间 1 创建了一个名为t1的变量,以生成具有指定平均值和标准偏差的正态分布数据(更多信息请参见?rnorm)。为了模拟随时间的变化,生成了另一个随机变量,称为差异的dif。然后将这两个变量相加得出t2,即每个科目在时间 2 的分数。

样品:样品 _7_4。R

          # CREATE SIMULATED DATA
          t1 <- rnorm(50, mean = 52, sd = 6)  # Time 1
          dif <- rnorm(50, mean = 6, sd = 12)  # Difference
          t2 <- t1 + dif  # Time 2

一旦产生数据,就可以调用t.test()函数。这种情况下的自变量是两次有数据的变量,还有paired = TRUE,说明应该采用配对 t 检验。

          # PAIRED T-TEST WITH DEFAULTS
          t.test(t2, t1, paired = TRUE)  # Must specify "paired"

                  Paired t-test
          data:  t2 and t1
          t = 4.457, df = 49, p-value = 4.836e-05
          alternative hypothesis: true difference in means is not equal to 0
          95 percent confidence interval:
            4.078233 10.775529
          sample estimates:
          mean of the differences
                         7.426881

在这个例子中,分数随时间的变化具有统计学意义。请注意,您自己的结果会有所不同,因为数据是随机生成的。这种效果可以在下面的代码中看到,如果 t-test 用几个选项再次运行:指定非零的 null 值,调用单尾测试,并使用不同的置信水平。本例中的平均差异较小(5.81 vs. 7.43),因为数据是在运行此代码之前再次生成的。

          # PAIRED T-TEST WITH OPTIONS
          t.test(t2, t1,
                 paired = TRUE,
                 mu = 6,  # Specify a non-0 null value.
                 alternative = "greater",  # One-tailed test
                 conf.level = 0.99)  # 99% CI (vs. 95%)

                  Paired t-test
          data:  t2 and t1
          t = -0.1027, df = 49, p-value = 0.5407
          alternative hypothesis: true difference in means is greater than 6
          99 percent confidence interval:
           1.529402      Inf
          sample estimates:
          mean of the differences
                         5.816891

在这种情况下,差异在统计上并不显著,但这主要是由于使用了不同的空值(6 与 0),而不是数据的变化。

我们可以通过清理工作区来完成。

          # CLEAN UP
          rm(list = ls())  # Remove all objects from the workspace.

单因素方差分析

单因素方差分析,或称方差分析,用于比较几个不同组在单个定量结果变量上的平均值。在这个例子中,我们将再次使用来自 R 的rnorm()函数的模拟数据。和以前一样,这意味着您的数据会略有不同,但总体模式应该是相同的。在为每个组创建了一个变量的四个变量之后,使用data.frame()cbind()函数将它们组合成一个数据框。之后,数据需要重新组织。然后,这四个独立的变量通过stack()函数堆叠成一个名为values的结果变量,该函数还创建了一个名为ind的列来指示它们的源变量;该变量用作分组变量。

样本:样本 _7_5。R

          # CREATE SIMULATION DATA
          # Step 1: Each group in a separate variable.
          x1 <- rnorm(30, mean = 40, sd = 8)  # Group 1, mean = 40
          x2 <- rnorm(30, mean = 41, sd = 8)  # Group 1, mean = 41
          x3 <- rnorm(30, mean = 44, sd = 8)  # Group 1, mean = 44
          x4 <- rnorm(30, mean = 45, sd = 8)  # Group 1, mean = 45

          # Step 2: Combine vectors into a single data frame.
          xdf <- data.frame(cbind(x1, x2, x3, x4))  # xdf = "x data frame"

          # Step 3: Stack data to get the outcome column and group column.
          xs <- stack(xdf)  # xs = "x stack"

此时,数据已准备好用 R 的aov()函数进行分析。默认规范很简单,只有两个必需的参数:结果变量,在这种情况下是values,分组变量,在这种情况下是ind。这两个变量由波浪符~连接。(参数data = xs只是表示保存变量的数据框。)

          # ONE-FACTOR ANOVA
          anova1 <- aov(values ~ ind, data = xs)  # Basic model.
          summary(anova1)  # Model summary.

                       Df Sum Sq Mean Sq F value Pr(>F) 
          ind           3    579  192.97   3.188 0.0264 *
          Residuals   116   7022   60.53                
          ---
          Signif. codes:  0***0.001**0.01*0.05.0.1 ‘ ’ 1

这些结果表明,方差的综合分析具有统计学意义,p 值为. 03。然而,这个测试并不能表明群体差异在哪里。要找到它们,我们需要事后比较。R 中默认的事后程序是图基的诚实显著差异测试或TukeyHSD()【19】因为我们将方差分析模型保存到了一个名为 anova1 的对象中,所以我们可以在下面的代码中使用该对象作为参数:

          # POST-HOC COMPARISONS
          TukeyHSD(anova1)

            Tukey multiple comparisons of means
              95% family-wise confidence level
          Fit: aov(formula = values ~ ind, data = xs)

          $ind
                     diff        lwr       upr     p adj
          x2-x1  1.132450 -4.1039279  6.368829 0.9425906
          x3-x1  5.502549  0.2661705 10.738927 0.0354399
          x4-x1  4.004412 -1.2319658  9.240791 0.1964255
          x3-x2  4.370098 -0.8662799  9.606477 0.1362299
          x4-x2  2.871962 -2.3644162  8.108340 0.4835521
          x4-x3 -1.498136 -6.7345146  3.738242 0.8782931

TukeyHSD()函数报告观察到的配对组之间的差异,以及置信区间和调整后 p 值的下限和上限。在这种特殊情况下,有趣的是第 1 组和第 3 组之间唯一有统计学意义的差异。这令人惊讶,因为生成随机数据的命令实际上要求组 1 和组 4 之间有更大的差异。然而,考虑到随机数据生成的变迁,这样的怪癖是意料之中的。这也表明每组 30 分的样本量可能不足以给出稳定的结果。【20】在未来的研究中,至少将样本量增加一倍是有益的。

我们可以通过清理在本练习中生成的变量和对象的工作空间来完成。

          # CLEAN UP
          rm(list = ls())  # Remove all objects from workspace

比较比例

在我们检查的最后五个程序中——相关性、回归、双样本 t 检验、配对 t 检验和方差分析——结果变量是定量的(即测量的区间或比率水平)。这使得计算平均值和标准偏差成为可能,然后用于推理测试。然而,在某些情况下,结果变量是分类的(即,标称的或可能是序数的测量水平。)本章的最后两部分讨论了这些情况。在一个二分结果的情况下,也就是说,一个结果只有两个可能的值,如是或否,开或关,点击或不点击,那么比例测试可以是一个比较两个或更多组的表现的理想方式。

在这个例子中,我们将再次使用模拟数据。R 的prop.test()函数需要每组两个信息:试验的次数或总的观察值,通常称为 n,结果为正的试验的次数,通常称为 x,在下面的代码中,我使用 R 的rep()函数为试验的次数创建了一个名为n5的五个 100 的向量(更多信息请参见?rep)。然后创建第二个向量x5,其中包含每个组的阳性结果数。

样本:样本 _7_6。R

          # CREATE SIMULATION DATA
          # Two vectors are needed:
          # One specifies the total number of people in each group.
          # This creates a vector with 5 100s in it, for 5 groups.
          n5 <- c(rep(100, 5))
          # Another specifies the number of cases with positive outcomes.
          x5 <- c(65, 60, 60, 50, 45)

下一步是用两个参数调用 R 的prop.test()函数:带有 X 数据的变量和带有 n 数据的变量。

          # PROPORTION TEST
          prop.test(x5, n5)
                  5-sample test for equality of proportions without continuity
                  correction

          data:  x5 out of n5
          X-squared = 10.9578, df = 4, p-value = 0.02704
          alternative hypothesis: two.sided
          sample estimates:
          prop 1 prop 2 prop 3 prop 4 prop 5
            0.65   0.60   0.60   0.50   0.45

输出包括卡方检验(此处显示为 X 平方)和 p 值,在本例中,p 值低于. 05 的标准截止值。它还给出了观察到的样本比例。

在只有两个组被比较的情况下,R 也将给出组的比例之间的差异的置信区间。默认值为. 95,但可以通过conf.level参数进行更改。

          # CREATE SIMULATION DATA FOR 2 GROUPS
          n2 <- c(40, 40)  # 40 trials
          x2 <- c(30, 20)  # Number of positive outcomes
          # PROPORTION TEST FOR 2 GROUPS
          prop.test(x2, n2, conf.level = .80)  # With CI

                  2-sample test for equality of proportions with continuity
                  correction
          data:  x2 out of n2
          X-squared = 4.32, df = 1, p-value = 0.03767
          alternative hypothesis: two.sided
          80 percent confidence interval:
           0.09097213 0.40902787
          sample estimates:
          prop 1 prop 2
            0.75   0.50

在这种情况下,尽管样本相对较少,但样本比例之间的差异在统计上是显著的,如 p 值和置信区间所示。

我们可以通过清理工作区来完成。

          # CLEAN UP
          rm(list = ls())  # Remove all objects from the workspace.

交叉列表

我们将讨论的最后一个二元程序是交叉列表数据的卡方推断检验。在这个例子中,我们将使用来自 R 的datasets包的Titanic数据。该数据包含泰坦尼克号残骸的生存数据,按性别、年龄(儿童或成人)和乘客等级(1 st 、2 nd 、3 rd 或船员)细分。详见?Titanic。数据采用表格格式,当显示时,由四个 4 x 2 表格组成,尽管也可以使用ftable()功能将其显示为“平面”应急表格。

样本:样本 _7_7。R

          # LOAD DATA
          require(“datasets”)  # Load the datasets package.
          Titanic              # Show complete data in tables.
          ftable(Titanic)      # Display a "flat" contingency table.
                             Survived  No Yes
          Class Sex    Age                  
          1st   Male   Child            0   5
                       Adult          118  57
                Female Child            0   1
                       Adult            4 140
          2nd   Male   Child            0  11
                       Adult          154  14
                Female Child            0  13
                       Adult           13  80
          3rd   Male   Child           35  13
                       Adult          387  75
                Female Child           17  14
                       Adult           89  76
          Crew  Male   Child            0   0
                       Adult          670 192
                Female Child            0   0
                       Adult            3  20

虽然表格格式是存储和显示数据的一种方便的方式,但是我们需要为我们的分析重新构建数据,以便每个观察都有一行。我们可以使用我们在 sample_1_1 中看到的一串嵌套命令来实现这一点。r:

          # RESTRUCTURE DATA
          tdf <- as.data.frame(lapply(as.data.frame.table(Titanic),
                 function(x)rep(x, as.data.frame.table(Titanic)$Freq)))[, -5]
          tdf[1:5, ]  # Check the first five rows of data.
            Class  Sex   Age Survived
          1   3rd Male Child       No
          2   3rd Male Child       No
          3   3rd Male Child       No
          4   3rd Male Child       No
          5   3rd Male Child       No

对于这个例子,我们将只关注四个变量中的两个:ClassSurvived。为此,我们将使用table()函数创建一个精简的数据集,并将其保存到一个新对象中,即泰坦尼克号表的ttab

          # CREATE REDUCED TABLE
          ttab <- table(tdf$Class, tdf$Survived)  # Select two variables.
          ttab  # Show the new table.
                  No Yes
            1st  122 203
            2nd  167 118
            3rd  528 178
            Crew 673 212

原始频率很重要,但是通过查看行百分比更容易理解模式。我们可以通过使用prop.table()函数并请求第一列来获得这些。在下面的代码中,我还将这些命令包装在round()函数中,将输出减少到两位小数,然后乘以 100 得到百分比。

          # PERCENTAGES
          rowp <- round(prop.table(ttab, 1), 2) * 100 # row %
          colp <- round(prop.table(ttab, 2), 2) * 100 # column %
          totp <- round(prop.table(ttab), 2) * 100    # total %
          rowp
                 No Yes
            1st  38  62
            2nd  59  41
            3rd  75  25
            Crew 76  24

从这些结果可以清楚地看出,头等舱乘客的存活率要高得多,为 62%,而三等舱乘客和机组人员的存活率要低得多,分别为 25%和 24%。独立性的卡方检验,或称 R 的chisq.test()函数,可以根据无效假设检验这些结果:

          # CHI-SQUARED TEST FOR INDEPENDENCE
          tchi <- chisq.test(ttab)  # Compare two variables in ttab
          tchi
                  Pearson's Chi-squared test
          data:  ttab
          X-squared = 190.4011, df = 3, p-value < 2.2e-16

毫不奇怪,这些群体差异非常显著,p 值几乎为零。除了这个基本输出,R 还能够从保存的卡方对象中给出其他几个详细的表:

  • tchi$observed给出观测频率,与ttab中的数据相同。
  • tchi$expected给出零分布的预期频率。
  • tchi$residuals给出皮尔逊残差。
  • tchi$stdres根据残差单元方差给出标准化残差。

最后,我们可以在继续下一步之前卸载包并清除工作区。

          # CLEAN UP
          detach("package:datasets", unload = TRUE)  # Unloads the datasets package.
          rm(list = ls())  # Remove all objects from the workspace.