R语言自动计算并添加显著性字母(上)

之前分析处理数据总是在SPSS里做方差分析,之后在Origin里作图,之后手动添加显著性字母,因此我就想到在R语言中同时实现这两者。

本文涉及的是单因素单组方差分析,单因素多组方差分析在下篇。

显著性检验方法选取

首先我们要了解一下应该如何选取显著性分析方法,不然之后做出来的都没有意义。

当我们对一组数据进行检验前,首先需要对其正态性和方差齐性进行检验,如果该组数据符合正态分布同时方差齐,那么我们将采取参数检验;反之,数据满足正态分布但方差齐、数据不满足正态分布但方差齐和数据不满足正态分布同时方差不齐都将采取非参数检验

请参考该博客,讲得超级清晰。

统计方法的选择(1)--正态性和方差齐性 - 简书 (jianshu.com)

知道了该用什么,接下来就是查这些方法在R语言中如何表示。

#1.数据的正态检验,p>0.05数据正态分布,适合数据量3-5000,大于5000则可以不用进行正态性检验
shapiro.test(data$values)

#2.方差齐性检验
#2.1符合正态分布才能进行Bartlett检验,p>0.05表示方差齐
#bartlett.test(data$values ~ data$group, data=data)
#2.2该方法对数据正态性不敏感,因此正态性与非正态性数据均适用,p>0.05表示方差齐
leveneTest(data$values ~ as.factor(data$group), data=data)

在这我是分别采用了shapiro-wilk test和Levene's test对其正态性和方差齐性进行检验

参数检验并转换成字母

#3.符合正态分布且方差齐-参数检验
variance<-aov(values ~ group, data=data)
summary(variance) #极显著的情况下才能进行后续多重比较,不然无意义
#3.1比较次数<=3
MC <- LSD.test(variance,"group", p.adj="bonferroni")#结果显示:标记字母法out$group
MC
#3.2比较次数多于3
#library(multcomp)
#MC <- duncan.test(variance,"group")

error=as.data.frame(MC$groups)
error$group=row.names(error)
error2=merge(error,df,by="group")
colnames(error2)=c("group","values","label","mean","sd")

#3.3
#MC <- TukeyHSD(variance,"group")
#MC
#library(multcompView)
#tukey_letters1 <- multcompLetters4(variance, MC)  #显示abc
#error <- as.data.frame.list(tukey_letters1$group)  
#error$group=row.names(error)
#把df和error2合并
#error2=merge(error,df,by="group")
#colnames(error2)=c("group","label","a","values","sd")

参数检验是采取了anova方法,因为我是3组,所以我用多重检验中的LSD方法进行了显著性检验,当然,其他多重检验方法我也放在这里了,具体的选取可以进一步细化选取。(别嫌我啰嗦哇,这是为了后续代码修改做铺垫~)

非参数检验并转换成字母

#当数据不符合正态分布或者方差不齐时,不适用ANOVA检验,用Kruskal-Wallis非参数检验
#不符合正态性分布或方差不齐-非参数检验
data$group=as.factor(data$group)
#方差检验,相当于参数检验中的aov()
result <- kruskal.test(values ~ group, data = data)
result   #Kruskal-Wallis p=0.29
#多重检验
library(reshape2) # 需要此包来进行两两比较
pairwise_pvalues <- pairwise.wilcox.test(data$values, data$group, p.adjust.method = "bonferroni")
pairwise_pvalues  #这个数据格式对着,就看后续如何处理
p_matrix <- pairwise_pvalues$p.value
library(multcompView)

# 提取p值的辅助函数
extraxt_P <- function(x) {
  rn <- row.names(x)
  cn <- colnames(x)
  an <- unique(c(cn, rn))
  myval <- x[!is.na(x)]
  mymat <- matrix(1, nrow = length(an), ncol = length(an), dimnames = list(an, an))
  for(ext in 1:length(cn)) {
    for(int in 1:length(rn)) {
      if(is.na(x[row.names(x) == rn[int], colnames(x) == cn[ext]])) next
      mymat[row.names(mymat) == rn[int], colnames(mymat) == cn[ext]] <- x[row.names(x) == rn[int], colnames(x) == cn[ext]]
      mymat[row.names(mymat) == cn[ext], colnames(mymat) == rn[int]] <- x[row.names(x) == rn[int], colnames(x) == cn[ext]]
    }
  }
  return(mymat)
}
# 提取p值矩阵
p_matrix <- extraxt_P(p_matrix)
# 获取每个组别的均值
group_means <- tapply(data$values, data$group, mean)
# 根据均值对组别进行排序,使得均值最大的组别在前
sorted_groups <- names(sort(group_means, decreasing = TRUE))
# 重新排列p值矩阵的行和列,以匹配排序后的组别顺序
sorted_p_matrix <- p_matrix[sorted_groups, sorted_groups]
# 使用multcompLetters函数
letters_result <- multcompLetters(sorted_p_matrix)
error=as.data.frame(letters_result$Letters)
error$group=row.names(error)
#把df和error2合并
error2=merge(error,df,by="group")
colnames(error2)=c("group","label","values","sd")

