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

但是,一旦数据不满足一定的分布条件,也就是不满足方差分析的条件时,我们就需要更换为非参数的方法,这里我们测试了一个非参数检验的方法示例,先执行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))

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容