更改 ggplot2 中的图例以具有相似标签组

changing the legends in ggplot2 to have groups of similar labels

此问题基于

中提供的解决方案

如下

library(ggplot2)
library(gtable)
library(grid)

diamonds$cut = factor(diamonds$cut, levels=c("Fair","Good"," ","Very Good",
                                             "Premium","Ideal"))

p = ggplot(diamonds, aes(color, fill = cut)) + 
       geom_bar() + 
       scale_fill_manual(values = 
              c(hcl(seq(15, 325, length.out = 5), 100, 65)[1:2], 
              "white",
              hcl(seq(15, 325, length.out = 5), 100, 65)[3:5]),
              drop = FALSE) +
  guides(fill = guide_legend(ncol = 2, title.position = "top")) +
  theme(legend.position = "bottom", 
        legend.key = element_rect(fill = "white"))

# Get the ggplot grob
g = ggplotGrob(p)

# Get the legend
leg = g$grobs[[which(g$layout$name == "guide-box")]]$grobs[[1]]

# Set up the two sub-titles as text grobs
st = lapply(c("First group", "Second group"), function(x) {
   textGrob(x, x = 0, just = "left", gp = gpar(cex = 0.8)) } )

# Add a row to the legend gtable to take the legend sub-titles
leg = gtable_add_rows(leg, unit(1, "grobheight", st[[1]]) + unit(0.2, "cm"), pos =  3)

# Add the sub-titles to the new row
leg = gtable_add_grob(leg, st, 
            t = 4, l = c(2, 6), r = c(4, 8), clip = "off")

# Add a little more space between the two columns
leg$widths[[5]] = unit(.6, "cm")

# Move the legend to the right
 leg$vp = viewport(x = unit(.95, "npc"), width = sum(leg$widths), just = "right")

# Put the legend back into the plot
g$grobs[[which(g$layout$name == "guide-box")]] = leg

# Draw the plot
grid.newpage()
grid.draw(g)

这提供了数字(来自那里)。

不过,我想做两件事。

  1. 第一组:我想将“一般”和“良好”分别重新标记为“非常好”和“高级”。因此,它们在每个组(第一和第二)中都非常好和优质。

  2. 我想做的第二件事是将它们放在一行中(第一组和第二组的两列并排放置,所有内容都在一行中,以节省垂直space.

我该怎么做?如果我的问题不清楚,请告诉我。我觉得我离这里很近了,但是这个解决方案并不能完全回答我的问题。非常感谢!

首先,您可以通过 scale_fill_manuallabels 参数简单地更改图例中出现的标签。其次,与其摆弄 gtable,如果你想将这些组排成一行,这可能要求更高,你可以使用 ggnewscale 包,正如 在与您添加的 post 相同 link。虽然这个答案还使用了 relayer 包,但我的方法有点不同,因为我重新排列了层的顺序,这样就不需要 relayer 包了:

library(ggplot2)
library(ggnewscale)

diamonds$cut = factor(diamonds$cut, levels=c("Fair","Good", "Very Good",
                                             "Premium","Ideal"))

labels <- levels(diamonds$cut)
labels <- setNames(labels, labels)
labels["Fair"] <- "Very Good"
labels["Good"] <- "Premium"

colors <- hcl(seq(15, 325, length.out = 5), 100, 65)
colors <- setNames(colors, levels(diamonds$cut))

ggplot() + 
  geom_bar(data = diamonds, aes(color, fill = cut)) + 
  scale_fill_manual(aesthetics = "fill", values = colors, labels = labels[1:2],
                    breaks = names(colors)[1:2], name = "First Group:",
                    guide = guide_legend(title.position = "left", order = 1)) +
  new_scale_fill() +
  geom_bar(data = diamonds, aes(color, fill = cut)) + 
  scale_fill_manual(aesthetics = "fill", values = colors, labels = labels[3:5],
                    breaks = names(colors)[3:5], name = "Second Group:",
                    guide = guide_legend(title.position = "left", order = 0)) +
  theme(legend.position = "bottom", 
        legend.direction = "horizontal",
        legend.key = element_rect(fill = "white"))