如何在一个 ggplot2 图中为两个几何图层添加图例?

Posted

技术标签:

【中文标题】如何在一个 ggplot2 图中为两个几何图层添加图例?【英文标题】:How to add a legend for two geom layers in one ggplot2 plot? 【发布时间】:2018-04-11 22:28:11 【问题描述】:

我有一个如下所示的数据框:

glimpse(spottingIntensityByMonth)
# Observations: 27
# Variables: 3
# $ yearMonth <dttm> 2015-05-01, 2015-06-01, 2015-07-01, 2015-08-01, 2015-09-01, 2015-10-01, 2...
# $ nClassificationsPerDayPerSpotter <dbl> 3.322581, 13.212500, 13.621701,
    6.194700, 18.127778, 12.539589, 8.659722, ...
# $ nSpotters <int> 8, 8, 22, 28, 24, 22, 24, 27, 25, 29, 32, 32, 21, 14, 18, 13, 20, 19, 15, ...

我正在尝试像这样用 ggplot2 绘制它:

ggplot() + 
    geom_col(data = spottingIntensityByMonth, 
             mapping = aes(x = yearMonth, 
                           y = nClassificationsPerDayPerSpotter)
             ) + 
    xlab("Month of year") + 
    scale_y_continuous(name = "Daily classifications per Spotter") + 
    geom_line(data = spottingIntensityByMonth, 
              mapping = aes(x = yearMonth,
                            y = nSpotters)
              ) +
    theme_bw()

这会产生这样的情节:

现在我想添加一个说明行和列含义的图例。我该怎么做呢?谢谢!

【问题讨论】:

【参考方案1】:

在 ggplot 中,会自动为映射美学创建图例。您可以添加如下映射:

ggplot(data = df, 
       mapping = aes(x = x)) + 

  # specify fill for bar / color for line inside aes(); you can use
  # whatever label you wish to appear in the legend
  geom_col(aes(y = y.bar, fill = "bar.label")) +
  geom_line(aes(y = y.line, color = "line.label")) +

  xlab("Month of year") + 
  scale_y_continuous(name = "Daily classifications per Spotter") + 

  # the labels must match what you specified above
  scale_fill_manual(name = "", values = c("bar.label" = "grey")) +
  scale_color_manual(name = "", values = c("line.label" = "black")) +

  theme_bw()

在上面的示例中,我还将数据和常见的审美映射 (x) 移动到了ggplot()

样本数据集:

set.seed(7)
df <- data.frame(
  x = 1:20,
  y.bar = rpois(20, lambda = 5),
  y.line = rpois(20, lambda = 10)
)

【讨论】:

正如您所描述的那样工作,非常感谢您的详细回答!唯一不明白的是 scale_*_manual() 函数调用背后的逻辑,怎么理解呢?不管怎么说,还是要谢谢你!! :) @hpy 很高兴它有帮助:) scale_*_manual() 函数允许您以命名向量的形式指定自己的调色板,例如c("a" = "red", "b" = "green"),其中“a”和“b”是相关变量中的值。在这种情况下,由于我希望填充/颜色随y.bar/y.line 内的值而变化,因此就填充/颜色而言,我让每个值都取一个值。这有点不正统,但我发现它在实践中效果很好。 知道了,谢谢你的解释!这对了解非常有帮助。【参考方案2】:

此解决方案旨在从 1 个数据帧中绘制 2 条曲线。一列数据绘制为相对于 x 轴(观察日期)的 折线图,另一列数据绘制为相对于同一 x 轴(观察日期)的 面积图。面积曲线将位于辅助 y 轴上。图例绘图和格式也显示在 附图片。希望您喜欢这个解决方案。

数据框结构如下/这是整个数据集的一个样本,我将选择 2 列,obsdate,receives 和 value:

我正在使用 Shiny 库将其托管在服务器上;如果你不了解 Shiny 可以忽略,这只是布局~html

library(xlsx) # Library for Excel import 
library (ggplot2) # Library for plot
library(openxlsx) #FOR Running the xlsx file 
library(shiny) #SERVER UI LIBRARY IN R
library(lubridate) # For converting the imported dates to Date Format

file <- "C:/Users/Nikhil Asati/Desktop/Office/Bicurve_data.xlsx"
data1<- read.xlsx( file ,1)
data1$obsdate <- dmy(data1$obsdate)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(),
    mainPanel(
      plotOutput("Plot")
    )
  )
)
server <- function(input, output) 
  output$Plot <- renderPlot(
    #plot value
    p <- ggplot(data1, aes(x=obsdate))
        p <- p + geom_line(aes(y=revenue, colour ="revenue"))
    #plot revenue
        p <- p + geom_ribbon(aes(ymin = 0, ymax=value/16, fill = 'value'),  
                             linetype=1,     
                             #solid, dashed or other line types
                             colour="grey70",
                             #border line color
                             size=1
                             # ,show.legend= TRUE
        )
         p <- p + scale_y_continuous(sec.axis = sec_axis(~.*16, name = "value"))
          
         p<- p + scale_colour_manual("", values=c("revenue" = "Grey" ))
         p<- p +scale_fill_manual(name = "", values = c("value" = "green"))
         p<- p +theme(legend.position = "top") 
         p
  )
  



shinyApp(ui = ui, server = server) 

输出将是:

【讨论】:

以上是关于如何在一个 ggplot2 图中为两个几何图层添加图例?的主要内容,如果未能解决你的问题,请参考以下文章

《ggplot2-EGDA》 -chapter4-ggplot2里图层的概览

如何将手绘红色圆圈添加到 ggplot2 图中?

如何使用不同的几何图形将边际总计添加到 ggplot2 facet_grid 图

如何在单个ggplot2中对齐图层(密度图和垂直线)

R语言ggplot2可视化在箱图中为箱图添加均值的标签及对应数值实战

如何使用 ggplot2