简体   繁体   中英

Use free_y scale on first axis and fixed on second + facet_grid + ggplot2

Is there any method to set scale = 'free_y' on the left hand (first) axis in ggplot2 and use a fixed axis on the right hand (second) axis?

I have a dataset where I need to use free scales for one variable and fixed for another but represent both on the same plot. To do so I'm trying to add a second, fixed, y-axis to my data. The problem is I cannot find any method to set a fixed scale for the 2nd axis and have that reflected in the facet grid.

This is the code I have so far to create the graph -

#plot weekly seizure date 
p <- ggplot(dfspw_all, aes(x=WkYr, y=Seizures, group = 1)) +  geom_line() + 
  xlab("Week Under Observation") + ggtitle("Average Seizures per Week - To Date") + 
  geom_line(data = dfsl_all, aes(x =WkYr, y = Sleep), color = 'green') +
  scale_y_continuous(
    # Features of the first axis
    name = "Seizures",
    # Add a second axis and specify its features
    sec.axis = sec_axis(~.[0:20], name="Sleep")
  )

p + facet_grid(vars(Name), scales = "free_y") +
  theme(axis.ticks.x=element_blank(),axis.text.x = element_blank())

This is what it is producing (some details omitted from code for simplicity) -

在此处输入图像描述

What I need is for the scale on the left to remain "free" and the scale on the right to range from 0-24.

Secondary axes are implemented in ggplot2 as a decoration that is a transformation of the primary axis, so I don't know an elegant way to do this, since it would require the secondary axis formula to be aware of different scaling factors for each facet.

Here's a hacky approach where I scale each secondary series to its respective primary series, and then add some manual annotations for the secondary series. Another way might be to make the plots separately for each facet like here and use patchwork to combine them.

Given some fake data where the facets have different ranges for the primary series but the same range for the secondary series:

library(tidyverse)
fake <- tibble(facet = rep(1:3, each = 10),
               x = rep(1:10, times = 3),
               y_prim = (1+sin(x))*facet/2,
               y_sec = (1 + sin(x*3))/2)

ggplot(fake, aes(x, y_prim)) +
  geom_line() + 
  geom_line(aes(y= y_sec), color = "green") +
  facet_wrap(~facet, ncol = 1)

在此处输入图像描述

...we could scale each secondary series to its primary series, and add custom annotations for that secondary series:

fake2 <- fake %>%
  group_by(facet) %>%
  mutate(y_sec_scaled = y_sec/max(y_sec) * (max(y_prim))) %>%
  ungroup()

fake2_labels <- fake %>% 
  group_by(facet) %>%
  summarize(max_prim = max(y_prim), baseline = 0, x_val = 10.5)

ggplot(fake2, aes(x, y_prim)) +
  geom_line() + 
  geom_line(aes(y= y_sec_scaled), color = "green") +
  facet_wrap(~facet, ncol = 1, scales = "free_y") +
  geom_text(data = fake2_labels, aes(x = x_val, y = max_prim, label = "100%"),
            hjust = 0, color = "green") +
  geom_text(data = fake2_labels, aes(x = x_val, y = baseline, label = "0%"),
            hjust = 0, color = "green") +
  coord_cartesian(xlim = c(0, 10), clip = "off") +
  theme(plot.margin = unit(c(1,3,1,1), "lines"))

在此处输入图像描述

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