简体   繁体   English

如何在ggplot2的geom_bar plot中设置双Y轴?

[英]how to set dual Y axis in geom_bar plot in ggplot2?

I'd like to draw bar plot like this but in dual Y axis我想像这样画条 plot 但在双 Y 轴上

( https://i.stack.imgur.com/ldMx0.jpg ) ( https://i.stack.imgur.com/ldMx0.jpg )

the first three indexs range from 0 to 1, so I want the left y-axis (corresponding to NSE, KGE, VE) to range from 0 to 1, and the right y-axis (corresponding to PBIAS) to range from -15 to 5.前三个索引的范围是0到1,所以我希望左边的y轴(对应NSE、KGE、VE)的范围是0到1,右边的y轴(对应PBIAS)的范围是-15到 5。

the following is my data and code:以下是我的数据和代码:

library("ggplot2")

## data
data <- data.frame(
  value=c(0.82,0.87,0.65,-3.39,0.75,0.82,0.63,1.14,0.85,0.87,0.67,-7.03),
  sd=c(0.003,0.047,0.006,4.8,0.003,0.028,0.006,4.77,0.004,0.057,0.014,4.85),
  index=c("NSE","KGE","VE","PBIAS","NSE","KGE","VE","PBIAS","NSE","KGE","VE","PBIAS"),
  period=c("all","all","all","all","calibration","calibration","calibration","calibration","validation","validation","validation","validation")
)

## fix index sequence
data$index <- factor(data$index, levels = c('NSE','KGE','VE',"PBIAS"))
data$period <- factor(data$period, levels = c('all','calibration', 'validation'))


## bar plot
ggplot(data, aes(x=index, y=value, fill=period))+ 
  geom_bar(position="dodge", stat="identity")+
  geom_errorbar(aes(ymin=value-sd, ymax=value+sd),
                position = position_dodge(0.9), width=0.2 ,alpha=0.5, size=1)+
  theme_bw()

I try to scale and shift the second y-axis, but PBIAS bar plot was removed because of out of scale limit as follow:我尝试缩放和移动第二个 y 轴,但 PBIAS 条 plot 由于超出比例限制而被删除,如下所示:

( https://i.stack.imgur.com/n6Jfm.jpg ) ( https://i.stack.imgur.com/n6Jfm.jpg )

the following is my code with dual y axis:以下是我的双 y 轴代码:

## bar plot (scale and shift the second y-axis with slope/intercept in 20/-15)
ggplot(data, aes(x=index, y=value, fill=period))+ 
  geom_bar(position="dodge", stat="identity")+
  geom_errorbar(aes(ymin=value-sd, ymax=value+sd),
                position = position_dodge(0.9), width=0.2 ,alpha=0.5, size=1)+
  theme_bw()+
  scale_y_continuous(limits = c(0,1), name = "value", sec.axis = sec_axis(~ 20*.- 15, name="value")) 

Any advice for move bar_plot or other solution?对移动 bar_plot 或其他解决方案有什么建议吗?

Taking a different approach, instead of using a dual axis one option would be to make two separate plots and glue them together using patchwork .采用不同的方法,而不是使用双轴,一种选择是制作两个单独的图并使用patchwork将它们粘合在一起。 IMHO that is much easier than fiddling around with the rescaling the data (that's the step you missed, ie if you want to have a secondary axis you also have to rescale the data) and makes it clearer that the indices are measured on a different scale:恕我直言,这比摆弄重新缩放数据要容易得多(这是你错过的步骤,即如果你想要一个辅助轴,你还必须重新缩放数据)并且更清楚地表明指数是在不同的尺度上测量的:

library(ggplot2)
library(patchwork)

data$facet <- data$index %in% "PBIAS"

plot_fun <- function(.data) {
  ggplot(.data, aes(x = index, y = value, fill = period)) +
    geom_bar(position = "dodge", stat = "identity") +
    geom_errorbar(aes(ymin = value - sd, ymax = value + sd),
                  position = position_dodge(0.9), width = 0.2, alpha = 0.5, size = 1
    ) +
    theme_bw()
}

p1 <- subset(data, !facet) |> plot_fun() + scale_y_continuous(limits = c(0, 1))
p2 <- subset(data, facet) |> plot_fun() + scale_y_continuous(limits = c(-15, 15), position = "right")

p1 + p2 +
  plot_layout(guides = "collect", width = c(3, 1))

在此处输入图像描述

A second but similar option would be to use ggh4x which via ggh4x::facetted_pos_scales allows to set the limits for facet panels individually.第二个但类似的选项是使用ggh4x ,它通过ggh4x::facetted_pos_scales允许单独设置分面面板的限制。 One drawback, the panels have the same width.一个缺点是面板具有相同的宽度。 (I failed in making this approach work with facet_grid and space="free" ) (我未能使这种方法适用于facet_gridspace="free"

library(ggplot2)
library(ggh4x)

data$facet <- data$index %in% "PBIAS"

ggplot(data, aes(x = index, y = value, fill = period)) +
  geom_bar(position = "dodge", stat = "identity") +
  geom_errorbar(aes(ymin = value - sd, ymax = value + sd),
    position = position_dodge(0.9), width = 0.2, alpha = 0.5, size = 1
  ) +
  facet_wrap(~facet, scales = "free") +
  facetted_pos_scales(
    y = list(
      facet ~ scale_y_continuous(limits = c(-15, 15), position = "right"),
      !facet ~ scale_y_continuous(limits = c(0, 1), position = "left")
    )
  ) +
  theme_bw() +
  theme(strip.text.x = element_blank())

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM