R语言实战__第7章 基本统计分析

第7章 基本统计分析

在数据被组织成合适的形式后,可以使用图形探索数据,接下来是使用数值描述每个变量的分布,然后则是两两探索所选择变量之间的关系。
本章将评述用于生成基本的描述性统计量和推断统计量的R函数。

7.1 描述性统计分析

本节介绍分析连续型变量中心趋势、变化性和分布性的方法。
使用第1章中Motor Trend杂志的车辆路试(mtcars)数据集。重点关注每加仑汽油行驶英里数(mpg)、马力(hp)和车重(wt)。

> vars <- c("mpg", "hp", "wt")
> head(mtcars[vars])
> > #查看三个变量的数据
                   mpg  hp    wt
Mazda RX4         21.0 110 2.620
Mazda RX4 Wag     21.0 110 2.875
Datsun 710        22.8  93 2.320
Hornet 4 Drive    21.4 110 3.215
Hornet Sportabout 18.7 175 3.440
Valiant           18.1 105 3.460

将首先查看所有32中车型的描述性统计量,然后按照变速箱类型(am)和汽缸数(cyl)考察描述性统计量。变速箱类型是以0表示自动档、1表示手动档来编码的二分变量,汽缸数为4、5或6。

7.1.1 方法云集

在描述性统计量的计算方面,R中的选择非常多。从基础安装中包含的函数开始,然后查看那么些用户贡献包中的扩展函数。
集中安装中,可用summary( )函数获取描述性统计量。
代码清单7-1 通过summary( )计算描述性统计量

> #7-1 
> summary(mtcars[vars])
      mpg              hp              wt       
 Min.   :10.40   Min.   : 52.0   Min.   :1.513  
 1st Qu.:15.43   1st Qu.: 96.5   1st Qu.:2.581  
 Median :19.20   Median :123.0   Median :3.325  
 Mean   :20.09   Mean   :146.7   Mean   :3.217  
 3rd Qu.:22.80   3rd Qu.:180.0   3rd Qu.:3.610  
 Max.   :33.90   Max.   :335.0   Max.   :5.424  

summary( )函数提供了最小值、最大值、四分位数和数值型变量的均值,以及因子向量和逻辑型向量的频数统计。

第5章中的apply( )函数或sapply( )函数计算所选择的任意描述性统计量。对于sapply( )函数,使用格式为:
sapply(x, FUN, options)
其中x是数据框(或矩阵),FUN为一个任意函数。如果指定了options,它们将被传递给FUN。可以在这里插入的典型函数有mean、sd、var、min、median、length、range和quantile。函数fivenum( )可返回图基五数总括(即最小值、下四分位数、中位数、上四分位数和最大值)。

代码清单7-2 通过sapply( )计算描述性统计量

> mystats <- function(x, na.omit=FALSE) { #na.omit为0不移除缺失观测的整行
+              if (na.omit) 
+                x <- x[!is.na(x)] #如果存在缺失,则删除单个保留其他有效数据
+              m <- mean(x)  #均值
+              n <- length(x) #有效观测数
+              s <- sd(x)  #标准差
+              skew <- sum((x-m)^3/s^3)/n #偏度
+              kurt <- sum((x-m)^4/s^4)/n - 3 #峰度
+              return(c(n=n, mean=m, stdev=s, skew=skew, kurtosis=kurt))
+ }
> sapply(mtcars[vars], mystats)
               mpg          hp          wt
n        32.000000  32.0000000 32.00000000 #观测数
mean     20.090625 146.6875000  3.21725000 #均值
stdev     6.026948  68.5628685  0.97845744 #标准差
skew      0.610655   0.7260237  0.42314646 #偏度
kurtosis -0.372766  -0.1355511 -0.02271075 #峰度

样本中的车型,每加仑汽油行驶英里数的平均值为20.1,标准差为6.0。分布呈现右偏(偏度+0.61),并且较正态分布稍平(峰度-0.37)。
如果只希望单纯地忽略缺失值,应当使用:
sapply(mtcars[vars], mystats, na.omit=TRUE)

Himsc包中的describe( )函数可返回变量和观测的数量、缺失值和唯一值的数目、平均值、分位数,以及五个最大的值和五个最小的值。

代码清单7-3 通过Hmisc包中的describe( )函数计算描述性统计量

> library(Hmisc)
> describe(mtcars[vars])
mtcars[vars] 

 3  Variables      32  Observations
-----------------------------------------------------------------------------
mpg 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
      32        0       25    0.999    20.09    6.796    12.00    14.34 
     .25      .50      .75      .90      .95 
   15.43    19.20    22.80    30.09    31.30 

lowest : 10.4 13.3 14.3 14.7 15.0, highest: 26.0 27.3 30.4 32.4 33.9
-----------------------------------------------------------------------------
hp 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
      32        0       22    0.997    146.7    77.04    63.65    66.00 
     .25      .50      .75      .90      .95 
   96.50   123.00   180.00   243.50   253.55 

lowest :  52  62  65  66  91, highest: 215 230 245 264 335
-----------------------------------------------------------------------------
wt 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
      32        0       29    0.999    3.217    1.089    1.736    1.956 
     .25      .50      .75      .90      .95 
   2.581    3.325    3.610    4.048    5.293 

lowest : 1.513 1.615 1.835 1.935 2.140, highest: 3.845 4.070 5.250 5.345 5.424
-----------------------------------------------------------------------------

pastecs包中有一个名为stat..desc( )的函数,可以计算种类繁多的描述性统计量。使用格式为:
stat.desc(x, basic=TRUE, desc=TRUE, norm=FALSE, p=0.95)
其中的x是一个数据框或时间序列。若basic=TRUE(默认值),则计算其中所有值、空值、缺失值的数量,以及最小值、最大值、值域和综合。若desc=TRUE(默认值),则计算中位数、平均数、平均数的标准误差,平局数置信度为95%的置信区间、方差、标准差以及变异系数。若norm=TRUE(非默认),则返回正态分布的统计量,包括偏度和峰度(以及它们的统计显著程度)和Shapiro - Wilk正态检验结果。这里使用了p值来计算平均数的置信区间(默认为0.95)。

