3

I need to plot some data over time. However, data is missing for a large part of the time series. I'd like to remove the whole section with missing data from the middle of the graph.

Here's the data

# Setup 
library(tidyverse)
library(patchwork)

# Set seed 
set.seed(123)

# Generate data
df_test <- 
  tibble(
    date = seq(as.Date("2010-1-1"), as.Date("2015-1-1"), by = "months"),
    value = rnorm(n = length(date), mean = 10, sd = 1)) %>% 
  mutate( # Create missing values
    value = ifelse(
      date > as.Date("2010-03-20") & date < as.Date("2011-01-14"), 
      NA, 
      value))

Here's the graph with no cropping

# Graph full range
gg_full <- 
  df_test %>% 
  ggplot(
    aes(
      x = date, 
      y = value)) +
  geom_point() + 
  geom_step()

enter image description here

I want to remove the dates with missing values from the x-axis. Here's a photoshop with "-//-" where I've excised the dates.

enter image description here

Attempted solution

I tried creating two separate graphs and plot them side by side with patchwork.

# Graph first part only
gg_first <- 
  df_test %>%
  filter(date <= as.Date("2010-03-20")) %>% 
  ggplot(
    aes(
      x = date, 
      y = value)) +
  geom_point() + 
  geom_step()

# Graph latter part only
gg_latter <- 
  df_test %>%
  filter(date >= as.Date("2011-01-14")) %>% 
  ggplot(
    aes(
      x = date, 
      y = value)) +
  geom_point() + 
  geom_step()

# Layout plots 
gg_first + gg_latter + 
  patchwork::plot_layout(widths = c(1, 6))

enter image description here

However, this messes up the x-axis scale and involves a lot of manually removing elements like the y-axis labels from the right-hand but not the left-hand graph. However, I might simply be failing to use patchwork to its full potential.

Cameron
  • 226
  • 1
  • 12
  • 1
    This is not made easy in `ggplot2`, maybe this would help: https://stackoverflow.com/questions/61077866/force-y-axis-to-start-at-0-insert-break-and-have-a-large-y-axis-using-ggplot – Maël Sep 22 '22 at 08:50
  • Buried there is this blog https://www.j4s8.de/post/2018-01-15-broken-axis-with-ggplot2/ Which uses facet_grid to create the break and it works really well. df_test %<>% mutate( facet_indicator = case_when( date <= as.Date("2010-03-20") ~ "First", date >= as.Date("2011-01-14") ~ "Latter", TRUE ~ "Excise")) And then you run df_test %>% filter(facet_indicator != "Excise") %>% ggplot( aes( date, value)) + geom_point() + geom_step() + facet_grid(. ~ facet_indicator) Thanks :) – Cameron Sep 22 '22 at 09:10

1 Answers1

3

One option is ggbreak:

library(ggbreak)
gg_full +
  scale_x_break(c(ymd("2010-03-25"), ymd("2011-01-10"))) +
  scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
  theme(axis.text.x.top = element_blank(), axis.ticks.x.top = element_blank())

enter image description here

Maël
  • 45,206
  • 3
  • 29
  • 67
  • Perfect, this works thanks :) We can tidy up the x-axis with gg_full + ggbreak::scale_x_break( breaks = as.Date(c("2010-03-21", "2011-01-01"))) + scale_x_date( date_breaks = "1 year", date_labels = "%Y") + theme( axis.text.x.top = element_blank(), axis.ticks.x.top = element_blank()) – Cameron Sep 22 '22 at 09:15
  • Very much cleaner indeed. Do you mind if I add to the answer? – Maël Sep 22 '22 at 09:16
  • 1
    Go for it, the better for posterity – Cameron Sep 22 '22 at 09:17