如何使用 ggplot2 在辅助轴上绘制具有反向条形图的多个时间序列?

rag*_*hav 5 r ggplot2

我有一个包含四列的数据框,如下所示(这里我只是放置实际数据框的标题):

df <- tibble(Date=c("2007-05-01", "2007-05-02","2007-05-03", "2007-05-04", "2007-05-05"), Obs = c(0.16,0.15,0.17,0.19,0.14), Sim = c(0.17, 0.11, 0.21, 0.15, 0.13), Rain = c(0.1, 0.11, 0.04,0.21,0.5))
Run Code Online (Sandbox Code Playgroud)

如何绘制数据,使变量ObsSim绘制在主 y 轴上,并Rain在反向辅助轴上绘制为条形?

这是我迄今为止尝试过的代码:

ggplot(df, aes(x=as.Date(Date))) + 
  geom_line(aes(y=Obs, color="red")) +
  geom_line(aes(y=Sim, color="green")) +
  geom_bar(mapping = aes(y = Rain), stat = "identity") +
  scale_y_continuous(name = expression('Soil moisture, m'^"3"*' m'^"-3"), 
                     sec.axis = sec_axis(~ 3 - .*0.5, name = "Precipitation (inch)")) 
Run Code Online (Sandbox Code Playgroud)

这是我的预期输出:

在此输入图像描述

编辑:此外,如何插入与每行(即 Obs、Sim 和 Rain)相对应的图例?

Ian*_*ell 2

这是一种使用的方法geom_rect

  1. 计算主轴和次轴最大值之间的比率。

  2. 存储辅助反向轴的最大值。

  3. ymin使用最大值减去该值乘以比率来绘制矩形。

  4. 将辅助轴刻度设置为最大值减去值除以比率。

我添加了一个BottomOffset参数,如果您希望在辅助轴的底部有一些额外的空间,您可以调整该参数。我还继续添加了代码来更改轴的颜色。

编辑:现在有一个图例。

Ratio <- max(c(df$Obs, df$Sim), na.rm = TRUE) / max(df$Rain)
RainMax <- max(df$Rain,na.rm = TRUE)
BottomOffset <- 0.05

ggplot(df, aes(x=as.Date(Date))) + 
  geom_line(aes(y=Obs, color="1")) +
  geom_line(aes(y=Sim, color="2")) +
  geom_rect(aes(xmin=as.Date(Date) - 0.1,
                xmax = as.Date(Date) + 0.1,
                ymin = (BottomOffset + RainMax - Rain) * Ratio,
                ymax = (BottomOffset + RainMax) * Ratio,
                color = "3"),
            fill = "red", show.legend=FALSE) + 
  geom_hline(yintercept = (BottomOffset + RainMax) * Ratio, color = "red") +
  geom_hline(yintercept = 0, color = "black") +
  labs(x = "Date", color = "Variable") +
  scale_y_continuous(name = expression('Soil moisture, m'^"3"*' m'^"-3"), 
                     sec.axis = sec_axis(~ BottomOffset + RainMax  - . / Ratio, name = "Precipitation (inch)"),
                     expand = c(0,0)) +
  scale_color_manual(values = c("1" = "blue", "2" = "green", "3" = "red"),
                     labels = c("1" = "Obs", "2" = "Sim", "3"= "Rain")) +
  theme(axis.line.y.right = element_line(color = "red"), 
        axis.ticks.y.right = element_line(color = "red"),
        axis.text.y.right = element_text(color = "red"),
        axis.title.y.right = element_text(color = "red"),
        axis.line.y.left = element_line(color = "blue"), 
        axis.ticks.y.left = element_line(color = "blue"),
        axis.text.y.left = element_text(color = "blue"),
        axis.title.y.left = element_text(color = "blue"),
        legend.position = "bottom")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述