【问题标题】:How to rotate legend symbols in ggplot2?如何在ggplot2中旋转图例符号?
【发布时间】:2022-01-24 03:36:44
【问题描述】:

例如使用数据mtcars 和函数coord_flip 考虑这个绘图

library(ggplot2)
library(Hmisc)

ggplot(mtcars,aes(x=gear,y=cyl)) + stat_summary(aes(color=as.factor(rep(1:2,16))),
fun.data=mean_cl_boot, position=position_dodge(0.4)) + coord_flip()

误差线在图表上是水平的,但在图例中是垂直的,这让我很困扰 :) 如何旋转这些符号?

【问题讨论】:

  • 提出 GitHub 问题并等到 Hadley 得到另一个实习生。更好的是,写一个拉取请求。
  • 当我们使用 coord_flip() 时,符号默认会翻转,但无论如何这个函数应该很容易被用户编辑。

标签: r plot graph graphics ggplot2


【解决方案1】:

我没有想出一个适用于正常 ggplot2 工作流程的答案,所以现在,这里是一个 hacky 答案。关闭 stat_summary 图例。然后,使用超出您要绘制的实际数据范围的数据添加点和线几何。这将创建您想要的点和水平线图例。然后将绘图轴范围设置为仅包含真实数据的范围,这样虚假数据点就不会出现。

ggplot(mtcars, aes(x=gear, y=cyl, color=as.factor(rep(1:2,16)))) + 
  stat_summary(fun.data=mean_cl_boot, position=position_dodge(0.4), show.legend=FALSE) + 
  geom_line(aes(y=cyl-100)) +
  geom_point(aes(y=cyl-100), size=2.5) +
  coord_flip(ylim=range(mtcars$cyl)) 

另一种选择是使用网格函数将图例键 grobs 旋转 90 度,但我会将其留给比我更熟悉 grid 的人。

【讨论】:

    【解决方案2】:

    调整图例键

    GeomPointrange$draw_key <-  function (data, params, size)     {
    
             draw_key_vpath <- function (data, params, size) {
               # only need to change the x&y coords so that the line is horizontal
               # originally, the vertical line was `0.5, 0.1, 0.5, 0.9`
                  segmentsGrob(0.1, 0.5, 0.9, 0.5, 
                  gp = gpar(col = alpha(data$colour, data$alpha), 
                  lwd = data$size * .pt, lty = data$linetype, 
                  lineend = "butt"), arrow = params$arrow)
                  }
    
        grobTree(draw_key_vpath(data, params, size), 
                 draw_key_point(transform(data, size = data$size * 4), params))
    }
    

    然后绘制

     ggplot(mtcars,aes(x=gear,y=cyl)) + 
        stat_summary(aes(color=as.factor(rep(1:2,16))),
                      fun.data=mean_cl_boot, position=position_dodge(0.4)) + 
        coord_flip()
    

    【讨论】:

      【解决方案3】:

      按照@eipi10 的建议使用grid 函数来编辑grobs - 相关grobs 是段。有两种可能性:1)旋转段grobs;或 2) 编辑段 grobs 端点的 x 和 y 坐标。

      library(ggplot2)
      library(Hmisc)
      
      library(grid)
      
      p = ggplot(mtcars,aes(x=gear,y=cyl)) + 
          stat_summary(aes(color=as.factor(rep(1:2,16))),
                        fun.data=mean_cl_boot, position=position_dodge(0.4)) + 
          coord_flip()
      
      g = ggplotGrob(p)
      
      # Get names of segment grobs
      grid.ls(grid.force(g))$name   # "GRID.segments"
      
      # Check the structure of the segment grobs
      str(getGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE))
      
      # Edit the segment grobs using the editGrob() function
      # 1) Rotate the segments
          g <- editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,
              vp = viewport(angle = 90)) 
      
      # 2) set end points of segments
      #    g <- editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,  
      #         x0 = unit(0.1, "npc"), y0 = unit(0.5, "npc"), x1 = unit(0.9, "npc"), y1 = unit(0.5, "npc"))
      
      # Draw it
      grid.newpage()
      grid.draw(g)
      

      【讨论】:

        【解决方案4】:

        ggstance 包在这里提供了一个易于实施的解决方案:

        library(ggplot2)
        library(ggstance)
        
        ggplot(mtcars,aes(x=cyl,y=gear)) + stat_summaryh(aes(color=as.factor(rep(1:2,16))),
                                                        fun.data=mean_cl_boot_h, position = position_dodgev(height = 0.4))
        

        geom:

        df <- data.frame(x = 1:3, y = 1:3)
        ggplot(df, aes(x, y, colour = factor(x))) +
             geom_pointrangeh(aes(xmin = x - 1, xmax = x + 1))
        

        【讨论】:

        • 你可以解释得更好,但 +1 是好的解决方案!
        【解决方案5】:

        编辑自:https://gist.github.com/grantmcdermott/d86af2b8f21f4082595c0e717eea5a90

        要点是使用geom_pointrangeh from ggstance 并记住指定aes w.r.t。 x 轴。

        library(tidyverse)
        library(broom)
        library(hrbrthemes) 
        library('ggstance')
        library('jtools')
        
        df = 
          mtcars %>%
          mutate(vs = factor(vs), am = factor(am))
        
        fit1 = lm(mpg ~ vs * am * wt, data = df) 
        fit1_coefs = tidy(fit1, conf.int = T) 
        
        fit2 = lm(mpg ~ vs / am / wt, data = df)
        fit2_coefs = tidy(fit2, conf.int = T) 
        
        
        bind_rows(
          fit1_coefs %>% mutate(model = "Model 1"),
          fit2_coefs %>% mutate(model = "Model 2")
        ) %>%
          filter(grepl("wt", term)) %>%
          ## Optional regexp work to make plot look nicier  
          mutate(
            am = ifelse(grepl("am1", term), "Automatic", "Manual"),
            vs = ifelse(grepl("vs1", term), "V-shaped", "Straight"),
            x_lab = paste(am, vs, sep="\n")
          ) %>%
          ggplot(aes(col = model,y=x_lab, x=estimate, xmin=conf.low, xmax=conf.high)) +
          geom_pointrangeh(position = position_dodge(width = 0.5)) +
          guides(color = guide_legend(reverse = TRUE)) +
          geom_vline(xintercept = 0, col = "black",lty=4) +
            labs(x = NULL, y = NULL,title = "Title") +
          theme_nice() +
          theme(plot.title = element_text(hjust = 0.5))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-09
          • 2013-10-27
          • 1970-01-01
          • 2012-12-09
          • 1970-01-01
          • 2013-12-25
          • 1970-01-01
          相关资源
          最近更新 更多