使用 ggnewscale::new_scale() 和 R 中的 ggplot2 将图例拆分为图中的两列或多列

Dav*_*vid 5 r ggplot2 ggnewscale

在遵循 Stefan 对这篇文章的非常有用的回答(他使用的地方)之后ggnewscale::new_scale(),我现在遇到了以下问题:

“如何将自定义图例排列成ggnewscale多个垂直列?” 就像通常使用 ggplot2 中的命令完成的那样guides(scale_shape_manual=guide_legend(ncol=2))

最小可重现示例:

# fictional data in the scheme of /sf/ask/4676314121/

mutated <- list()
for(i in 1:10) {
  mutated[[i]] <- data.frame(Biological.Replicate = rep(1,4),
                           Reagent.Conc = c(10000, 2500, 625, 156.3),
                           Reagent = rep(1,8),
                           Cell.type = rep(LETTERS[i],4),
                           Mean.Viable.Cells.1 = rep(runif(n = 10, min = 0, max = 1),4))
}
mutated <- do.call(rbind.data.frame, mutated)
Run Code Online (Sandbox Code Playgroud)

用户“stefan”回答后修改后的代码如下所示:

# from /sf/answers/4676602661/

library(ggplot2)
library(ggnewscale)
library(dplyr)
library(magrittr)

mutated <- mutated %>% 
  mutate(Cell.type = as.factor(Cell.type),
         Reagent = factor(Reagent, 
                          levels = c("0", "1", "2")))

mean_mutated <- mutated %>%
  group_by(Reagent, Reagent.Conc, Cell.type) %>%
  split(.$Cell.type)

layer_geom_scale <- function(Cell.type) {
  list(geom_point(mean_mutated[[Cell.type]], mapping = aes(shape = Reagent)),
       geom_line(mean_mutated[[Cell.type]], mapping = aes(group = Reagent, linetype = Reagent)),
       scale_linetype_manual(name = Cell.type, values = c("solid", "dashed", "dotted"), drop=FALSE),
       scale_shape_manual(name = Cell.type, values = c(15, 16, 4), labels = c("0", "1", "2"), drop=FALSE) 
  )
}

my_plot <- 
  ggplot(mapping = aes(
    x = as.factor(Reagent.Conc),
    y = Mean.Viable.Cells.1)) +
  layer_geom_scale(unique(mutated$Cell.type)[1])

for(current_Cell.type_index in 2:length(unique(mutated$Cell.type))) {
  my_plot <- 
    my_plot +
    ggnewscale::new_scale("shape")  +
    ggnewscale::new_scale("linetype") +
    layer_geom_scale(unique(mutated$Cell.type)[current_Cell.type_index])
}

my_plot


Run Code Online (Sandbox Code Playgroud)

这导致:

现在,我希望图例在两列中并排显示,我尝试了这个(没有成功):

my_plot +
  guides(scale_shape_manual=guide_legend(ncol=2))
Run Code Online (Sandbox Code Playgroud)

编辑:我希望图例的排列方式的图片

有谁可以帮助我吗?

谢谢!

mar*_*ery 2

注意:此答案解决了在问题编辑 # 4 及以后进行澄清之前的问题。

横向图例

添加theme(legend.box = "horizontal")将使图例元素并排显示。

多列和ggnewscale

全局使用将导致 ggnewscale 更新尺度guides尺度发生修改。在这种情况下,只有变量RKO将被更新:

layer_geom_scale <- function(cell_type, color) {
  list(geom_point(mean_mutated[[cell_type]], mapping = aes(shape = Reagent), color = color),
       geom_line(mean_mutated[[cell_type]], mapping = aes(group = Reagent, linetype = Reagent), color = color),
       scale_linetype_manual(name = cell_type, values = c("solid", "dashed", "dotted"), drop=FALSE),
       scale_shape_manual(name = cell_type, values = c(15, 16, 4), labels = c("0", "1", "2"), drop=FALSE)
  )
}

