在多于两行中使用上标时修复图例标题-R ggplot2

时间:2018-12-25 00:31:50

标签: r ggplot2 expression legend

我正在绘制研究区域的地图,但是在编辑图例标题时遇到问题。 我需要将其设置为“用四行代码编写的40年休耕期中的预期水果生产力(水果ha ^ -1)。我可以使用bquote()将-1绘制为上标。但是它创建了一个额外的空间,我无法弄清楚如何删除它,只有在标题分成多行时才会出现多余的空格。 另外,expression(atop())创建上标,但是一旦我尝试将其划分为两行以上,就不会显示第三行和第四行。

这是使用bquote()具有额外空间的Map Map with the extra space in the legend title

这是使用expression(atop())具有四行标题的Map enter image description here

我确实尝试了互联网上的其他解决方案,包括this post。但是他们都用多余的空间绘制了第四行,或者只绘制了第一行或第二行。

下面是我正在使用的代码。欢迎任何帮助。 评论是不同的尝试。

数据= spatial_dist_fallows.csv

library(sf) #sf = simple feature
library(ggplot2)
library(dplyr)

PAECM_fallows <-read.csv("spatial_dist_fallows.csv")
PAECM_fallows_sp <- st_as_sf(PAECM_fallows,coords = c("X", "Y"),crs = "+proj=longlat +datum=WGS84 +no_defs")

custom_bins_fruit = c(0,60,120,180,240,1400)
PAECM_fallows_fruit <- PAECM_fallows_sp %>% 
  mutate(prod_cat_fallow = cut(prod_40, breaks= custom_bins_fruit),
         age_cat_fallow = cut(age, breaks = c(11,17,22,29,60)))


prod_map_PAECM_fruit<-ggplot()+
  geom_sf(data = PAECM_fallows_fruit,aes(size = prod_cat_fallow), shape = 18, show.legend = "point")+
  scale_size_manual(values= c(2,3,4,5,6),
                  # name = "Projected fruit\nproductivity in\nfallows in 40 yrs \n(fruits ha^-1)",
                  name = bquote("Projected fruit\nproductivity in\nfallows in 40 yrs \n( fruits"*ha^-1*")"),
                  # name = expression(paste("Projected fruit productivity\nin fallows in 40 yrs\n"),bquote(paste("("*fruits~ha^-1*")"))),#(Fruits/ha)
                  name = expression(atop("Projected fruit",
                                     "productivity in",
                                     "fallows in 40 yrs",
                                     "( fruits ha"^-1,")")),
                  breaks= c(NA,"(0,60]","(60,120]","(120,180]","(180,240]","(240,1.4e+03]"),
                  labels= c("NA","\u2264 60","60 - 120","120 - 180","180 - 240","> 240"),
                  guide = guide_legend(override.aes = list(linetype = "blank", shape = 18, fill = NA)))+
  # labs(size = expression(atop("Projected fruit\nproductivity in\nfallows in 40 yrs\n(fruits"*ha^-1*")", sep="")))+ #comment name line at the scale_size_manual
  # labs(size = bquote("Projected fruit productivity \nin fallows in 40 yrs \n( fruits"*ha^-1*")"))+ #comment name line at the scale_size_manual
  ggplot2::theme_minimal()+
  ggplot2::theme(legend.text.align=0.5,
                 legend.title.align = 0.5,
                 plot.background = element_blank(),
                 panel.grid = element_line(colour = "white"),
                 panel.background = element_rect(fill = "grey87", color = "white"))+#,
  coord_sf(xlim = c(-68.45,-68.2), ylim = c(-11.05,-10.8))
prod_map_PAECM_fruit

其他问题。一旦我开始使用bquote,就无法使用theme(legend.title.align = 0.5)对齐标题文本,还有其他想法吗?

2 个答案:

答案 0 :(得分:2)

经过一些其他尝试,我确实为图例标题提出了以下解决方案。

name = expression(atop("",
                       atop(textstyle("Projected fruit"),
                            atop(textstyle("productivity in"),
                                 atop(textstyle("fallows in 40 yrs"),
                                      atop(textstyle("(fruits ha"^-1*")"))))))),