代码清单7-4 通过pastecs包中的stat.desc( )函数计算描述性统计量

> library(pastecs)
> stat.desc(mtcars[vars])
                     mpg           hp          wt
nbr.val       32.0000000   32.0000000  32.0000000
nbr.null       0.0000000    0.0000000   0.0000000
nbr.na         0.0000000    0.0000000   0.0000000
min           10.4000000   52.0000000   1.5130000
max           33.9000000  335.0000000   5.4240000
range         23.5000000  283.0000000   3.9110000
sum          642.9000000 4694.0000000 102.9520000
median        19.2000000  123.0000000   3.3250000
mean          20.0906250  146.6875000   3.2172500
SE.mean        1.0654240   12.1203173   0.1729685
CI.mean.0.95   2.1729465   24.7195501   0.3527715
var           36.3241028 4700.8669355   0.9573790
std.dev        6.0269481   68.5628685   0.9784574
coef.var       0.2999881    0.4674077   0.3041285

psych包中的describe( )函数,可以计算非缺失值的数量、平均数、标准差、中位数、截尾均值、绝对中位差、最小值、最大值、值域、峰度和平均值的标准误差。

代码清单7-5 通过psych包中的describe( )计算描述性统计量

> library(psych)
> describe(mtcars[vars])
    vars  n   mean    sd median trimmed   mad   min    max  range skew
mpg    1 32  20.09  6.03  19.20   19.70  5.41 10.40  33.90  23.50 0.61
hp     2 32 146.69 68.56 123.00  141.19 77.10 52.00 335.00 283.00 0.73
wt     3 32   3.22  0.98   3.33    3.15  0.77  1.51   5.42   3.91 0.42
    kurtosis    se
mpg    -0.37  1.07
hp     -0.14 12.12
wt     -0.02  0.17

psych包和Hmisc包均提供了名为describe( )的函数。R在调用时优先调用最后载入的程序包中的。如果强制调用,可以使用Hmisc::describe( )

7.1.2 分组计算描述型统计量

在比较多组个体或观测时,关注的焦点经常是各组的描述性统计信息。在R中完整这个任务有托干中方法,以变速箱类型各水平的描述性统计量开始。
在第5章中,介绍了整合数据的方法。可以使用aggregate( )函数(5.6.2节)来分组获取描述性统计量。

代码清单7-6 使用aggregate( )分组获取描述性统计量

> aggregate(mtcars[vars], by=list(am=mtcars$am), mean)
  am      mpg       hp       wt
1  0 17.14737 160.2632 3.768895
2  1 24.39231 126.8462 2.411000
> aggregate(mtcars[vars], by=list(am=mtcars$am), sd)
  am      mpg       hp        wt
1  0 3.833966 53.90820 0.7774001
2  1 6.166504 84.06232 0.6169816

注意list(am=mtcars$am)的使用。如果使用的是list(mtcars$am),则am列被标注为Group.1而不是am。通过这个赋值指定了一个更有帮助的列标签。如果有多个分组变量,可以使用by=list(name1=groupvar1, name2=groupvar2, ... , groupvarN)这样的语句。
但是,aggregate( )仅允许在每次调用中使用平均数、标准差这样的单返回值函数。无法一次返回若干个统计量。此时可以使用by( )函数,格式为:
by(data, INDICES, FUN)
其中data是一个数据框或矩阵,INDICES是一个因子或因子组成的列表,定义了分组,FUN是任意函数。

代码清单7-7 使用by( )分组计算描述性统计量

> dstats <- function(x)sapply(x, mystats)
> myvars <- c("mpg", "hp", "wt")
> by(mtcars[myvars], mtcars$am, dstats)
mtcars$am: 0
                 mpg           hp         wt
n        19.00000000  19.00000000 19.0000000
mean     17.14736842 160.26315789  3.7688947
stdev     3.83396639  53.90819573  0.7774001
skew      0.01395038  -0.01422519  0.9759294
kurtosis -0.80317826  -1.20969733  0.1415676
--------------------------------------------------------- 
mtcars$am: 1
                 mpg          hp         wt
n        13.00000000  13.0000000 13.0000000
mean     24.39230769 126.8461538  2.4110000
stdev     6.16650381  84.0623243  0.6169816
skew      0.05256118   1.3598859  0.2103128
kurtosis -1.45535200   0.5634635 -1.1737358

doBy包和psych包也提供了分组计算描述性统计量的函数。doBy包中的summaryBy( )函数的使用格式为:
summaryBy(formula, data=dataframe, FUN=function)
其中的formula接受以下的格式:
var1 + var2 + var3 + ... + varN ~ groupvar1 + groupvar2 + ... + groupvarN
~左侧的变量是需要分析的数值型变量,而右侧的变量是类别型的分组变量。function可为任何内建或用户自编的R函数。

代码清单7-8 使用doBy包中的summaryBu( )分组计算概述统计量

> library(doBy)
> summaryBy(mpg+hp+wt~am,data=mtcars, FUN=mystats)
  am mpg.n mpg.mean mpg.stdev   mpg.skew mpg.kurtosis hp.n  hp.mean hp.stdev
1  0    19 17.14737  3.833966 0.01395038   -0.8031783   19 160.2632 53.90820
2  1    13 24.39231  6.166504 0.05256118   -1.4553520   13 126.8462 84.06232
      hp.skew hp.kurtosis wt.n  wt.mean  wt.stdev   wt.skew wt.kurtosis
1 -0.01422519  -1.2096973   19 3.768895 0.7774001 0.9759294   0.1415676
2  1.35988586   0.5634635   13 2.411000 0.6169816 0.2103128  -1.1737358

