【问题标题】:How to add custom legend in ggboxplot如何在ggboxplot中添加自定义图例
【发布时间】:2020-09-22 14:54:23
【问题描述】:

我正在尝试在 R 中创建一些箱线图。我一直在使用 ggboxplot 和 ggplot。到目前为止,这是我的代码和输出:

ggboxplot:

ggboxplot(shp_PA@data, x = "hei_1998to2007_cat", y = "adjrate.2008to2017", 
          xlab = "Hazardous Exposure Index Jenks", 
          ylab = "Lung Cancer Incidence Rate",
          color = "red",
          add = c("jitter", "mean"), 
          add.params = list(color = "black", shape=20)) 

ggplot:

shp_PA@data %>%
  ggplot(aes(x=hei_1998to2007_cat, y=adjrate.2008to2017)) +
  geom_boxplot(colour = "red") + 
  geom_jitter(color="black", size=0.75) +
  stat_summary(fun=mean, geom="point", shape=4, size=3, color="black") +
  xlab("Hazardous Exposure Index Jenks") + 
  ylab("Lung Cancer Incidence Rate")

我现在的主要兴趣是在每个箱线图上放置一个图例,其中包含用于描述平均值的符号,以及旁边的“平均值”一词。在base R中,它就像放置类似的东西一样简单

legend("topright", legend=c("Mean"),pch=5, col="red")

但我无法在 ggboxplot 或 ggplot 中弄清楚。我在网上看到的大部分内容都在讨论修改已经存在的图例。

我想知道如何做的另一件事是特定于 ggboxplot。我希望能够使抖动点的颜色和形状与均值符号不同。我尝试将 add.params 代码更改为

add.params = list(color = c("black", "blue"), shape=c(20,4))

但我得到了错误

Error: Aesthetics must be either length 1 or the same as the data (213): shape and colour

非常感谢任何帮助!

编辑:在 R 中添加使用 iris 数据集的可重现示例

ggboxplot:

ggboxplot(iris, x = "Species", y = "Sepal.Length", 
          color = "red",
          add = c("jitter", "mean"), 
          add.params = list(color = "black", shape=20)) 

ggplot:

ggplot(data=iris, aes(x=Species, y=Sepal.Length)) +
  geom_boxplot(colour = "red") + 
  geom_jitter(color="black", size=0.75) +
  stat_summary(fun=mean, geom="point", shape=4, size=3, color="black")

再次,我想添加一个图例,其中包含用于描述均值的符号和“均值”一词,并且能够使用 ggboxplot 具有抖动的颜色和形状以及不同的均值。

【问题讨论】:

标签: r ggplot2 legend boxplot


【解决方案1】:

使用ggplot 有点不标准,但你可以这样做。

添加一个带有用于描述平均值的符号和“平均值”一词的图例

使用aes 将不同的形状映射到geom_jitterstat_summary。使用scale_shape_manual控制这些形状

具有抖动的颜色和形状,意味着不同

使用color更改抖动点和均值点的颜色,使用override.aes更改图例中的颜色。

ggplot(data=iris, aes(x=Species, y=Sepal.Length)) +
    geom_boxplot(colour = "red") + 
    geom_jitter(size=1, color = 'green', aes(shape = 'all data')) +
    stat_summary(fun=mean, geom="point", size=3, color = 'black', aes(shape = 'mean')) +
    scale_shape_manual(values = c(20, 4)) +
    guides(shape = guide_legend(override.aes = list(color = c('green', 'black'))))

这里有另一个类似的答案:https://stackoverflow.com/a/5179731/12400385

【讨论】:

    【解决方案2】:

    欢迎来到 SO!

    ggplot2 添加自定义标签非常困难,我相信这是设计使然。所有图例都由aesscale_*_[continuoues|discrete|manual] 中的参数控制。如果我们不想开始学习如何grob(可能要花费几个小时),我们可以通过

    1. 向数据本身添加统计信息
    2. 创建一个列,指示哪些是统计数据,哪些是数据点
    3. 滥用我们可以在geom_* 函数中直接subset the datajitter 和非jittered 点创建特定层,并在这些层的美学中设置形状
    4. 使用scale_shape_manual(或scale_shape_discrete)自定义标记。

    mtcars 数据集为例(以及dplyr 用于管道),我们可以获得与ggboxplot 非常相似的东西

    library(ggplot2)
    library(dplyr)
    data(mtcars)
    # Setup data with mean instead of using stat_summary
    mtcars %>% 
      select(cyl, hp) %>%
      group_by(cyl) %>%
      summarize(hp = mean(hp)) %>% 
      bind_cols(stat = factor(rep('mean', 3))) %>% 
      bind_rows(mtcars %>%
                  select(cyl, hp) %>% 
                  bind_cols(stat = rep('data', nrow(mtcars)))) %>%
    
      # Create ggplot
      ggplot(aes(x = factor(cyl), y = hp)) + 
      geom_boxplot(colour = 'red') + 
    
      # Jitter based on subset of data. Do the same for geom_point (means)
      ## Note that to only plot a subset I pass a function to data that "filters" the data.
      geom_jitter(data = function(.data)filter(.data, stat == 'data'), 
                  aes(shape = stat), color = 'black') +
      # Add mean to the point and change shape into something we like.
      geom_point(data = function(.data)filter(.data, stat == 'mean'), 
                 aes(shape = stat), size = 2.5) +
      ## Use scale_shape_manual to change shape into something i like.
      scale_shape_manual(values = c('mean' = 8, 'data' = 16)) +
    
      # Fix the plot theme to be similar to ggboxplot
      theme(panel.grid = element_line(colour = NA),
            panel.background = element_rect(fill = "#00000000"),
            axis.line.x = element_line(colour = 'black'), 
            axis.line.y = element_line(colour = 'black'), 
            axis.text = element_text(size = 11),
            legend.position = 'bottom'
            ) +
      # Remove label from the legend if wanted
      labs(shape = NULL)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 2022-11-23
      • 2021-01-05
      • 2011-09-13
      相关资源
      最近更新 更多