代码之家  ›  专栏  ›  技术社区  ›  Adrian

ggplot2的geom_errorbar在多个变量之间按降序排列

  •  5
  • Adrian  · 技术社区  · 2 年前
    library(ggplot2)
    mydat <- data.frame(mean = c(23, 24, 15, 27, 18, 19, 23, 20, 32),
               lower = c(20, 19, 13, 15, 14, 18, 20, 17, 20),
               upper = c(25, 29, 17, 39, 22, 20, 26, 23, 40),
               class = c("A", "B", "C", "A", "B", "C", "A", "B", "C"),
               domain = c("North", "North", "North", "West", "West", "West", "South", "South", "South"))
    mydat$class <- as.factor(mydat$class)
    mydat$domain <- as.factor(mydat$domain)
    
    mydat %>% ggplot(aes(x = mean, y = class, color = domain, Group = domain, xmin = lower, xmax = upper)) +
      geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) + theme_light() + geom_point(position = position_dodge(width = 0.5)) + xlab("Counts")
    

    enter image description here

    我想通过减小上限值(即。, upper )误差条的两个 class 以及 domain s.所需输出为:

    enter image description here

    我尝试了以下代码,但没有达到预期效果:

    library(forcats)
    mydat %>% ggplot(aes(x = mean, y = class, color = fct_infreq(domain), Group = fct_infreq(domain), xmin = lower, xmax = upper)) +
      geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) + theme_light() + geom_point(position = position_dodge(width = 0.5)) + xlab("Counts")
    
    2 回复  |  直到 2 年前
        1
  •  1
  •   jared_mamrot    2 年前

    我不认为有一种“简单”的方法可以实现这一结果;当您根据 max(upper) 所有域的顺序都是“设置”的(尽管我很乐意在这方面被证明是错误的)。

    一个潜在的解决方案可能是按类别划分你的绘图,并分别对每个绘图重新排序,例如。

    library(tidyverse)
    
    mydat <- data.frame(mean = c(23, 24, 15, 27, 18, 19, 23, 20, 32),
                        lower = c(20, 19, 13, 15, 14, 18, 20, 17, 20),
                        upper = c(25, 29, 17, 39, 22, 20, 26, 23, 40),
                        class = c("A", "B", "C", "A", "B", "C", "A", "B", "C"),
                        domain = c("North", "North", "North", "West", "West", "West", "South", "South", "South"))
    mydat$class <- as.factor(mydat$class)
    mydat$domain <- as.factor(mydat$domain)
    
    colour_palette <- scales::hue_pal()(3)
    
    mydat %>%
      group_split(class) %>%
      map(~{ggplot(data = .x,
                   aes(x = mean, y = fct_reorder(.f = class, .x = upper, .fun = max),
                       color = fct_reorder(.f = domain, .x = upper, .fun = max),
                       Group = fct_reorder(.f = domain, .x = upper, .fun = max),
                       xmin = lower, xmax = upper)) +
      geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) + 
      theme_light() + 
      geom_point(position = position_dodge(width = 0.5)) +
          xlab("Counts") +
          ylab("Class") +
          scale_color_manual(values = c("North" = colour_palette[1],
                                        "South" = colour_palette[2],
                                        "West" = colour_palette[3]),
                             name = "Domain")})
    #> [[1]]
    

    #> 
    #> [[2]]
    

    #> 
    #> [[3]]
    

    创建于2023-10-23 reprex v2.0.2


    如果你“手动”这样做,你可以按照你想要的顺序排列,例如。

    library(tidyverse)
    
    mydat <- data.frame(mean = c(23, 24, 15, 27, 18, 19, 23, 20, 32),
                        lower = c(20, 19, 13, 15, 14, 18, 20, 17, 20),
                        upper = c(25, 29, 17, 39, 22, 20, 26, 23, 40),
                        class = c("A", "B", "C", "A", "B", "C", "A", "B", "C"),
                        domain = c("North", "North", "North", "West", "West", "West", "South", "South", "South"))
    mydat$class <- as.factor(mydat$class)
    mydat$domain <- as.factor(mydat$domain)
    
    colour_palette <- scales::hue_pal()(3)
    
    p1 <- mydat %>%
      filter(class == "A") %>%
      ggplot(aes(x = mean, y = fct_reorder(.f = class, .x = upper, .fun = max),
                       color = fct_reorder(.f = domain, .x = upper, .fun = max),
                       Group = fct_reorder(.f = domain, .x = upper, .fun = max),
                       xmin = lower, xmax = upper)) +
          geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) + 
          theme_light(base_size = 18) + 
          geom_point(position = position_dodge(width = 0.5)) +
          xlab("") +
          ylab("") +
          scale_color_manual(values = c("North" = colour_palette[1],
                                        "South" = colour_palette[2],
                                        "West" = colour_palette[3]),
                             name = "Domain") +
      scale_x_continuous(limits = c(10, 45))
    
    p2 <- mydat %>%
      filter(class == "B") %>%
      ggplot(aes(x = mean, y = fct_reorder(.f = class, .x = upper, .fun = max),
                 color = fct_reorder(.f = domain, .x = upper, .fun = max),
                 Group = fct_reorder(.f = domain, .x = upper, .fun = max),
                 xmin = lower, xmax = upper)) +
      geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) + 
      theme_light(base_size = 18) + 
      geom_point(position = position_dodge(width = 0.5)) +
      xlab("Counts") +
      ylab("") +
      scale_color_manual(values = c("North" = colour_palette[1],
                                    "South" = colour_palette[2],
                                    "West" = colour_palette[3]),
                         name = "Domain") +
      theme(legend.position = "none") +
      scale_x_continuous(limits = c(10, 45))
    
    p3 <- mydat %>%
      filter(class == "C") %>%
      ggplot(aes(x = mean, y = fct_reorder(.f = class, .x = upper, .fun = max),
                 color = fct_reorder(.f = domain, .x = upper, .fun = max),
                 Group = fct_reorder(.f = domain, .x = upper, .fun = max),
                 xmin = lower, xmax = upper)) +
      geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) + 
      theme_light(base_size = 18) + 
      geom_point(position = position_dodge(width = 0.5)) +
      xlab("") +
      ylab("") +
      scale_color_manual(values = c("North" = colour_palette[1],
                                    "South" = colour_palette[2],
                                    "West" = colour_palette[3]),
                         name = "Domain") +
      theme(legend.position = "none") +
      scale_x_continuous(limits = c(10, 45))
    
    library(patchwork)
    p3 / p1 / p2
    

    创建于2023-10-23 reprex v2.0.2

        2
  •  1
  •   ThomasIsCoding    2 年前

    我无法计算出与您预期的相同的输出,但希望以下代码对您有同等的意义(其中 domain 信息作为标签添加到每个错误栏)

    mydat %>%
        mutate(class = factor(class, names(sort(by(upper, class, max))))) %>%
        arrange(class, desc(upper)) %>%
        mutate(color = factor(n() - row_number()), .by = class) %>%
        ggplot(aes(x = mean, y = class, color = color, Group = domain, xmin = lower, xmax = upper)) +
        geom_errorbar(width = 0.1, position = position_dodge(width = 0.5)) +
        geom_text(aes(label = domain), position = position_dodge(0.5)) +
        theme_light() +
        geom_point(position = position_dodge(width = 0.5)) +
        xlab("Counts")
    

    enter image description here

    数据

    mydat <- data.frame(
        mean = c(23, 24, 15, 27, 18, 19, 23, 20, 32),
        lower = c(20, 19, 13, 15, 14, 18, 20, 17, 20),
        upper = c(25, 29, 17, 39, 22, 20, 26, 23, 40),
        class = c("A", "B", "C", "A", "B", "C", "A", "B", "C"),
        domain = c("North", "North", "North", "West", "West", "West", "South", "South", "South")
    )