psych包中的describeBy( )函数可计算和describe相同的描述性统计量,只是按照一个或多个分组变量分层。

代码清单7-9 使用psych包中的describe.by( )`分组计算概述统计量

> library(psych)
> myvars <- c("mpg", "hp", "wt")
> describe.by(mtcars[myvars], mtcars$am)
> #describe.by弃用,请使用descriBy( )
$`0`
    vars  n   mean    sd median trimmed   mad   min    max  range  skew
mpg    1 19  17.15  3.83  17.30   17.12  3.11 10.40  24.40  14.00  0.01
hp     2 19 160.26 53.91 175.00  161.06 77.10 62.00 245.00 183.00 -0.01
wt     3 19   3.77  0.78   3.52    3.75  0.45  2.46   5.42   2.96  0.98
    kurtosis    se
mpg    -0.80  0.88
hp     -1.21 12.37
wt      0.14  0.18

$`1`
    vars  n   mean    sd median trimmed   mad   min    max  range skew
mpg    1 13  24.39  6.17  22.80   24.38  6.67 15.00  33.90  18.90 0.05
hp     2 13 126.85 84.06 109.00  114.73 63.75 52.00 335.00 283.00 1.36
wt     3 13   2.41  0.62   2.32    2.39  0.68  1.51   3.57   2.06 0.21
    kurtosis    se
mpg    -1.46  1.71
hp      0.56 23.31
wt     -1.17  0.17

describeBy( )不允许指定任意函数,适应性较差。若存在多个分组变量,可使用list(groupvar1, groupvar2, ... , groupvarN)表示它们。但这仅在分组变量交叉口不出现空白单元时有效。

最后,使用5.6.3节中描述的reshape包灵活地按组导出描述性统计量。首先,使用:
dfm <- melt(dataframe, mesure.vars=y, id.vars=g)
融合数据框。其中的dataframe包含这数据,y是一个向量,指明了要进行概述的数值型变量(默认使用所有的变量),而g是由一个或多个分组变量组成的向量。然后使用:
cast(dfm, groupvar1 + groupvar2 + ... + variable ~ . , FUN)
重铸数据。分组变量以+号分隔,这里的variable只取其字面含义,而FUN是一个任意函数。

代码清单7-10 通过reshape包分组计算概述统计量

> library(reshape)
> dstats <- function(x) (c(n=length(x), mean=mean(x), sd=sd(x)))
> #定义函数dstats,求均值,标准差
> dfm <- melt(mtcars, measure.vars=c("mpg", "hp", "wt"), id.vars=c("am", "cyl"))
> #数据融合,按照am,cyl对mpg、hp、wt融合统计
> cast(dfm, am + cyl + variable ~ ., dstats)
> 按照am,cyl分组,对其变量求均值、标准差
   am cyl variable  n       mean         sd
1   0   4      mpg  3  22.900000  1.4525839
2   0   4       hp  3  84.666667 19.6553640
3   0   4       wt  3   2.935000  0.4075230
4   0   6      mpg  4  19.125000  1.6317169
5   0   6       hp  4 115.250000  9.1787799
6   0   6       wt  4   3.388750  0.1162164
7   0   8      mpg 12  15.050000  2.7743959
8   0   8       hp 12 194.166667 33.3598379
9   0   8       wt 12   4.104083  0.7683069
10  1   4      mpg  8  28.075000  4.4838599
11  1   4       hp  8  81.875000 22.6554156
12  1   4       wt  8   2.042250  0.4093485
13  1   6      mpg  3  20.566667  0.7505553
14  1   6       hp  3 131.666667 37.5277675
15  1   6       wt  3   2.755000  0.1281601
16  1   8      mpg  2  15.400000  0.5656854
17  1   8       hp  2 299.500000 50.2045815
18  1   8       wt  2   3.370000  0.2828427
> dfm
   am cyl variable   value
1   1   6      mpg  21.000
2   1   6      mpg  21.000
3   1   4      mpg  22.800
4   0   6      mpg  21.400

7.1.3 结果的可视化

分布特征的数值刻画很重要,但不能代替视觉呈现。

7.2 频数表和列联表

类别型变量的频数表和列联表,以及相应的独立性检验、相关性的度量、图形化展示结果的方法。
本节数据来自vcd包中的Arthritis数据集。表示一项风湿性关节炎新疗法的双盲临床实验结果。
数据展示:

> #数据展示
> library(vcd)
载入需要的程辑包:grid
> head(Arthritis)
  ID Treatment  Sex Age Improved
1 57   Treated Male  27     Some
2 46   Treated Male  29     None
3 77   Treated Male  30     None
4 17   Treated Male  32   Marked
5 36   Treated Male  46   Marked
6 23   Treated Male  58   Marked

7.2.1 生成频数表

R中提供了用于创建频数表和列联表的若干方法。部分列于表中:

表7-1 频数表和列联表函数.png

1. 一维列联表

可以使用table( )函数生成简单的频数统计表。示例如下:

> mytable <- with(Arthritis, table(Improved))
> #with限定数据框
> mytable
Improved
  None   Some Marked 
    42     14     28 
> prop.table(mytable)
> #表中条目转化为比例值
Improved
     None      Some    Marked 
0.5000000 0.1666667 0.3333333 
> prop.table(mytable)*100
> #百分比
Improved
    None     Some   Marked 
50.00000 16.66667 33.33333 

2. 二维列联表

对于二维列联表,table( )函数的使用格式为:
mytable <- table(A, B)
其中A是行变量,B是列变量。
xtabs( )函数还可使用公式风格的输入创建列联表,格式为:
mytable <- xtabs(~ A + B, data=mydata)
其中mydata是一个矩阵或数据框。要进行交叉分类的变量应出现在公式的右侧(即~符号右方),以+作为分隔符。若某个变量卸载公式左侧,则其为一个频数向量(在数据已经被表格化时很有用)。

> mytable <- xtabs(~ Treatment + Improved, data=Arthritis)
> mytable
         Improved
Treatment None Some Marked
  Placebo   29    7      7
  Treated   13    7     21

可以使用margin.table( )prop.table( )函数分别生成边际频数和比例。行和与行比例可以这样计算:

> margin.table(mytable, 1)
Treatment
Placebo Treated 
     43      41 
> prop.table(mytable, 1)
         Improved
Treatment      None      Some    Marked
  Placebo 0.6744186 0.1627907 0.1627907
  Treated 0.3170732 0.1707317 0.5121951

下标1指代table( )语句中的第一个变量。

列和与列比例可以这样计算:

> margin.table(mytable, 2)
Improved
  None   Some Marked 
    42     14     28 
> prop.table(mytable, 2)
         Improved
Treatment      None      Some    Marked
  Placebo 0.6904762 0.5000000 0.2500000
  Treated 0.3095238 0.5000000 0.7500000

这里的下标2指代table( )语句中的第二个变量。

各单元格比例可用如下语句获取:

> prop.table(mytable)
         Improved
Treatment       None       Some     Marked
  Placebo 0.34523810 0.08333333 0.08333333
  Treated 0.15476190 0.08333333 0.25000000

addmargins( )函数可为表格添加边际和。

> addmargins(mytable)
         Improved
Treatment None Some Marked Sum
  Placebo   29    7      7  43
  Treated   13    7     21  41
  Sum       42   14     28  84
> addmargins(prop.table(mytable))
         Improved
Treatment       None       Some     Marked        Sum
  Placebo 0.34523810 0.08333333 0.08333333 0.51190476
  Treated 0.15476190 0.08333333 0.25000000 0.48809524
  Sum     0.50000000 0.16666667 0.33333333 1.00000000
> #在使用addmargins( )时,默认为表中所有变量创建边际和
> addmargins(prop.table(mytable, 1), 2)
         Improved
Treatment      None      Some    Marked       Sum
  Placebo 0.6744186 0.1627907 0.1627907 1.0000000
  Treated 0.3170732 0.1707317 0.5121951 1.0000000
> #上方仅添加各行的和
> addmargins(prop.table(mytable, 2), 1)
         Improved
Treatment      None      Some    Marked
  Placebo 0.6904762 0.5000000 0.2500000
  Treated 0.3095238 0.5000000 0.7500000
  Sum     1.0000000 1.0000000 1.0000000
> #添加列和

注意:table( )函数默认忽略缺失值(NA)。要在频数统计中将NA视为一个有效的类别,请设定参数useNA="ifany"

使用gmodels包中的CrossTable( )函数是创建二维列联表的第三种方法。CrossTable( )函数仿照SAS中PROC FREQ或SPSS中CROSSTABS的形式生成二维列联表。

代码清单7-11 使用CrossTable生成二维列联表

> library(gmodels)
> CrossTable(Arthritis$Treatment, Arthritis$Improved)

 
   Cell Contents
|-------------------------|
|                       N |
| Chi-square contribution |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  84 

 
                    | Arthritis$Improved 
Arthritis$Treatment |      None |      Some |    Marked | Row Total | 
--------------------|-----------|-----------|-----------|-----------|
            Placebo |        29 |         7 |         7 |        43 | 
                    |     2.616 |     0.004 |     3.752 |           | 
                    |     0.674 |     0.163 |     0.163 |     0.512 | 
                    |     0.690 |     0.500 |     0.250 |           | 
                    |     0.345 |     0.083 |     0.083 |           | 
--------------------|-----------|-----------|-----------|-----------|
            Treated |        13 |         7 |        21 |        41 | 
                    |     2.744 |     0.004 |     3.935 |           | 
                    |     0.317 |     0.171 |     0.512 |     0.488 | 
                    |     0.310 |     0.500 |     0.750 |           | 
                    |     0.155 |     0.083 |     0.250 |           | 
--------------------|-----------|-----------|-----------|-----------|
       Column Total |        42 |        14 |        28 |        84 | 
                    |     0.500 |     0.167 |     0.333 |           | 
--------------------|-----------|-----------|-----------|-----------|

CrossTable( )函数有很多选项,可以计算(行、列、单元格)的百分比,指定小数位数;进行卡方、Fisher和McNemar独立性检验;计算期望和(皮尔逊、标准化、调整的标准化)残差;将缺失值作为一种有效值;进行行和列标题的标注;生成SAS或SPSS风格的输出。相见help(CrossTable)

3、多维列联表

table( )xlab( )都可以基于三个或更多的类别型变量生成多维列联表。margin.table( )prop.table( )addmargins( )函数可以自然地推广到高于二维的情况。另外,ftable( )函数可以紧凑地输出多维列联表。
代码清单7.12 多维列联表

> library(vcd)
载入需要的程辑包:grid
> mytable <- xtabs(~ Treatment + Sex + Improved, data = Arthritis)
> mytable
, , Improved = None

         Sex
Treatment Female Male
  Placebo     19   10
  Treated      6    7

, , Improved = Some

         Sex
Treatment Female Male
  Placebo      7    0
  Treated      5    2

, , Improved = Marked

         Sex
Treatment Female Male
  Placebo      6    1
  Treated     16    5

> ftable(mytable) #ftable输出紧凑表格
                 Improved None Some Marked
Treatment Sex                             
Placebo   Female            19    7      6
          Male              10    0      1
Treated   Female             6    5     16
          Male               7    2      5
> margin.table(mytable, 1)
Treatment
Placebo Treated 
     43      41 
> margin.table(mytable, 2)
Sex
Female   Male 
    59     25 
> margin.table(mytable, 3)
Improved
  None   Some Marked 
    42     14     28 
> margin.table(mytable, c(1, 3))
         Improved
Treatment None Some Marked
  Placebo   29    7      7
  Treated   13    7     21
> ftable(prop.table(mytable, c(1, 2))
+ )
                 Improved       None       Some     Marked
Treatment Sex                                             
Placebo   Female          0.59375000 0.21875000 0.18750000
          Male            0.90909091 0.00000000 0.09090909
Treated   Female          0.22222222 0.18518519 0.59259259
          Male            0.50000000 0.14285714 0.35714286
> ftable(addmargins(prop.table(mytable, c(1, 2)), 3)
+ )
                 Improved       None       Some     Marked        Sum
Treatment Sex                                                        
Placebo   Female          0.59375000 0.21875000 0.18750000 1.00000000
          Male            0.90909091 0.00000000 0.09090909 1.00000000
Treated   Female          0.22222222 0.18518519 0.59259259 1.00000000
          Male            0.50000000 0.14285714 0.35714286 1.00000000
> 

比例将被添加到不在prop.table( )调用中的下标上(上例中是第三个下标,或Improve)。在最后一个表格中看出,因为那里为第三个下标添加了边际和。

列联表可以展示组成表格的各种变量组合的频数或比例。

7.2.2 独立性检验

R提供了多种检验类别型变量独立性的方法。

1、卡方独立性检验

chisq.test( )函数可对二维表的行变量进行卡方独立性检验。
代码清单7-13 卡方独立性检验

> library(vcd)
> mytable <- xtabs(~ Treatment + Improved, data = Arthritis)
> chisq.test(mytable)

        Pearson's Chi-squared test

data:  mytable
X-squared = 13.055, df = 2, p-value = 0.001463

> mytable <- xtabs(~ Improved + Sex, data = Arthritis)
> chisq.test(mytable)

        Pearson's Chi-squared test

data:  mytable
X-squared = 4.8407, df = 2, p-value = 0.08889

Warning message:
In chisq.test(mytable) : Chi-squared近似算法有可能不准

第一个计算结果:p<0.01,患者接收的治疗和改善的水平可能存在某种关系;
第二个计算结果:p>0.05,患者性别和改善情况之间互相独立。

2、Fisher精确检验

fisher.test( )函数可进行FIsher精确检验。Fisher精确检验的厡假设是:边界固定的列联表中行和列是互相独立的。调用格式为:
fisher.test(mytable)
其中mytable为一个二维列联表。

> mytable <- xtabs(~ Treatment + Improved, data = Arthritis)
> fisher.test(mytable)

        Fisher's Exact Test for Count Data

data:  mytable
p-value = 0.001393
alternative hypothesis: two.sided

这里的fisher.test( )函数可以在任意行列数大于等于2的二维列联表上使用,但不能用于2×2列联表。

3、Cochran-Mantel-Haenszel检验

mentelhaen.test( )函数可用来进行Cochran-Mantel-Haenszel卡方检验,其原假设是,两个名义变量在第三个变量的每一层中都是条件独立的。
下列代码检验治疗情况和改善情况在性别的每一水平下是否独立。此检验假设不存在三阶交互作用(治疗情况×改善情况×性别)。

> mytable <- xtabs(~ Treatment + Improved + Sex, data = Arthritis)
> mantelhaen.test(mytable)

        Cochran-Mantel-Haenszel test

data:  mytable
Cochran-Mantel-Haenszel M^2 = 14.632, df = 2, p-value = 0.0006647

> 

结果表明,患者接收的治疗与得到的改善在性别的每一水平下并不独立(即,分性别来看,用药治疗的患者较接收安慰剂的患者有了更多的改善)。

7.2.3 相关性度量

显著性检验评估了是否存在充分的证据以拒绝变量见相互独立的厡假设。如果可以拒绝原假设,问题转向用以衡量相关性强弱的相关性度量。
vcd包中的assocstats( )函数可以用来计算二维列联表的phi系数、列联系数和Cramer’s V系数。
代码清单7-14 二维列联表的相关性度量

> library(vcd)
> mytable <- xtabs(~ Treatment + Improved, data = Arthritis)
> assocstats(mytable)
                    X^2 df  P(> X^2)
Likelihood Ratio 13.530  2 0.0011536
Pearson          13.055  2 0.0014626

Phi-Coefficient   : NA 
Contingency Coeff.: 0.367 
Cramer's V        : 0.394 

总体来说,较大的值意味着较强的相关性。vcd包也提供了一个kappa( )函数,可以计算混淆矩阵的Cohen’s kappa值以及加权的kappa值。(混淆矩阵可以表示两位评判者对于一系列对象进行分类所得结果的一致程度。)

7.2.4 结果的可视化

vcd包中拥有优秀的、用于可视化多维数据集中类别型变量间关系的函数,可以绘制马赛克图和关联图(参见11.4节)。ca包中的对应分析函数允许使用多种几何表示(Nenadic & Greenacre,2007)可视地探索列联表中行和列之间的关系。

7.2.5 将表转换为扁平格式

拥有一个列联表如何转化为原始数据,提供一个示例:
代码清单7-15 通过table2flat将表转换为扁平格式

> table2flat <- function(mytable) {
+   df <- as.data.frame(mytable)
+   rows <- dim(df)[1]
+   cols <- dim(df)[2]
+   x <- NULL
+   for (i in 1:rows) {
+     for (j in 1:df$Freq[i]) {
+       row <- df[i, c(1:(cols-1))]
+       x <- rbind(x, row)
+     }
+   }
+   row.names(x) <- c(1:dim(x)[1])
+   return(x)
+ }

此函数可以接收一个R中的表格(行列数任意)并返回一个扁平格式的数据框。也可以使用这个函数输入别处的表格。
以下表为例进行转换输入

7-16 原始表格.png

代码清单7-16 使用table2flat( )`函数转换已发表的数据

