简体   繁体   中英

ggplot2 dual axes plot with character vector on secondary axis

I want to include a secondary y-axis in my coefficient plot. On the secondary axis, I want to display a var which contains the point estimates and their 95% CI. The examples I have seen so far work if the information on the secondary axis is numeric but my var is character. For example, in the image below the secondary y-axis shows a p-value and the solution here does not work for character variables在此处输入图像描述

In the example data below, I want to show the var labelled "estimates" where P-value is shown in the example figure below.

structure(list(Exposure = c("Organic Carbon", "Organic Carbon", 
"Organic Carbon", "Organic Carbon", "Black Carbon", "Black Carbon", 
"Black Carbon", "Black Carbon", "Carbon Monoxide", "Carbon Monoxide", 
"Carbon Monoxide", "Carbon Monoxide"), `Unit Increase` = c("1 µg/m3", 
"1 µg/m3", "1 µg/m3", "1 µg/m3", "1 µg/m3", "1 µg/m3", "1 µg/m3", 
"1 µg/m3", "10 ppbv", "10 ppbv", "10 ppbv", "10 ppbv"), Models = c("Model 1", 
"Model 2", "Model 3", "Model 4", "Model 1", "Model 2", "Model 3", 
"Model 4", "Model 1", "Model 2", "Model 3", "Model 4"), mean = c(1.00227974541066, 
0.985112091974051, 0.983374917346068, 0.981911815085857, 1.05170784539884, 
0.866397662179956, 0.852380008027597, 0.843141476496602, 1.0285956205419, 
1.01469851838101, 1.01167376733896, 1.01112354142356), sd = c(0.009168606994035, 
0.00941380294243673, 0.00930958569680644, 0.00931923969816641, 
0.0923351388901415, 0.0926479017865309, 0.0923142930597128, 0.0916749212837342, 
0.000753411222911813, 0.000758915467329065, 0.000747152757518728, 
0.000748722745120326), lci = c(0.984429504585927, 0.967102723558839, 
0.96559452133446, 0.964139630281724, 0.877605428442938, 0.722528919823888, 
0.711303894242616, 0.704476676931527, 1.01351836592852, 0.999717112334597, 
0.996966839004107, 0.996393951145291), uci = c(1.02045365704779, 
1.00345683050333, 1.0014827204373, 1.00001159824068, 1.26034930530902, 
1.03891330635438, 1.02143638459725, 1.00910019120188, 1.04389716670672, 
1.02990443046443, 1.02659764746465, 1.02607087773444), estimates = c("1.002 (0.984 - 1.020)", 
"0.985 (0.967 - 1.003)", "0.983 (0.966 - 1.001)", "0.982 (0.964 - 1.000)", 
"1.052 (0.878 - 1.260)", "0.866 (0.723 - 1.039)", "0.852 (0.711 - 1.021)", 
"0.843 (0.704 - 1.009)", "1.029 (1.014 - 1.044)", "1.015 (1.000 - 1.030)", 
"1.012 (0.997 - 1.027)", "1.011 (0.996 - 1.026)")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -12L))

So far, I have tried this

df %>% 
  ggplot(aes(x=mean, y= interaction(`Unit Increase`,Exposure, sep = "&"), colour=Models)) + 
  scale_color_brewer(palette="Set1",
                     breaks=c("Model 1","Model 2","Model 3", "Model 4")) + 
  geom_vline(xintercept = 1) + 
  geom_point(position = position_dodge(width=.75)) + 
  geom_errorbarh(aes(xmin = lci, xmax=uci), position=position_dodge(width=.75), height=0) + 
  labs(x="Odds Ratio", y="Exposures (Unit of Increase)", colour="Models") +
  guides(
    y = guide_axis_nested(delim = "&", n.dodge = 1)) +
  theme(
    axis.text.y.left = element_text(margin = margin(r = 5, l = 5)),
    ggh4x.axis.nesttext.y = element_text(margin = margin(r = 6, l = 6)),
    ggh4x.axis.nestline = element_blank()) + 
  theme_classic()

and got this result (without the second axis)

在此处输入图像描述

Discrete scales don't support secondary axes, see issue . That said, you can work around it by using ggh4x::guide_axis_manual() . It's a bit of a pain where exactly the breaks should be though (I cheated by looking at the layer_data() ).

library(ggplot2)
library(ggh4x)

# df <- structure(...) # omitted for brevity

ggplot(df, aes(x=mean, y = interaction(`Unit Increase`, Exposure, sep = "&"), 
               colour=Models)) + 
  scale_color_brewer(palette="Set1",
                     breaks=c("Model 1","Model 2","Model 3", "Model 4")) + 
  geom_vline(xintercept = 1) + 
  geom_point(position = position_dodge(width=.75)) + 
  geom_errorbarh(aes(xmin = lci, xmax=uci), position=position_dodge(width=.75), height=0) + 
  labs(x="Odds Ratio", y="Exposures (Unit of Increase)", colour="Models") +
  guides(
    y = guide_axis_nested(delim = "&", n.dodge = 1),
    y.sec = guide_axis_manual(
      breaks = as.vector(outer(c(-0.28125, -0.09375, 0.09375, 0.28125), 1:3, "+")),
      labels = df$estimates
    )
  ) +
  theme_classic() +
  theme(
    axis.text.y.left = element_text(margin = margin(r = 5, l = 5)),
    ggh4x.axis.nesttext.y = element_text(margin = margin(r = 6, l = 6)),
    ggh4x.axis.nestline.y = element_blank())

Created on 2022-05-16 by the reprex package (v2.0.1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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