美文网首页
【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