> treatment <- rep(c("Placebo", "Treated"), times=3)
> improved <- rep(c("None", "Some", "Marked"), each=2)
> Freq <- c(29, 13, 7, 17, 7, 21)
> #纵向数据
> mytable <- as.data.frame(cbind(treatment, improved, Freq))
> mydata <- table2flat(mytable)
> head(mydata)
  treatment improved
1   Placebo     None
2   Placebo     None
3   Placebo     None
4   Placebo     None
5   Treated     None
6   Placebo     Some

7.3 相关

相关系数可以用来描述定量变量之间的关系。相关系数的符号(±)表明关系的方向(正相关或负相关),其值表示关系的强弱程度。
本节使用R基础安装中的state.x77数据集,它提供了美国50个州在1977年的人口、收入、文盲率等数据。此外使用psych包和ggm包。

7.3.1 相关类型

R可以计算多种相关系数,包括Pearson相关系数、Spearman相关系数、Kendall相关系数、偏相关系数、多分格(polychoric)相关系数和多系列(polyserial)相关系数。

1、Prarson、Spearman和Kendall相关系数

Pearson积差相关系数衡量了两个定量变量之间的线性相关程度。Spearman等级相关系数则衡量分级定序变量之间的相关程度。Kendall'sTau相关系数也是一种非参数的等级相关度量。
cor( )函数可以计算这三种相关关系,而cov( )函数可用来计算协方差。两个函数的参数有很多,其中与相关系数的计算有关的参数可以简化为:
cor(x, use= , method= )

  • x是矩阵或数据框;
  • use指定缺失数据的处理方式(all.obs假设无缺失数据,遇到将报错;everything缺失数据相关系数计算为missing;complete.obs行删除;pairwise.complete.obs成对删除);
  • method指定相关系数的类型,pearson、spearman或kendall。
  • 默认的参数为use="everything"method="pearson"