my_plot <- 
  ggplot(mapping = aes(
    x = as.factor(Reagent.Conc),
    y = Mean.Viable.Cells.1)) +
  layer_geom_scale("HCT", "#999999") +
  ggnewscale::new_scale("linetype") +
  ggnewscale::new_scale("shape") +
  layer_geom_scale("RKO", "#E69F00") +
  theme(legend.box = "horizontal") +
  guides(shape = guide_legend(ncol = 2),
         linetype = guide_legend(ncol = 2))

my_plot
Run Code Online (Sandbox Code Playgroud)

使用全局指南后的绘图

要修改所有变量的相同比例,guide应在比例定义中添加:

layer_geom_scale <- function(cell_type, color) {
  list(geom_point(mean_mutated[[cell_type]], mapping = aes(shape = Reagent), color = color),
       geom_line(mean_mutated[[cell_type]], mapping = aes(group = Reagent, linetype = Reagent), color = color),
       scale_linetype_manual(name = cell_type, values = c("solid", "dashed", "dotted"), drop=FALSE,
                             guide = guide_legend(ncol = 2)),
       scale_shape_manual(name = cell_type, values = c(15, 16, 4), labels = c("0", "1", "2"), drop=FALSE,
                          guide = guide_legend(ncol = 2))
  )
}

my_plot <- 
  ggplot(mapping = aes(
    x = as.factor(Reagent.Conc),
    y = Mean.Viable.Cells.1)) +
  layer_geom_scale("HCT", "#999999") +
  ggnewscale::new_scale("linetype") +
  ggnewscale::new_scale("shape") +
  layer_geom_scale("RKO", "#E69F00") +
  theme(legend.box = "horizontal")

my_plot
Run Code Online (Sandbox Code Playgroud)

在每个尺度上绘制指南


原始数据

# from /sf/ask/4676314121/

mutated <- structure(list(
  Biological.Replicate = c(1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L), 
  Reagent.Conc = c(10000, 2500, 625, 156.3,
                   39.1, 9.8, 2.4, 0.6, 
                   10000, 2500, 625, 156.3, 
                   39.1, 9.8, 2.4, 0.6, 
                   10000, 2500, 625, 156.3, 
                   39.1, 9.8, 2.4, 0.6),
  Reagent = c(1L, 1L, 1L, 1L, 
              1L, 1L, 1L, 1L, 
              2L, 2L, 2L, 2L, 
              2L, 2L, 2L, 2L, 
              0L, 0L, 0L, 0L, 
              0L, 0L, 0L, 0L),
  Cell.type = c("HCT", "HCT", "HCT", "HCT",
                "HCT", "HCT", "HCT", "HCT", 
                "HCT", "HCT", "HCT", "HCT",
                "HCT", "HCT", "HCT", "HCT",
                "RKO", "RKO", "RKO", "RKO", 
                "RKO", "RKO", "RKO", "RKO"), 
  Mean.Viable.Cells.1 = c(1.014923966, 1.022279854, 1.00926559, 0.936979842, 
                          0.935565248, 0.966403395, 1.00007073, 0.978144524, 
                          1.019673384, 0.991595836, 0.977270557, 1.007353643, 
                          1.111928183, 0.963518289, 0.993028364, 1.027409034, 
                          1.055452733, 0.953801253, 0.956577449, 0.792568337, 
                          0.797052961, 0.755623576, 0.838482346, 0.836773918)), 
  row.names = 9:32, 
  class = "data.frame")
# from /sf/answers/4676602661/

library(ggplot2)
library(ggnewscale)
library(dplyr)
library(magrittr)

mutated <- mutated %>% 
  mutate(Cell.type = factor(Cell.type, 
                            levels = c("HCT", "RKO")),
         Reagent = factor(Reagent, 
                          levels = c("0", "1", "2")))

mean_mutated <- mutated %>%
  group_by(Reagent, Reagent.Conc, Cell.type) %>%
  split(.$Cell.type)
Run Code Online (Sandbox Code Playgroud)