别着急!简化版在下面

既然要么参数检验,要么非参数检验,那么理所当然会想到if语句

所以代码思路就是:if 符合正态分布&方差齐,用参数检验;else用非参数检验。

所以单因素单组显著性检验代码如下:

首先是导入的数据格式(各分组下包含重复)

#单组用这个
library(agricolae)
library(car)
library(multcompView)
library(reshape2)
data=read.table("data.txt", header = 1, check.names = F, sep = "")
#求mean和sd
df2=aggregate(x=data$values, by=list(data$group),FUN=function(x) c(mean=mean(x), sd=sd(x)))
df2$mean=df2$x[,1]
df2$sd=df2$x[,2]
df2=df2[,-2]
colnames(df2)=c("group","mean","sd")

#1.数据的正态检验,p>0.05数据正态分布,适合数据量3-5000,大于5000则可以不用进行正态性检验
a=shapiro.test(data$values)
ZT=a$p.value
ZT
#2.方差齐性检验
#2.1符合正态分布才能进行Bartlett检验,p>0.05表示方差齐
#bartlett.test(data$values ~ data$group, data=data)
#2.2该方法对数据正态性不敏感,因此正态性与非正态性数据均适用,p>0.05表示方差齐
b=leveneTest(data$values ~ as.factor(data$group), data=data)
c=as.data.frame(b$`Pr(>F)`)
FC=c[1,]
FC


if(ZT > 0.05 & FC>0.05) {
  variance<-aov(values ~ group, data=data)
  MC <- LSD.test(variance,"group", p.adj="bonferroni")#结果显示:标记字母法out$group
  error=as.data.frame(MC$groups)
  error$group=row.names(error)
  error2=merge(error,df2,by="group")
  error2=error2[,-2]
  colnames(error2)=c("group","label","values","sd")

} else {
  data$group=as.factor(data$group)
  #方差检验,相当于参数检验中的aov()
  result <- kruskal.test(values ~ group, data = data)
  pairwise_pvalues <- pairwise.wilcox.test(data$values, data$group, p.adjust.method = "bonferroni",exact=FALSE)
  p_matrix <- pairwise_pvalues$p.value
  
  extraxt_P <- function(x) {
    rn <- row.names(x)
    cn <- colnames(x)
    an <- unique(c(cn, rn))
    myval <- x[!is.na(x)]
    mymat <- matrix(1, nrow = length(an), ncol = length(an), dimnames = list(an, an))
    for(ext in 1:length(cn)) {
      for(int in 1:length(rn)) {
        if(is.na(x[row.names(x) == rn[int], colnames(x) == cn[ext]])) next
        mymat[row.names(mymat) == rn[int], colnames(mymat) == cn[ext]] <- x[row.names(x) == rn[int], colnames(x) == cn[ext]]
        mymat[row.names(mymat) == cn[ext], colnames(mymat) == rn[int]] <- x[row.names(x) == rn[int], colnames(x) == cn[ext]]
      }
    }
    return(mymat)
  }
  
  p_matrix <- extraxt_P(p_matrix)
  group_means <- tapply(data$values, data$group, mean)
  sorted_groups <- names(sort(group_means, decreasing = TRUE))
  sorted_p_matrix <- p_matrix[sorted_groups, sorted_groups]
  letters_result <- multcompLetters(sorted_p_matrix)
  error=as.data.frame(letters_result$Letters)
  error$group=row.names(error)
  error2=merge(error,df2,by="group")
  colnames(error2)=c("group","label","values","sd")
}

最终要的就是error2数据表,长这样:

再把error2数据表各列添加到绘图过程中的geom_text()函数中就行了,具体操作如下:

#做一个柱状图
p1 <- ggplot(df, aes(x=group, y=mean))+  #aes里面设置你想要的x轴和y轴
  geom_bar(aes(fill=group),stat = "identity", position = position_dodge())+   
  geom_errorbar(aes(ymin=mean-sd,ymax=mean+sd,group=group),  #加误差线
                position=position_dodge(width=0.8),linewidth = 0.8, width = 0.2)+
 #想加显著性请先求出显著性字母,并运行下一句添加显著性字母 
  geom_text(data=error2,aes(x=group,y=values+sd,label=label),size=8,color="red",vjust=-0.5)

多组放下篇啦!

做学习小记,欢迎交流指正!