代码清单7-17 协方差和相关系数

> states <- state.x77[, 1:6]
> cov(states)
              Population      Income   Illiteracy     Life Exp      Murder
Population 19931683.7588 571229.7796  292.8679592 -407.8424612 5663.523714
Income       571229.7796 377573.3061 -163.7020408  280.6631837 -521.894286
Illiteracy      292.8680   -163.7020    0.3715306   -0.4815122    1.581776
Life Exp       -407.8425    280.6632   -0.4815122    1.8020204   -3.869480
Murder         5663.5237   -521.8943    1.5817755   -3.8694804   13.627465
HS Grad       -3551.5096   3076.7690   -3.2354694    6.3126849  -14.549616
                HS Grad
Population -3551.509551
Income      3076.768980
Illiteracy    -3.235469
Life Exp       6.312685
Murder       -14.549616
HS Grad       65.237894
> cor(states)
            Population     Income Illiteracy    Life Exp     Murder
Population  1.00000000  0.2082276  0.1076224 -0.06805195  0.3436428
Income      0.20822756  1.0000000 -0.4370752  0.34025534 -0.2300776
Illiteracy  0.10762237 -0.4370752  1.0000000 -0.58847793  0.7029752
Life Exp   -0.06805195  0.3402553 -0.5884779  1.00000000 -0.7808458
Murder      0.34364275 -0.2300776  0.7029752 -0.78084575  1.0000000
HS Grad    -0.09848975  0.6199323 -0.6571886  0.58221620 -0.4879710
               HS Grad
