基于颜色和形状的嵌套图例

RvV*_*RvV 5 r legend ggplot2

我想制作嵌套组(组和子组)的 xy 图,其中点按组着色并按子组形状。一个最小的例子如下:

DATA<-data.frame(
  Group=c(rep("group1",10),rep("group2",10),rep("group3",10) ),
  Subgroup = c(rep(c("1.1","1.2"),5), rep(c("2.1","2.2"),5), rep(c("3.1","3.2"),5)),
  x=c(rnorm(10, mean=5),rnorm(10, mean=10),rnorm(10, mean=15)),
  y=c(rnorm(10, mean=3),rnorm(10, mean=4),rnorm(10, mean=5))
)
ggplot(DATA, aes(x=x, y=y,colour=Group, shape=Subgroup) ) +
  geom_point(size=3) 
Run Code Online (Sandbox Code Playgroud)

坐标图1

然而,因为实际上我有更多的子组,无法根据可用形状轻松识别,所以我想在每个组中重复相同的形状。下面是相同的代码,但有一个附加列(形状)指定形状:

DATA<-data.frame(
  Group=c(rep("group1",10),rep("group2",10),rep("group3",10) ),
  Subgroup = c(rep(c("1.1","1.2"),5), rep(c("2.1","2.2"),5), rep(c("3.1","3.2"),5)),
  Shape = as.character(c(rep(c(1,2),15) ) ), 
  x=c(rnorm(10, mean=5),rnorm(10, mean=10),rnorm(10, mean=15)),
  y=c(rnorm(10, mean=3),rnorm(10, mean=4),rnorm(10, mean=5))
)

ggplot(DATA, aes(x=x, y=y,colour=Group, shape=Shape) ) +
  geom_point(size=3)
Run Code Online (Sandbox Code Playgroud)

坐标图2

现在形状和颜色都是我想要的。但是,图例不再列出子组。我想要的是一个图例,列出每个相应组下的所有子组。就像是:

  • 组1
    • 1.1
    • 1.2
  • 组2
    • 2.1
    • 2.2
  • 第3组
    • 3.1
    • 3.2

(理想情况下,这将是一个嵌套图例。如果嵌套图例不可能,也许它们可以是三个单独的图例,以组作为标题)

这是可以实现的吗?如何实现?

谢谢

ste*_*fan 1

实现您想要的结果的一种选择是通过该ggnewscale软件包,该软件包允许使用多种比例和图例来实现相同的美感。

为此我们必须

  1. 将数据分割并通过单独的图层GROUP绘制每个数据。GROUPgeom_point
  2. 此外,每个GROUP都有一个单独的形状比例和图例,可以通过 实现ggnewscale::new_scale
  3. 我们没有利用美学,而是color将每个组的颜色设置为参数,为此我使用了命名的颜色向量
  4. 我没有复制和粘贴每个组的代码,而是使用purrr::imap循环分割的数据集并动态添加图层。

另请注意:一般来说,图例的顺序默认是通过“魔法算法”设置的。为了让组按正确的顺序排列,我们必须通过 显式设置顺序guide_legend

library(ggplot2)
library(ggnewscale)
library(dplyr)
library(purrr)
library(tibble)

DATA_split <- split(DATA, DATA$Group)

# Vector of colors and shapes
colors <- setNames(scales::hue_pal()(length(DATA_split)), names(DATA_split))
shapes <- setNames(scales::shape_pal()(length(unique(DATA$Shape))), unique(DATA$Shape))

ggplot(mapping = aes(x = x, y = y)) +
  purrr::imap(DATA_split, function(x, y) {
    # Get Labels
    labels <- x[c("Shape", "Subgroup")] %>% 
      distinct(Shape, Subgroup) %>% 
      deframe()
    # Get order
    order <- as.numeric(gsub("^.*?(\\d+)$", "\\1", y))
    list(
      geom_point(data = x, aes(shape = Shape), color = colors[[y]], size = 3),
      scale_shape_manual(values = shapes, labels = labels, name = y, guide = guide_legend(order = order)),
      new_scale("shape")
    )
  })
Run Code Online (Sandbox Code Playgroud)

数据

set.seed(123)

DATA <- data.frame(
  Group = c(rep("group1", 10), rep("group2", 10), rep("group3", 10)),
  Subgroup = c(rep(c("1.1", "1.2"), 5), rep(c("2.1", "2.2"), 5), rep(c("3.1", "3.2"), 5)),
  Shape = as.character(c(rep(c(1, 2), 15))),
  x = c(rnorm(10, mean = 5), rnorm(10, mean = 10), rnorm(10, mean = 15)),
  y = c(rnorm(10, mean = 3), rnorm(10, mean = 4), rnorm(10, mean = 5))
)
Run Code Online (Sandbox Code Playgroud)