第三章:关于统计资料的思考
计数资料和分类资料的区别
-
计数资料:其实就是对于某个事件进行计数的资料,例如对于咳嗽次数的计数。而分类资料则是一个事件的两种类别,比如男女。所以两者是不同的数据类型。
-
统计分析上来看,
- 由于计数资料,一般来说服从Poisson分布,所以在回归分析的时候使用Poisson回归或者负二项回归。两个回归之间的区别在于,Poisson一般用于个体之间相互独立的情形,而负二项则用于个体之间不独立的情形,比如说咳嗽是相互传染的,那么分析的时候需要用到负二项。另外如果条件方差超过条件均值时也是推荐使用负二项的。 我们使用
robust
包中的Breslow
癫痫数据进行常见的Poisson回归分析演示。我们就遭受轻微或严重间歇性癫痫的病人的年龄和癫痫发病数收集了数据,包含病人被随机分配到药物组或者安慰剂组前八周和随机分配后八周两种情况。响应变量为sumY(随机化后八周内癫痫发病数),预测变量为治疗条件(Trt)、年龄(Age)和前八周内的基础癫痫发病数(Base)。
Hide
library(robust)
library(tidyverse)
data("breslow.dat")
smallData <- breslow.dat[,c(6:8,10)]
summary(smallData)
Base Age Trt sumY
Min. : 6.00 Min. :18.00 placebo :28 Min. : 0.00
1st Qu.: 12.00 1st Qu.:23.00 progabide:31 1st Qu.: 11.50
Median : 22.00 Median :28.00 Median : 16.00
Mean : 31.22 Mean :28.34 Mean : 33.05
3rd Qu.: 41.00 3rd Qu.:32.00 3rd Qu.: 36.00
Max. :151.00 Max. :42.00 Max. :302.00
Hide
####查看响应变量的基本分布
hist(smallData$sumY, breaks = 20)
Hide
####Poisson回归分析
model <- glm(sumY ~ Base + Age + Trt, data = smallData, family = poisson())
summary(model)
Call:
glm(formula = sumY ~ Base + Age + Trt, family = poisson(), data = smallData)
Deviance Residuals:
Min 1Q Median 3Q Max
-6.0569 -2.0433 -0.9397 0.7929 11.0061
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1.9488259 0.1356191 14.370 < 2e-16 ***
Base 0.0226517 0.0005093 44.476 < 2e-16 ***
Age 0.0227401 0.0040240 5.651 1.59e-08 ***
Trtprogabide -0.1527009 0.0478051 -3.194 0.0014 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for poisson family taken to be 1)
Null deviance: 2122.73 on 58 degrees of freedom
Residual deviance: 559.44 on 55 degrees of freedom
AIC: 850.71
Number of Fisher Scoring iterations: 5
Hide
####检验过度离势
qcc::qcc.overdispersion.test(smallData$sumY, type = "poisson")
Overdispersion test Obs.Var/Theor.Var Statistic p-value
poisson data 62.87013 3646.468 0
过度离势检验<0.05的时候。表示存在过度离势。因此需要把
family
参数转换为:quasipoisson
Hide
###负二项回归
library(MASS)
modle <- glm.nb(sumY ~ Base + Age + Trt, data = smallData)
summary(modle)
Call:
glm.nb(formula = sumY ~ Base + Age + Trt, data = smallData, init.theta = 3.361505307,
link = log)
Deviance Residuals:
Min 1Q Median 3Q Max
-3.3755 -0.7517 -0.1916 0.2817 2.6103
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1.931832 0.408372 4.731 2.24e-06 ***
Base 0.027736 0.002817 9.846 < 2e-16 ***
Age 0.016815 0.012535 1.341 0.18
Trtprogabide -0.193518 0.154271 -1.254 0.21
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for Negative Binomial(3.3615) family taken to be 1)
Null deviance: 181.856 on 58 degrees of freedom
Residual deviance: 63.667 on 55 degrees of freedom
AIC: 476.46
Number of Fisher Scoring iterations: 1
Theta: 3.362
Std. Err.: 0.710
2 x log-likelihood: -466.457
- 而分类资料一般选用Logistic回归。对于分类资料而言,如果是二分类资料使用基本的Logistic回归即可。如果是多分类的则需要看分组之间是否有序,适当的选择有序/无序Logistic回归即可。
Hide
###简单的二分类Logistic回归
data(anesthetic, package = "DAAG")
head(anesthetic)
| |
| |
move
<dbl>
|
conc
<dbl>
|
logconc
<dbl>
|
nomove
<dbl>
|
| :-- | --: | --: | --: | --: |
| 1 | 0 | 1.0 | 0.0000000 | 1 |
| 2 | 1 | 1.2 | 0.1823216 | 0 |
| 3 | 0 | 1.4 | 0.3364722 | 1 |
| 4 | 1 | 1.4 | 0.3364722 | 0 |
| 5 | 1 | 1.2 | 0.1823216 | 0 |
| 6 | 0 | 2.5 | 0.9162907 | 1 |
6 rows
Hide
fit_logit <- glm(nomove ~ conc, family = binomial(), data = anesthetic)
summary(fit_logit)
Call:
glm(formula = nomove ~ conc, family = binomial(), data = anesthetic)
Deviance Residuals:
Min 1Q Median 3Q Max
-1.76666 -0.74407 0.03413 0.68666 2.06900
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -6.469 2.418 -2.675 0.00748 **
conc 5.567 2.044 2.724 0.00645 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 41.455 on 29 degrees of freedom
Residual deviance: 27.754 on 28 degrees of freedom
AIC: 31.754
Number of Fisher Scoring iterations: 5
多分类的话,如果分类是无序的则使用
nnet::multinom
即可。
Hide
###无序多分类
require(foreign)
require(nnet)
ml <- read.dta("https://stats.idre.ucla.edu/stat/data/hsbdemo.dta")
ml$prog2 <- relevel(ml$prog, ref = "academic")
head(ml)
| |
| |
id
<dbl>
|
female
<fctr>
|
ses
<fctr>
|
schtyp
<fctr>
|
prog
<fctr>
|
read
<dbl>
|
write
<dbl>
|
math
<dbl>
|
science
<dbl>
| |
| :-- | --: | :-- | :-- | :-- | :-- | --: | --: | --: | --: | --- |
| 1 | 45 | female | low | public | vocation | 34 | 35 | 41 | 29 | |
| 2 | 108 | male | middle | public | general | 34 | 33 | 41 | 36 | |
| 3 | 15 | male | high | public | vocation | 39 | 39 | 44 | 26 | |
| 4 | 67 | male | low | public | vocation | 37 | 37 | 42 | 33 | |
| 5 | 153 | male | middle | public | vocation | 39 | 31 | 40 | 39 | |
| 6 | 51 | female | high | public | general | 42 | 36 | 42 | 31 | |
6 rows | 1-10 of 14 columns
Hide
###无序logit
test <- multinom(prog2 ~ ses + write, data = ml)
Error in multinom(prog2 ~ ses + write, data = ml) : 参数没有用(data = ml)
如果分类是有序的,则可是使用
MASS::polr
Hide
require(foreign)
require(MASS)
require(Hmisc)
###读取数据
dat <- read.dta("https://stats.idre.ucla.edu/stat/data/ologit.dta")
####有序logit回归
m <- polr(apply ~ pared + public + gpa, data = dat, Hess=TRUE)
####定义结果返回函数
order_logires <- function(model, n){
ctable <- coef(summary(model))
p <- pnorm(abs(ctable[, "t value"]), lower.tail = FALSE) * 2
ci <- confint(model)
if(n == 1){
res <- c(exp(c(OR = coef(model), ci)), p = p[1])
}else{
res <- cbind(exp(cbind(OR = coef(model), ci)), p = p[1:n])
}
return(res)
}
###返回OR, 95%CI, P
order_logires(m, 3)
Waiting for profiling to be done...
OR 2.5 % 97.5 % p
pared 2.8510579 1.6958376 4.817114 8.087072e-05
public 0.9429088 0.5208954 1.680579 8.435464e-01
gpa 1.8513972 1.1136247 3.098490 1.811594e-02
计数资料可否采用连续性变量来分析
- 由于计数资料也是有很多分类的,那么在看其回归的时候,能否使用线性回归。这个一般来说是不能的。线性回归需要满足的条件之一是正态。计数资料因为一般没有负数所以很有可能是偏态的。所以是不能是有的。
- 不过如果计数资料取值离0很远。同时呈正态,如果研究者不介意预测结果出现小数点或者负数则可以使用。
分类资料分析统计方法的选择
对于分类资料,如果要观察其等级关系的结果的时候,最好使用秩和检验(Wilcoxon)。如果只是观察各组之间有没有差异则最好使用卡方检验
寻找cutoff的多种方法
根据专业知识来决定
基于专业知识划分是最好的cutoff的方式。模型计算出来的东西。必定不具备一定的说服力。
利用广义客家模型结合专业划分
当我们在选择cut-off的时候,没有办法完全利用专业知识来划分的时候。但是如果有一定的参考,再结合专业知识的话就可以进行划分的时候,那么就可以用到广义可加模型。相较于一般的线性模型,广义可加模型绘制出来的曲线不一定是线性的。这个模型主要可以用来探索自变量和因变量的关系。 - R语言中可是使用mgcv::gam
来进行模型预测
Hide
library(mgcv)
dat <- read.csv("dat1.csv")
head(dat)
| |
| |
age
<int>
|
ageg
<int>
|
hyper
<int>
|
| :-- | --: | --: | --: |
| 1 | 58 | 2 | 1 |
| 2 | 50 | 2 | 1 |
| 3 | 56 | 2 | 1 |
| 4 | 56 | 2 | 1 |
| 5 | 52 | 2 | 1 |
| 6 | 60 | 3 | 1 |
6 rows
Hide
fit <- gam(hyper ~ s(age), data = dat, family = binomial())
plot(fit)
abline(h = 0)
image.png
由例子可见。可以吧年龄三分类。
利用ROC曲线
如果有一个明确的二分类结局的话,可以使用ROC曲线来寻找最佳的cutoff。 - R里面可是使用pROC
包进行结果的统计
利用最大选择秩统计量
如果当结局变量函数时间变量,或者说是分类变量的时候.可是使用最大选择秩统计量来进行最佳cutoff的选择。其主要思想也是把所有可能的分组都计算一遍。然后寻找最佳的结果。这种方式最多用于在生存分析的时候寻找最佳的cutoff - R中可以通过maxstat
来实现。
Hide
library(maxstat)
set.seed(29)
x <- sort(runif(20))
y <- c(rnorm(10), rnorm(10, 2))
mydata <- data.frame(cbind(x,y))
head(mydata)
| |
| |
x
<dbl>
|
y
<dbl>
|
| :-- | --: | --: |
| 1 | 0.09308678 | 0.42860107 |
| 2 | 0.09968104 | 1.92485609 |
| 3 | 0.10321380 | 0.30992181 |
| 4 | 0.11999244 | -0.03158589 |
| 5 | 0.17617088 | 0.47206596 |
| 6 | 0.23314674 | -0.34216061 |
6 rows
Hide
mod <- maxstat.test(y ~ x, data=mydata, smethod="Wilcoxon", pmethod="HL",
minprop=0.25, maxprop=0.75, alpha=0.05)
plot(mod)
image.png
使用分类树进行划分
使用分类树,类似于决策曲线一样的来说明如果进行分组。
Hide
library(rpart)
fit <- rpart(Kyphosis ~ Age + Number + Start, data = kyphosis)
plot(fit)
text(fit, use.n = TRUE)
image.png
聚类分析
之前的方法都有一个条件即必须有一个明确的确定的结局。这样根据结局对自变量进行划分,通常将这种情况称为有监督的。但是如果我们没有结局变量的时候,如果要讲样本进行划分的话,这样就需要用到无监督的聚类分析。
- 常用的方式发层次法。K-means法等等。
网友评论