Population -0.09848975
Income      0.61993232
Illiteracy -0.65718861
Life Exp    0.58221620
Murder     -0.48797102
HS Grad     1.00000000
> cor(states, method="speraman")
Error in match.arg(method) : 
  'arg' should be one of “pearson”, “kendall”, “spearman”
> cor(states, method="spearman")
           Population     Income Illiteracy   Life Exp     Murder    HS Grad
Population  1.0000000  0.1246098  0.3130496 -0.1040171  0.3457401 -0.3833649
Income      0.1246098  1.0000000 -0.3145948  0.3241050 -0.2174623  0.5104809
Illiteracy  0.3130496 -0.3145948  1.0000000 -0.5553735  0.6723592 -0.6545396
Life Exp   -0.1040171  0.3241050 -0.5553735  1.0000000 -0.7802406  0.5239410
Murder      0.3457401 -0.2174623  0.6723592 -0.7802406  1.0000000 -0.4367330
HS Grad    -0.3833649  0.5104809 -0.6545396  0.5239410 -0.4367330  1.0000000

默认情况下得到结果为方阵(所有变量之间两两计算相关)。可以计算非方形的相关矩阵,示例:

> x <- states[, c("Population", "Income", "Illiteracy", "HS Grad")]
> y <- states[, c("Life Exp", "Murder")]
> cor(x, y)
              Life Exp     Murder
Population -0.06805195  0.3436428
Income      0.34025534 -0.2300776
Illiteracy -0.58847793  0.7029752
HS Grad     0.58221620 -0.4879710

2、偏相关

偏相关是指在控制一个或多个定量变量时,另外两个定量变量之间的相互关系。ggm包中的pcor( )函数可计算偏相关系数。函数调用格式为:
pcor(u, S)
其中的u是一个数值向量,前两个值表示要计算相关系数的变量下标,其余的数值为条件变量(即要排除影响的变量)的下标。S为变量的协方差矩阵。示例:

> library(ggm)
> pcor(c(1, 5, 2, 3, 6), cov(states))
[1] 0.3462724

控制收入2、文盲率3和高中毕业率6影响时,人后1和谋杀率5之间的相关系数为0.346。偏相关系数常用语社会科学研究。

3、其他类型的相关

polycor包中的hetcor( )函数可以计算一种混合的相关矩阵,其中包括数值型变量的Pearson积差相关系数、数值型变量和有序变量之间的多系列相关系数、有序变量之间的多分格相关系数以及二分变量之间的四分相关系数。多系列、多分格和四分相关系数都假设有序变量或二分变量由潜在的正态分布导出。