<think>好的,我现在要解决用户的问题:在R语言中如何创建带显著性标注的箱线图。用户提到了使用ggplot2和ggsignif包,所以首先我需要回顾这两个包的使用方法,以及相关的步骤。 首先,用户的需求是绘制箱线图添加显著性标记。根据引用[1]和[4],使用ggplot2和ggsignif是正确的途径。我需要确认这两个包的安装和加载步骤,确保用户能够正确运行代码。然后,数据的准备也很重要,比如用户提到的鸢尾花数据集,这是一个常用的示例数据,应该没有问题。 接下来,绘制基本的箱线图。使用ggplot2的geom_boxplot函数,映射Species到x轴,Sepal.Length到y轴。这一步应该没问题,但需要检查是否有拼写错误或者变量名错误。例如,Species的首字母大写,Sepal.Length是否正确。 然后添加显著性标记,这里用ggsignif的geom_signif函数。需要指定比较的组别,比如这里用户可能想比较setosa和versicolor,versicolor和virginica等。参数comparisons应该是一个列表,里面包含需要比较的组对。同时,test参数指定统计检验方法,比如t.test,或者wilcox.test。test.args可能需要根据检验方法调整,比如是否假设方差齐性等。这里例子中用了t.test,但用户的数据是否符合t.test的假设呢?可能需要提醒用户根据数据情况选择合适的检验方法。 接下来,annotate参数用于设置标注的显示方式,比如星号表示显著性水平。textsize调整字体大小,y_position调整标注的位置,避免重叠。这里可能需要用户根据实际图形调整位置,因为不同的数据范围可能需要不同的y值。 代码中的stat参数设置为"identity",意味着直接使用计算好的p值,而不是让函数自己计算。这可能是因为用户希望自定义比较的组,或者已经知道p值。但如果是让ggsignif自动计算,可能需要调整参数。不过根据示例,用户希望自动计算,所以可能需要确认参数是否正确。 然后,用户可能需要调整主题和标签,比如使用theme_bw()让背景更干净,labs添加标题和坐标轴标签。这部分主要是美化图形,不影响显著性标记的添加,但提升可读性。 最后,用户可能需要保存图形,使用ggsave函数,指定文件名、图形对象、尺寸和分辨率。 在注意事项部分,需要提醒用户比较组的正确性,检验方法的选择,以及标注位置的美观。比如,如果比较的组很多,标注可能会重叠,需要手动调整y_position的值。此外,检验方法是否符合数据分布,比如非正态分布可能需要非参数检验。 然后,生成相关问题。根据用户可能遇到的后续问题,比如如何更换检验方法,处理多组比较,调整标注样式,导出高清图,或者处理不显著的情况。这些都是用户在添加显著性标记时可能遇到的问题,需要提前考虑。 现在检查是否有遗漏的步骤或可能的错误点。例如,是否需要在geom_signif中设置正确的映射,或者是否需要调整颜色、线条类型等。此外,引用是否正确,用户提供的引用[1]和[4]都是相关的,需要正确标注。 最后,确保回答结构清晰,分步骤说明,代码正确无误,且注意事项涵盖了常见问题。这样用户能够按照步骤操作,同时了解可能出现的问题和解决方法。</think>在R语言中,使用`ggplot2`和`ggsignif`包可以方便地创建带显著性标注的箱线图。以下是具体步骤: --- ### **步骤1:安装加载包** ```r # 安装包(若未安装) install.packages("ggplot2") install.packages("ggsignif") # 加载包 library(ggplot2) library(ggsignif) ``` --- ### **步骤2:准备数据** 以鸢尾花数据集`iris`为例,比较不同物种(Species)的萼片长度(Sepal.Length): ```r data(iris) head(iris) # 查看数据结构 ``` --- ### **步骤3:绘制基础箱线图** ```r p <- ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) + geom_boxplot() + theme_bw() # 设置简洁主题 print(p) ``` --- ### **步骤4:添加显著性标记** 使用`geom_signif`函数标注组间显著性: ```r p + geom_signif( comparisons = list( c("setosa", "versicolor"), # 比较组1 c("versicolor", "virginica") # 比较组2 ), map_signif_level = TRUE, # 自动标注星号(*表示p<0.05,**p<0.01等) test = "t.test", # 使用t检验 test.args = list(var.equal = FALSE), # 假设方差不齐 annotations = c("*", "**"), # 自定义标注文本 textsize = 4, # 标注字体大小 y_position = c(8, 9) # 标注的垂直位置(避免重叠) ) ``` --- ### **步骤5:调整图形样式(可选)** ```r final_plot <- p + geom_signif(...) + # 同上 labs(title = "不同物种的萼片长度分布", x = "物种", y = "萼片长度") + theme(legend.position = "none") # 隐藏图例 print(final_plot) ``` --- ### **注意事项** 1. **比较组的设置**:`comparisons`参数需明确指定要比较的组名。 2. **检验方法选择**:若数据非正态分布,可将`test`改为`wilcox.test`(非参数检验)[^4]。 3. **标注位置调整**:通过`y_position`参数避免标注重叠,数值需根据数据范围调整。 --- ### **保存图形** ```r ggsave("boxplot_with_significance.png", plot = final_plot, width = 8, height = 6, dpi = 300) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值