具有表达式的 ggplot2两行标签

我想用 expression()语句在两行上写一个轴标签。但是,plotmathexpression不允许这样做(例如,带下标的文本出现在最右边)。我发现 这个讨论大约在2005年出现过类似的问题,但是它们所提供的工作并没有转化为我在 ggplot2中的应用程序。最近的一个问题解决了多行表达式语句的不同排列问题,但是这里也不适用。

例如:

p <- ggplot(mtcars,aes(x=wt,y=mpg))+
geom_point()+
xlab(expression(paste("A long string of text goes here just for the purpose \n of illustrating my point Weight "[reported])))
try(ggsave(plot=p,filename=<some file>,height=4,width=6))

产生一个图像,其中下标“已报告”被踢出到右边,当我想要它坐在旁边的前一个单词。 ggplot2 two line label with expression

130286 次浏览

我觉得这是个窃听器。(或者是“不支持多行表达式”的结果,正如你链接到的对话中所说的那样)。

加文•辛普森(Gavin Simpson)提到的变通办法是:

#For convenience redefine p as the unlabeled plot
p <- ggplot(mtcars,aes(x=wt,y=mpg))+geom_point()


#Use atop to fake a line break
p + xlab(expression(atop("A long string of text for the purpose", paste("of illustrating my point" [reported]))))

enter image description here

可以对下标使用真正的换行符。在下面这个与你的例子形式相同的简短例子中,下标正确地放置在文本的其余部分的旁边,但是两行文本没有正确地居中:

p + xlab(expression(paste("line1 \n line2 a" [b])))

enter image description here

我认为在这两种情况下,当文本的上行比下行长时,下标的位置都是错误的。比较一下

p + xlab(expression(paste("abc \n abcd" [reported])))

enter image description here

p + xlab(expression(paste("abc \n ab" [reported])))

enter image description here

下标总是在上行右端对齐。

p + xlab(expression(paste("abcdefghijklmnop \n ab" [reported])))

enter image description here

你可以用这招,

library(gridExtra)
library(grid)


element_custom <- function() {
structure(list(), class = c("element_custom", "element_text"))
}


element_grob.element_custom <- function(element, label="", ...)  {


mytheme <- ttheme_minimal(core = list(fg_params = list(parse=TRUE,
hjust=0, x=0.1)))
disect <- strsplit(label, "\\n")[[1]]
tableGrob(as.matrix(disect), theme=mytheme)
}


# default method is unreliable
heightDetails.gtable <- function(x) sum(x$heights)


ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
geom_line() +
labs(x= "First~line \n italic('and a second') \n integral(f(x)*dx, a, b)")+
(theme_grey() %+replace% theme(axis.title.x = element_custom()))

enter image description here

1)使用 cowplot::draw_label()的解决方案

还可以使用包 cowplot中的注释函数 draw_label()(在 这个的讨论中提出)。我们可以调用 cowplot::draw_label(),因为我们有很多行文本。当 cowplot::draw_label()cowplot::ggdraw()结合使用时,它可以在画布/工作表上的任何位置进行注释,其坐标范围从0到1(相对于整个画布)。

需要调整注释位置并为自定义轴标题留出足够的空间。

请注意,cowplot包目前改变了缺省 ggplot 主题,因此,如果需要,在加载包之后使用 theme_set(),正如前面提到的 给你

另请注意,函数 cowplot::draw_label()在引擎盖下使用 ggplot2::annotation_custom()。我将在下面的第二部分提到更多关于这方面的内容。

library(ggplot2)
library(cowplot)
#>
#> Attaching package: 'cowplot'
#> The following object is masked from 'package:ggplot2':
#>
#>     ggsave


# If needed, revert to default theme (cowplot modifies the theme);
# theme_set(theme_grey())


p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
# Make enough space for the custom two lines axis title
p <- p +
xlab("") + # empty label
# Tweak the margins (push the label down by forcing a wider top margin)
theme(axis.title.x = element_text(size = 10, # also adjust text size if needed
margin = margin(t = 10, r = 0, b = 0, l = 0,
unit = "mm")))


# The two lines we wish on the plot
line_1 <- "A long string of text for the purpose"
line_2 <- expression(paste("of illustrating my point" [reported]))
# Or avoid paste() (is not actually needed)
# line_2 <- expression("of illustrating my point" [reported])


# Call cowplot::draw_label two times to plot two lines of text
ggdraw(p) +
draw_label(line_1, x = 0.55, y = 0.075) + # use relative coordinates for positioning
draw_label(line_2, x = 0.55, y = 0.025)

请注意,cowplot::draw_label()还可以与设置剪切关闭 coord_cartesian(clip = "off")结合使用,coord_cartesian(clip = "off")允许在画布上的任何位置绘制图形。这次我们不再使用相对坐标,而是使用 plot/data (绝对坐标)中的坐标:

# Other two expressions
line_1b <- expression(bolditalic('First line'))
line_2b <- expression(integral(f(x)*dx, a, b))


p + coord_cartesian(clip = "off") + # allows plotting anywhere on the canvas
draw_label(line_1b, x = 3.5, y = 8.2) + # use absolute coordinates for positioning
draw_label(line_2b, x = 3.5, y = 6)

Reprex 软件包于2019-01-14创作(0.2.1)


2)使用 ggplot2::annotation_custom()的解决方案

如前所述,cowplot::draw_label()ggplot2::annotation_custom()的包装器。因此,我们可以直接使用 ggplot2::annotation_custom()来代替 cowplot::draw_label(),同时设置剪切 coord_cartesian(clip = "off"),这在合并 这个请求时变得可用。

但是,这种方法更加详细,有更多的坐标参数,我们需要使用 grid::textGrob()

# Some other two lines we wish on the plot as OX axis title
line_1c <- expression("Various fonts:" ~ bolditalic("bolditalic") ~ bold("bold") ~ italic("italic"))
line_2c <- expression("this" ~~ sqrt(x, y) ~~ "or this" ~~ sum(x[i], i==1, n) ~~ "math expression")
# the ~~ ads a bit more space than ~ between the expression's components


p + coord_cartesian(clip = "off") +
annotation_custom(grid::textGrob(line_1c), xmin = 3.5, xmax = 3.5, ymin = 7.3, ymax = 7.3) +
annotation_custom(grid::textGrob(line_2c), xmin = 3.5, xmax = 3.5, ymin = 5.5, ymax = 5.5)

Reprex 软件包于2019-01-14创作(0.2.1)

ggtext包提供了一个不同的选项,它允许 HTML 标记格式化/自定义标签和文本。

library(ggtext)
ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
xlab("A long string of text goes here just for the purpose<br>of illustrating my point Weight<sub>reported</sub>") +
theme(axis.title.x = element_markdown())

enter image description here