美文网首页
【R画图学习21.2】差异显著性*和abc(非参数检验)

【R画图学习21.2】差异显著性*和abc(非参数检验)

作者: jjjscuedu | 来源:发表于2022-11-26 20:11 被阅读0次

但是,一旦数据不满足一定的分布条件,也就是不满足方差分析的条件时,我们就需要更换为非参数的方法,这里我们测试了一个非参数检验的方法示例,先执行Kruskal-Wallis检验比较整体差异,再执行Behrens-Fisher的非参数多重比较查看两两差异。

但是Behrens-Fisher 检验得到的是两组间的 p 值,对于显著性“abc”的标注,通过 p 值再结合中位数水平需要手动判断,大体方法和前面讲的类似。

但是,npmc包的最后更新版本(1.0.7)无法正确运行在R 3.0以上的版本。HK Zhang 在Rstudio中做了调试和编译,对npmc.R的原代码做了一些细微的更改以支持最新的mvtnorm包。npmc包最后编译运行成功。(注:R>4.0 目前也不行了,3.8可行)

最新原程序共享在GitHub:

https://github.com/HK-Zhang/Rice/tree/master/npmc

也可以通过下面链接直接下载这个包

http://pan.baidu.com/s/1nuqdXcX

还是用21.1的测试数据。

library(reshape2)

library(npmc)

library(ggplot2)

data <- read.table("test_data.txt",header=T,sep="\t")

我们先来测试一组数据,选取group1和value1的数据来测试看下。

#Kruskal-Wallis 检验,整体差异

dat <- data[c("group1", "value1")]

names(dat) <- c('class', 'var')

dat$class <- factor(dat$class)

fit <- kruskal.test(var~class, dat)

p_value <- fit$p.value

#获取 Kruskal-Wallis 检验 p 值

stat_kruskal <- NULL

    if (p_value < 0.001) {

      sig <- '***' } else if(p_value >= 0.001 & p_value < 0.01) {

      sig <- '**'  } else if(p_value >= 0.01 & p_value < 0.05)  {

      sig <- '*'  } else {

      sig <- ''    }

stat_kruskal <- rbind(stat_kruskal, c("group1","value1",p_value, sig))

#Behrens-Fisher 检验(npmc 包),非参数多重比较

BF_test <- npmc(dat, df = 2, alpha = 0.05)

BF <- BF_test$test$BF

BF结果如下图所示,可以看出是group1内每个小组和小组之间value1的统计检验结果,pvalue在p.value.2s中,只不过每个小组用的1,2,3对应的index顺序。

info <- BF_test$info

info里面包含index和class的信息。

BF$group <- paste("group1", "value1", sep = '/')

所以,我们现在把BF中的index换成相应的组名。

for (i in 1:nrow(BF)){

  x <- strsplit(as.character(BF$cmp[i]),"-")[[1]]

  BF[i,'class1'] <-rownames(info)[which(info$group.index == x[1])]

  BF[i,'class2'] <-rownames(info)[which(info$group.index == x[2])]

}

stat_BF <- NULL

stat_BF <- rbind(stat_BF, BF[c(12:14, 2:11)])

#这样子,我们就获得了每个组之间的统计检验显著性结果。

但是,如果我们想要标记abc,就需要自己手动来标记了,首先需要排序中位数,然后按21.1的方法来手动标记abc。

#下面,我们就计算中位数,然后按从高到低来排序。

dat_new <- cbind(aggregate(dat$var, by = list(dat$class), FUN = median),

                  aggregate(dat$var, by = list(dat$class), FUN = sd))

dat_new$group <- "group1"

dat_new$var <- "value1"

dat_new <- dat_new[c(5, 6, 1,2, 4)]

names(dat_new) <- c('group', 'var', 'class', 'median',"sd")

dat_new <- dat_new[order(dat_new$median, decreasing = TRUE), ]

class <- as.vector(dat_new$class)

下面,我们就来手动标记abc,一般做法如下(前面也讲过):

(1)首先根据均值大小,将各组由高往低排排序,均值最高的组标注为“a”;

(2)将均值最高的组与第二高的组相比,若差异显著,则第二组标注为“b”;若不显著,继续比较其与均值第三高的组的差异;

(3)若均值最高的组与第二高的组不显著,均值第二高的组与第三高的组显著,则第二高的组就同样标注为“a”,第三高的组标注为“b”;若均值最高的组与第二高的组不显著、均值第二高的组与第三高的组不显著,但均值最高的组与第三高的组显著,则第二高的组就标注为“ab”,第三高的组标注为“b”;

(4)然后以标注为“b”的组的均值为标准,以此类推,继续循环往后比较,直到最小均值的组被标记,且比较完毕为止。

m = 1; n = 2; l = 1

dat_new[m,'sig'] <- letters[l]    #最高的赋值为a

while(n<length(class)){

  for(n in (m+1):length(class)) {

    #从stat_BF中获取class[m]和class[n]的pvalue,但是首先需要判断一下顺序,index小的放前面

      tmp1=info$group.index[which(info$class.level == class[m])]

      tmp2=info$group.index[which(info$class.level == class[n])]  

      if(tmp1<tmp2){

      index1=class[m]

      index2=class[n]

      }else{

      index1=class[n]

      index2=class[m]

      }

      tmp_p= stat_BF[intersect(which(stat_BF$class1==index1),which(stat_BF$class2==index2)),]$p.value.2s

#如果p小于显著性值,则letters依次望下排。

      if(tmp_p<0.05){

      dat_new[n,'sig'] <- letters[l+1]

      if (n - m != 1) {

        for (x in (m+1):(n-1)) {

          tmp1=info$group.index[which(info$class.level == class[x])]

          tmp2=info$group.index[which(info$class.level == class[n])]

          if(tmp1<tmp2){

          index1=class[x]

          index2=class[n]

          }else{

          index1=class[n]

          index2=class[x]

          }

tmp_p= stat_BF[intersect(which(stat_BF$class1==index1),which(stat_BF$class2==index2)),]$p.value.2s

          if(tmp_p<0.05){

            dat_new[x,'sig'] <- letters[l]

          }else{

            dat_new[x,'sig'] <- paste(letters[l], letters[l+1], sep = '')

          }

        }

      }     

      l = l + 1

      m = n

      break

      }

  }

 dat_new[(m:n),'sig'] <- letters[l]

}