7.3.2 相关性的显著性检验

得到相关系数后,进行统计显著性检验。常用的厡假设为变量间不相关(即总体的相关系数为0)。可以使用cor.test( )函数对单个的Pearson、Spearman和Kendall相关系数进行检验。简化后的使用格式为:
cor.test(x, y, alternative = , method = )
其中x和y为要检验相关性的变量,alternative则用来指定进行双侧检验或单侧检验(取值为“two.side”、"less"或"greater"),而method用以指定要计算的相关类型(“pearson”、“kendall”或“spearman”)。研究的假设为总体的相关系数小于0时,使用alternative="less"。在研究的假设为总体的相关系数大于0时,应使用alternative="greater"。在默认情况下,假设为alternative="two.side"(总体相关系数不等于0)。
代码清单7-18 检验某种相关系数的显著性

> cor.test(states[, 3], states[, 5])

        Pearson's product-moment correlation

data:  states[, 3] and states[, 5]
t = 6.8479, df = 48, p-value = 1.258e-08
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.5279280 0.8207295
sample estimates:
      cor 
0.7029752 

cor.tets( )每次只能检验一种相关关系。但psych包中提供的corr.test( )函数可以一次做更多的事情。
代码清单7-19 通过corr.test计算相关矩阵并进行显著性检验

> library(psych)
> corr.test(states, use="complete")
Call:corr.test(x = states, use = "complete")
Correlation matrix 
           Population Income Illiteracy Life Exp Murder HS Grad
Population       1.00   0.21       0.11    -0.07   0.34   -0.10
Income           0.21   1.00      -0.44     0.34  -0.23    0.62
Illiteracy       0.11  -0.44       1.00    -0.59   0.70   -0.66
Life Exp        -0.07   0.34      -0.59     1.00  -0.78    0.58
Murder           0.34  -0.23       0.70    -0.78   1.00   -0.49
HS Grad         -0.10   0.62      -0.66     0.58  -0.49    1.00
Sample Size 
[1] 50
Probability values (Entries above the diagonal are adjusted for multiple tests.) 
           Population Income Illiteracy Life Exp Murder HS Grad
Population       0.00   0.59       1.00      1.0   0.10       1
Income           0.15   0.00       0.01      0.1   0.54       0
Illiteracy       0.46   0.00       0.00      0.0   0.00       0
Life Exp         0.64   0.02       0.00      0.0   0.00       0
Murder           0.01   0.11       0.00      0.0   0.00       0
HS Grad          0.50   0.00       0.00      0.0   0.00       0

 To see confidence intervals of the correlations, print with the short=FALSE option
> 

可以看出人口数量和高中毕业了的相关系数(-0.10)并不显著地不为0(p=0.5)。

  • 其他显著性检验

在7.4.1节中,介绍了偏相关系数。在多元正态性假设下,ggm包中的pcor.test( )函数可以用来检验在控制一个或多个额外变量时两个变量之间的独立性。使用格式为:
pcor.test(r, q, n)
其中的r是有pcor( )函数计算得到的偏相关系数,q为要控制的变量数(以数值表示位置),n为样本大小。
此外,psych包中的t.test( )函数提供了多种使用的显著性检验方法。

7.3.3 相关关系的可视化

以相关系数表示的二元关系可以通过散点图和散点图矩阵进行可视化,而相关图(correlogram)则为以一种有意义的方式比较大量的相关系数提供了一种独特而强大的方法。图形将在第11章详述。

7.4 t检验

针对变量为连续型的组间比较,并假设其呈正态分布。
MASS包中的UScrime数据集。包含1960年美国47个州的刑罚制度对犯罪率影响的信息。Prob监禁概率,U1(1424岁男性失业率),U2(3539岁男性失业率)。类别型变量So(该州是否位于南方的知识变量)最为分组变量使用。

7.4.1 独立样本的t检验

一个针对两组的独立样本t检验可以用于检验两个总体的均值相等的假设。假设两组数据独立,并且是从正态总体中抽得。检验的调用格式为:
t.test(y ~ x, data)
其中的y是一个数值型变量,x是一个二分变量。调用格式为:
t.test(y1, y2)
其中的y1和y2为数值型向量(即各组的结果变量)。可选参数data的取值为一个包含了这些变量的矩阵或数据框。
这里的t检验默认假定方差不相等,并使用Welsh的修正自由度。可以添加参数var.equal=TRUE假的方差相等,并使用合并方差估计。默认的备择假设是双侧的(即均值不想等,但大小的方向不确定)。可以添加参数alternative=“less”alternative="greater"进行有方向的检验。
在下列代码中,我们使用了一个假设方差不等的双侧检验,比较南方和非南方各州的监禁概率:

> library(MASS)
> t.test(Prob ~ So, data=UScrime)

        Welch Two Sample t-test

data:  Prob by So
t = -3.8954, df = 24.925, p-value = 0.0006506
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.03852569 -0.01187439
sample estimates:
mean in group 0 mean in group 1 
     0.03851265      0.06371269 

> 

厡假设南方各州和非南方各州拥有相同监禁概率拒绝,p<0.001。

7.4.2 非独立样本的t检验

在两组的观测之间相关时,获得的是一个非独立组设计(dependent groups design)。前-后测设计(pre-post design)或重复测量设计(repeated measures design)同样也会产生非独立的组。
非独立样本的t检验假定组间的差异呈正态分布。

> library(MASS)
> sapply(UScrime[c("U1", "U2")], function(x) (c(mean=mean(x), sd=sd(x))))
           U1       U2
mean 95.46809 33.97872
sd   18.02878  8.44545
> with(UScrime, t.test(U1, U2, paired=TRUE))

        Paired t-test

data:  U1 and U2
t = 32.407, df = 46, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 57.67003 65.30870
sample estimates:
mean of the differences 
               61.48936 

> 

