【问题标题】:tidyverse/ggplot2: subsetting by a factor that is used in manual scales?tidyverse/ggplot2:按手动比例中使用的因子进行子集?
【发布时间】:2019-08-29 19:10:20
【问题描述】:

我有一个庞大而复杂的数据集,但重要的部分归结为类似于以下内容:

my_df <- data.frame(Expt = rep(c("Expt1", "Expt2", "Expt3", "Expt4"), each = 96),
                  ExpType = rep(c("A", "B"), each = 192),
                  Treatment = c(rep("T1", 192), rep("T2", 144), rep("T1", 48)),
                  Subject = c(rep(c("S01", "S02", "S03", "S04", "S05", "S06", "S07", "S08"), 24), rep("S01", 96), rep("S06", 96)),
                  xvar = as.factor(rep(rep(c(10, 5, 2.5, 1.25, 0.6, 0.3, 0.16, 0.08, 0.04, 0.02, 0, "NA"), each = 8),  4)),
                  yvar = runif(384))

我目前正在按 ExpType 和 Treatment 对数据进行分组,计算一些汇总统计数据,然后绘制图形,如下所示:

myplots <- my_df %>%
  group_by(ExpType, Treatment) %>%  #  took out Include because I'm using the versions with no questionable data
  nest() %>%

  mutate(sumstats = map(
    .x = data,
    ~.x %>%
      group_by(Subject, xvar) %>%
      summarize(
        my_mean = mean(yvar, na.rm = TRUE)
      )))  %>%

  mutate(plots1 = map2(
    .x = data,
    .y = sumstats,
    ~ggplot(data = .x) +
      theme_classic() +
      scale_shape_manual(name = "Subject", values = c("S01" = 23, "S02" = 24, "S03" = 21, "S04" = 21, "S05" = 22, "S06" = 22, "S07" = 24, "S08" = 25)) + 
      scale_linetype_manual(name = "Subject", values = c("S01" = "solid", "S02" = "dotted", "S03" = "dotted", "S04" = "solid", "S05" = "dotted", "S06" = "dashed", "S07" = "solid", "S08" = "dashed")) +
      scale_fill_manual(name = "Subject", values = c("S01" = "#AA4499", "S02" = "#882255", "S03" = "#CC6677", "S04" = "#DDCC77", "S05" = "#999933", "S06" = "#117733", "S07" = "#44AA99", "S08" = "#88CCEE")) +
      scale_color_manual(name = "Subject", values = c("S01" = "#AA4499", "S02" = "#882255", "S03" = "#CC6677", "S04" = "#DDCC77", "S05" = "#999933", "S06" = "#117733", "S07" = "#44AA99", "S08" = "#88CCEE")) +
      geom_line(data = .y, aes(x=xvar, y = my_mean, group=Subject,  color=Subject, linetype = Subject)) +
      geom_point(aes(x=xvar, y = yvar, group=Subject, fill=Subject, shape = Subject), size = 2.5)

  ))

walk(.x = myplots$plots1,  ~print(.x))

这很好,但我有足够的主题,很难看到发生了什么,我希望能够为每个主题制作单独的图表。我可以按主题分面,但它们的数量足够多,以至于图表非常小,很难看到发生了什么。

我在哪里/如何在这个额外的子集步骤中添加,并且仍然将因子传递给手动比例?

【问题讨论】:

  • 澄清一下,您想按 ExpType + Treatment + Subject 分组,但能够访问 ggplot 对象中的 Subject 值吗?
  • 是的;我希望仍然能够使用主题来设置美学参数(点/线样式)。

标签: r ggplot2 tidyverse


【解决方案1】:

解决方案 1

从每个嵌套数据集中访问主题值同时将其作为嵌套之外的分组变量的一种简单方法是创建具有相同值的重复列:

# define manual scale palettes outside for easy reusability
shape.pal <- c(23, 24, 21, 21, 22, 22, 24, 25)
linetype.pal <- c("solid", "dotted", "dotted", "solid", "dotted", "dashed", "solid", "dashed")
fill.pal <- c("#AA4499", "#882255", "#CC6677", "#DDCC77", "#999933", "#117733", "#44AA99", "#88CCEE")
names(shape.pal) <- names(linetype.pal) <- names(fill.pal) <- paste0("S0", seq(1, 8))
myplots <- my_df %>%
  mutate(Subject2 = Subject) %>% # add a duplicate column for subject
  group_by(ExpType, Treatment, Subject2) %>% # don't next duplicate subject column
  nest() %>%

  mutate(sumstats = map(
    .x = data,
    ~.x %>%
      group_by(Subject, xvar) %>%
      summarize(
        my_mean = mean(yvar, na.rm = TRUE)
      )))  %>%

  mutate(plots1 = map2(
    .x = data,
    .y = sumstats,
    ~ggplot(data = .x, 
            aes(x = xvar, y = yvar, group = Subject)) +
      geom_line(data = .y, 
                aes(y = my_mean, color = Subject, linetype = Subject)) +
      geom_point(aes(fill = Subject, shape = Subject), 
                 size = 2.5) +
      labs(shape = "Subject", linetype = "Subject", fill = "Subject", colour = "Subject") +
      scale_shape_manual(values = shape.pal) + 
      scale_linetype_manual(values = linetype.pal) +
      scale_fill_manual(values = fill.pal, aesthetics = c("fill", "color")) +
      theme_classic()
  ))

walk(.x = myplots$plots1,  ~print(.x))

对应于 ExpType = A、Treatment = T1、Subject = S01 的结果图:

解决方案 2

更一般地,如果您在创建 ggplot 对象时使用 pmap 而不是 map2,则可以访问分组变量,因为 pmap 允许您同时映射超过 2 个输入。

下面的演示,它还映射到 ExpType 和 Treatment 以反映每个图在其图标题中的分组变量值的组合:

myplots <- my_df %>%
  group_by(ExpType, Treatment, Subject) %>% # use subject as a grouping variable
  group_nest() %>%

  mutate(sumstats = map(
    .x = data,
    ~.x %>%
      group_by(xvar) %>% # not grouping by subject here, as it's not a column in data
      summarize(
        my_mean = mean(yvar, na.rm = TRUE)
      )))  %>%

  mutate(plots1 = pmap(
    .l = list(x = data,
              y = sumstats,
              s = as.character(Subject),
              z = as.character(ExpType),
              w = as.character(Treatment)),
    function(x, y, s, z, w) ggplot(data = x, aes(x = xvar, group = s)) +
      geom_line(data = y, 
                aes(y = my_mean, color = s, linetype = s)) +
      geom_point(aes(y = yvar, fill = s, shape = s), 
                 size = 2.5) +
      labs(title = paste0("ExpType: ", z, ", Treatment: ", w),
           shape = "Subject", linetype = "Subject", fill = "Subject", colour = "Subject") +
      scale_shape_manual(values = shape.pal) + 
      scale_linetype_manual(values = linetype.pal) +
      scale_fill_manual(values = fill.pal, aesthetics = c("fill", "colour")) +
      theme_classic()     
  ))

walk(.x = myplots$plots1,  ~print(.x))

对应于 ExpType = A、Treatment = T1、Subject = S01 的结果图:

【讨论】:

  • 谢谢!这真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 2017-11-09
  • 1970-01-01
  • 2021-06-20
  • 2020-06-02
  • 1970-01-01
  • 2017-10-15
  • 2011-07-12
  • 2023-03-28
相关资源
最近更新 更多