如何在ggplot2的annotate中用空格分隔带右上标的表达式
问题
需要在ggplot2图形的同一坐标位置添加三个表达式作为注释,每个表达式中的星号需显示为右上标(代表模型输出的显著系数)。目前使用paste()结合parse=TRUE实现,用斜杠分隔时可正常运行,但替换为空格(或调整空格数量)就会报错,希望实现用空格分隔三个表达式且星号保持右上标。
可正常运行的代码(斜杠分隔)
# 可正常运行的代码(斜杠分隔) Dummy_df <- as.data.frame(cbind("Var1" = c(0, 177), "Var2" = c(0, 177))) ggplot(Dummy_df, aes(x = Var1, y = Var2)) + geom_point(size = 0.1, colour = "white") + theme_light() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), panel.background = element_blank(), axis.line = element_blank()) + xlab(" ") + ylab(" ") + annotate("text", label = paste('2.16^"***"', "/", '5.48^"***"', "/", '1.92^"***"'), x = 40.75, y = 138, parse = TRUE, size = 5)
报错代码及错误信息
尝试用空格分隔时,以下两段代码均报错:
代码1(显式添加空格)
ggplot(Dummy_df, aes(x = Var1, y = Var2)) + geom_point(size = 0.1, colour = "white") + theme_light() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), panel.background = element_blank(), axis.line = element_blank()) + xlab(" ") + ylab(" ") + annotate("text", label = paste('2.16^"***"', " ", '5.48^"***"', " ", '1.92^"***"'), x = 40.75, y = 138, parse = TRUE, size = 5)
代码2(默认空格分隔)
ggplot(Dummy_df, aes(x = Var1, y = Var2)) + geom_point(size = 0.1, colour = "white") + theme_light() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), panel.background = element_blank(), axis.line = element_blank()) + xlab(" ") + ylab(" ") + annotate("text", label = paste('2.16^"***"', '5.48^"***"', '1.92^"***"'), x = 40.75, y = 138, parse = TRUE, size = 5)
错误信息
Error in `annotate()`: ! 转换geom到grob时出现问题。 ℹ 错误发生在第2层。 Caused by error in `parse()`: ! <text>:1:14: 意外的数值常量 1: 2.16^"***" 5.48 ^ Run `rlang::last_trace()`查看错误发生位置。
解决方案
报错核心原因:当parse=TRUE时,R会将label解析为plotmath语法,而plotmath中的空格是语法分隔符(用于分隔表达式元素),不是用于显示的空格。直接用空格分隔两个表达式会导致语法错误,因为plotmath无法识别无运算符连接的两个独立表达式。
以下是三种可行的解决方法:
方法1:用plotmath的~表示显示空格
在paste()中用'~'作为分隔符,plotmath会将~解析为显示用的空格:
ggplot(Dummy_df, aes(x = Var1, y = Var2)) + geom_point(size = 0.1, colour = "white") + theme_light() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), panel.background = element_blank(), axis.line = element_blank()) + xlab(" ") + ylab(" ") + annotate("text", label = paste('2.16^"***"', '~', '5.48^"***"', '~', '1.92^"***"'), x = 40.75, y = 138, parse = TRUE, size = 5)
方法2:在plotmath中使用paste()函数
直接构造plotmath的paste()表达式,让解析时执行该函数组合带空格的文本:
ggplot(Dummy_df, aes(x = Var1, y = Var2)) + geom_point(size = 0.1, colour = "white") + theme_light() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), panel.background = element_blank(), axis.line = element_blank()) + xlab(" ") + ylab(" ") + annotate("text", label = 'paste(2.16^"***", " ", 5.48^"***", " ", 1.92^"***")', x = 40.75, y = 138, parse = TRUE, size = 5)
方法3:使用ggtext包的Markdown语法
如果不想用plotmath,可以用ggtext包支持的Markdown上标语法,无需启用parse=TRUE:
# 先安装并加载ggtext包 # install.packages("ggtext") library(ggtext) ggplot(Dummy_df, aes(x = Var1, y = Var2)) + geom_point(size = 0.1, colour = "white") + theme_light() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_blank(), panel.background = element_blank(), axis.line = element_blank()) + xlab(" ") + ylab(" ") + annotate("richtext", label = "2.16<sup>***</sup> 5.48<sup>***</sup> 1.92<sup>***</sup>", x = 40.75, y = 138, size = 5, fill = NA, label.color = NA)
这里设置fill=NA和label.color=NA是为了去掉文本框的背景和边框,和普通text效果一致。
内容的提问来源于stack exchange,提问作者Yevgeniya
相关产品推荐
相关产品推荐