ggplot(data = dat_new, aes(x = class, y = median)) +

geom_col(aes(fill = class), color = NA, show.legend = FALSE) +

geom_errorbar(aes(ymin = median - sd, ymax = median + sd), width = 0.2) +

geom_text(aes(label = sig, y = median + sd + 0.3*(median+sd)),size=5) +

labs(x = '', y = '')+

theme(text = element_text(size = 20))

下面,像21.1一样,我们写个双层循环,把group1和group2分别和value进行显著性检验。

groups<-c('group1', 'group2')

values<-c('value1', 'value2', 'value3', 'value4')

stat_kruskal <- NULL

stat_BF <- NULL

data_list <- NULL

for(i in groups)

{

  for (j in values)

  { 

    cat("i:", i,"\n")

    cat("j:", j,"\n")

    #Kruskal-Wallis 检验,整体差异

    dat <- data[c(i,j)]

    names(dat) <- c('class', 'var')

    dat$class <- factor(dat$class)

    fit <- kruskal.test(var~class, dat)

    p_value <- fit$p.value

    #获取 Kruskal-Wallis 检验 p 值

    if (p_value < 0.001) {

      sig <- '***' } else if(p_value >= 0.001 & p_value < 0.01) {

      sig <- '**'  } else if(p_value >= 0.01 & p_value < 0.05)  {

      sig <- '*'  } else {

      sig <- ''    }

    stat_kruskal <- rbind(stat_kruskal, c(i,j,p_value, sig))

    #Behrens-Fisher 检验(npmc 包),非参数多重比较

    BF_test <- npmc(dat, df = 2, alpha = 0.05)

    BF <- BF_test$test$BF

    info <- BF_test$info

    BF$group <- paste(i, j, sep = '/')

    for (q in 1:nrow(BF)){

        x <- strsplit(as.character(BF$cmp[q]),"-")[[1]]

        BF[q,'class1'] <-rownames(info)[which(info$group.index == x[1])]

        BF[q,'class2'] <-rownames(info)[which(info$group.index == x[2])]

    }

    stat_BF <- rbind(stat_BF, BF[c(12:14, 2:11)])

    tmp_BF<-BF[c(12:14, 2:11)]

    dat_new <- cbind(aggregate(dat$var, by = list(dat$class), FUN = median),

                  aggregate(dat$var, by = list(dat$class), FUN = sd))

    dat_new$group <- i

    dat_new$var <- j

    dat_new <- dat_new[c(5, 6, 1,2, 4)]

    names(dat_new) <- c('group', 'var', 'class', 'median',"sd")

    dat_new <- dat_new[order(dat_new$median, decreasing = TRUE), ]

    class <- as.vector(dat_new$class)

    m = 1; n = 2; l = 1

    dat_new[m,'sig'] <- letters[l]

    while(n<length(class)){

    for(n in (m+1):length(class)) {

      tmp1=info$group.index[which(info$class.level == class[m])]

      tmp2=info$group.index[which(info$class.level == class[n])]

      if(tmp1<tmp2){

      index1=class[m]

      index2=class[n]

      }else{

      index1=class[n]

      index2=class[m]

      }

      tmp_p= tmp_BF[intersect(which(tmp_BF$class1==index1),which(tmp_BF$class2==index2)),]$p.value.2s

      if(tmp_p<0.05){

      dat_new[n,'sig'] <- letters[l+1]

      if (n - m != 1) {

        for (x in (m+1):(n-1)) {

          tmp1=info$group.index[which(info$class.level == class[x])]

          tmp2=info$group.index[which(info$class.level == class[n])]

          if(tmp1<tmp2){

          index1=class[x]

          index2=class[n]

          }else{

          index1=class[n]

          index2=class[x]

          }

          tmp_p= tmp_BF[intersect(which(tmp_BF$class1==index1),which(tmp_BF$class2==index2)),]$p.value.2s

          if(tmp_p<0.05){

            dat_new[x,'sig'] <- letters[l]

          }else{

            dat_new[x,'sig'] <- paste(letters[l], letters[l+1], sep = '')

          }

        }

      }     

      l = l + 1

      m = n

      break

      }

  }

  dat_new[(m:n),'sig'] <- letters[l]

}

data_list <- rbind(data_list, dat_new)

  }

}

整体的统计检验结果:

每对里面每个类别的Behrens-Fisher非参数多重比较结果:

最后包含abc的文件如下图所示:

我们按分面画出每对的统计检验结果。

ggplot(data = data_list, aes(x = class, y = median)) +

geom_col(aes(fill = class), color = NA, show.legend = FALSE) +

geom_errorbar(aes(ymin = median - sd, ymax = median + sd), width = 0.2) +

facet_grid(var~group, scale = 'free' , space = 'free_x') +

geom_text(aes(label = sig, y = median + sd + 0.3*(median+sd)),size=5) +

labs(x = '', y = '')+

theme(text = element_text(size = 20))

相关文章

网友评论

      本文标题:【R画图学习21.2】差异显著性*和abc(非参数检验)

      本文链接:https://www.haomeiwen.com/subject/saeffdtx.html