我使用textstyle()来绘制所有具有相同大小的文本,否则每次调用atop()时它都会被绘制得较小。 Atop()在第一行和第二行之间创建一个空格,这就是为什么代码的第一行是atop(“”,所以第一行将是空白的原因。

这是下面地图的最终代码。

library(sf) #sf = simple feature
library(ggplot2)
library(dplyr)

PAECM_fallows <-read.csv("spatial_dist_fallows.csv")
PAECM_fallows_sp <- st_as_sf(PAECM_fallows,coords = c("X", "Y"),crs = "+proj=longlat +datum=WGS84 +no_defs")

custom_bins_fruit = c(0,60,120,180,240,1400)
PAECM_fallows_fruit <- PAECM_fallows_sp %>% 
  mutate(prod_cat_fallow = cut(prod_40, breaks= custom_bins_fruit),
     age_cat_fallow = cut(age, breaks = c(11,17,22,29,60)))


prod_map_PAECM_fruit_legend_test<-ggplot()+
  geom_sf(data = PAECM_fallows_fruit,aes(size = prod_cat_fallow), shape = 18, show.legend = "point")+
  scale_size_manual(values= c(2,3,4,5,6),
              name = expression(atop("",
                                     atop(textstyle("Projected fruit"),
                                          atop(textstyle("productivity in"),
                                               atop(textstyle("fallows in 40 yrs"),
                                                    atop(textstyle("(fruits ha"^-1*")"))))))),
              breaks= c(NA,"(0,60]","(60,120]","(120,180]","(180,240]","(240,1.4e+03]"),
              labels= c("NA","\u2264 60","60 - 120","120 - 180","180 - 240","> 240"),
              guide = guide_legend(override.aes = list(linetype = "blank", shape = 18, fill = NA)))+
  ggplot2::theme_minimal()+
  ggplot2::theme(legend.text.align=0.5,
             legend.title.align = 0.5,
             plot.background = element_blank(),
             panel.grid = element_line(colour = "white"),
             panel.background = element_rect(fill = "grey87", color = "white"))+#,
  coord_sf(xlim = c(-68.45,-68.2), ylim = c(-11.05,-10.8))
prod_map_PAECM_fruit_legend_test

enter image description here

答案 1 :(得分:0)

或者,您可以使用注释功能cowplot::draw_label()ggplot2::annotation_custom()。我认为ggplot2 two-line label with expression中对这些方法的解释也很有帮助。

1)使用cowplot::draw_label()

的解决方案
library(ggplot2)
library(cowplot)
#> Warning: package 'cowplot' was built under R version 3.5.2
#> 
#> 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())

# Build a simple plot as example
p <- ggplot(mtcars, aes(x = wt, y = mpg, size = factor(gear))) + 
  geom_point() +
  labs(size = element_blank()) + # remove default legend title
  # Make enough space for the custom legend title by tweaking the right margin
  theme(legend.margin = margin(t = 0, r = 26, b = 0, l = 0, unit = "mm"))
  # Adjust further theme elements if needed, like text size, font, etc

# The lines of text and expression that constitute your custom legend title
lines <- list(
  "Projected fruit",
  "productivity in",
  "fallows in 40 yrs",
  expression("(fruits ha" ^-1 ~ ")")
)

# Using relative coordinates ranging from 0 to 1 (relative to the entire canvas).
# There is some guesswork with the coordinates until we get them right.
min_y <- 0.6
step <- 0.04 # dictates the line spacing; need to play with it until you get it right
ys <- seq(from = min_y + step * 4, to = min_y, by = -step)
x <- 0.87

# Add the annotations that will actually constitute the legend title.
gg <- ggdraw(p)
#> Warning: Using size for a discrete variable is not advised.
# Neglect the warning in this example.
for (i in 1:4){
  gg <- gg + draw_label(lines[[i]], x = x, y = ys[i])
}
gg

请注意,cowplot::draw_label()也可以与设置剪裁coord_cartesian(clip = "off")结合使用,从而可以在画布上的任何位置绘图(请参见带有ggplot2::annotation_custom()的下一个示例)。在这种情况下,我们不再使用相对坐标,而是使用绘图/数据中的相对坐标(绝对坐标)。


2)使用ggplot2::annotation_custom()

的解决方案

请注意,cowplot::draw_label()在幕后使用ggplot2::annotation_custom(),因此它几乎是相同的注释技术,但有点冗长。我们需要开始剪裁。这次我们不再使用相对坐标,而是使用绘图/数据中的相对坐标(绝对坐标)。

以上方的p绘图示例为基础:

min_y <- 24
step <- 1 # dictates the line spacing; need to play with it until you get it right
ys <- seq(from = min_y + step * 4, to = min_y, by = -step)
x <- 6.2

# set clipping off - allows plotting anywhere on the canvas
pp <- p + coord_cartesian(clip = "off")
for (i in 1:4){
  pp <- pp + annotation_custom(grid::textGrob(lines[[i]]), 
                               xmin = x, xmax = x, ymin = ys[i], ymax = ys[i])
}
pp
#> Warning: Using size for a discrete variable is not advised.

reprex package(v0.2.1)于2019-01-15创建