差异的均值(61.5)足够大,可以保证拒绝年长和年轻男性的平均失业率相同的假设。年轻男性的失业率更高。

7.4.3 多余两组的情况

如果在对于两个组之间进行比较,在假设数据从正态总体中独立抽样得到时,可以使用方差分析(ANOVA)。ANOVA是一套覆盖了许多实验设计和准实验设计的综合方法。见第9章。

7.5 组间差异的非参数检验

数据无法满足t检验或ANOVA的参数假设,可以转而使用非参数方法。

7.5.1 两组的比较

若两组数据独立,可以使用Wilcoxon秩和检验(更为人知的名字是Mann - Whitney U检验)来评估观测是否是从相同的概率分布中抽得的(即,在一个总体中获得更高得分的概率是否比另一个总体要大)。调用格式为:
wilcox.test(y ~ x, data)
其中的y是数值型变量,x是一个二分变量。调用格式或为:
wilcox.test(y1, y2)
y1和y2为各组的结果变量。可选参数data是包含变量的矩阵或数据框。默认进行一个双侧检验。可以添加参数exact进行精确检验。指定alternative="less"alternative="greater"进行有方向的检验。
使用Mann - Whitney U检验回答上节关于监禁率的问题,将得到如下结果:

> with(UScrime, by(Prob, So, median))
So: 0
[1] 0.038201
--------------------------------------------------------------- 
So: 1
[1] 0.055552
> wilcox.test(Prob ~ So, data=UScrime)

        Wilcoxon rank sum test

data:  Prob by So
W = 81, p-value = 8.488e-05
alternative hypothesis: true location shift is not equal to 0

> 

Wilcoxon符号秩检验是非独立样本t检验的一种非参数替代方法。适用于两组成对数据和无法保证正态性假设的情境。调用格式与Mann - Whitney U检验完全相同,不过还可以添加参数paired=TRUE

> sapply(UScrime[c("U1", "U2")], median)
U1 U2 
92 34 
> with(UScrime, wilcox.test(U1, U2, paired=TRUE))

        Wilcoxon signed rank test with continuity correction

data:  U1 and U2
V = 1128, p-value = 2.464e-09
alternative hypothesis: true location shift is not equal to 0

Warning message:
In wilcox.test.default(U1, U2, paired = TRUE) :
  cannot compute exact p-value with ties
> 

本例中,含参的t检验和与其作用相同的非参数检验得到了相同的结论。当t检验和假设合理时,参数检验的功效更强(更容易发现存在的差异)。而非参数检验在假设非常不合理时(如对于等级有序数据)更适用。

7.5.2 多于两组的比较

比较的组数多余两个时,需转寻他法。如果要比较美国四个地区的文盲率,这成为单向设计,可以使用参数或非参数的方法来解决。
如果无法满足ANOVA设计的假设,那么可以使用非参数方法评估组间的差异。如果各组独立,则Kruskal-Wallis检验将是一种实用的方法。如果各组不独立,那么Friedman检验更合适。
Kruskal-Wallis检验的调用格式为:
kruskal.test(y ~ A, data)
其中的y是一个数值型结果变量,A是一个拥有两个或更多水平的分组变量(grouping variable)。(若有两个水平,则与Mann-Whitney U检验等价)而Friedman检验的调用格式为:
friedman.test(y ~ A | B, data)
y是数值型结果变量,A是一个分组变量,B是一个用以认定匹配观测的区组变量(blocking variable)。
利用Kruskal - Wallis检验回答文盲率的问题。

> states <- as.data.frame(cbind(state.region, state.x77))
> head(states)
           state.region Population Income Illiteracy Life Exp Murder HS Grad Frost
Alabama               2       3615   3624        2.1    69.05   15.1    41.3    20
Alaska                4        365   6315        1.5    69.31   11.3    66.7   152
Arizona               4       2212   4530        1.8    70.55    7.8    58.1    15
Arkansas              2       2110   3378        1.9    70.66   10.1    39.9    65
California            4      21198   5114        1.1    71.71   10.3    62.6    20
Colorado              4       2541   4884        0.7    72.06    6.8    63.9   166
             Area
Alabama     50708
Alaska     566432
Arizona    113417
Arkansas    51945
California 156361
Colorado   103766
> kruskal.test(Illiteracy ~ state.region, data=states)

        Kruskal-Wallis rank sum test

data:  Illiteracy by state.region
Kruskal-Wallis chi-squared = 22.672, df = 3, p-value = 4.726e-05

> 

显著性检验的结果意味这美国四个地区的文盲率各不相同。(p<0.001)
可以拒绝不存在差异的原假设,但并不知道哪些地区显著与其他地区不同。
可以使用Mann - Whitney U检验每次比较两组数据。
npmc包还提供了所需要的非参数多组比较程序。
安装npmc包,包中的npmc( )函数接收的输入为一个两列的数据框,其中一列名为var(因变量),另一列名为class(分组变量)。
代码清单7-20 非参数多组比较

此处npmc包已无法在现有版本的R中应用
> install.packages("npmc")
--- 在此連線階段时请选用CRAN的鏡子 ---
Warning message:
package ‘npmc’ is not available (for R version 3.3.2) 

7.6 组间差异的可视化

在7.4和7.5节中,介绍进行组间比较的统计方法。使用视觉直观地检查组间差异,同样是全面的数据分析策略中的一个重要部分。R中提供了许多比较组间数据的图形方法,包括6.5节中的箱线图(简单箱线图、含凹槽的箱线图、小提琴图)、6.4.1节中叠加的核密度图,以及第9章中的评估检验假定的图形方法。

7.7 小结

  • R中用于生成统计概要和进行假设检验的函数;
  • 样本统计量和频数表、独立性检验和类别型变量的相关度量、定量变量的相关系数(及连带的显著性检验);
  • 两组或更多组定量结果变量的比较

——2017.2.27
——于510

推荐阅读更多精彩内容