1

I'm working on a ggplot code. I have a dataset AirPassenger in tsibble format and I want to create a facet grid plot with four line plots showing the observed data, trend, seasonal, and irregular components. I have managed to create the plot using the following code:

library(fpp3)
library(tsibble)
library(ggplot2)
library(scales)
library(zoo)

# Load the data
pr1<-AirPassengers

# Convert time series to tsibble format
pr1_tsibble <- as_tsibble(pr1)

# Apply X-13ARIMA-SEATS model and perform decomposition
fit <- pr1_tsibble %>%
  model(X_13ARIMA_SEATS(value ~ transform(`function` = "none") + x11(mode = "add"))) %>%
  components()

# Extract components
index <- pr1_tsibble$index
data <- pr1_tsibble$value
trend <- fit$trend
seasonal <- fit$seasonal
irregular <- fit$irregular

# Combine components with the original data
combined <- data.frame(index, data, trend, seasonal, irregular)

library(dplyr)
combined <- combined %>%
  mutate(year = as.factor(format(index, "%Y")))
combined$index<-as.Date(combined$index, format= "%Y%b")

ggplot(combined, aes(x = index)) +
  geom_line(aes(y = data, color = "Observed")) +
  geom_line(aes(y = trend, color = "Trend"))+
  geom_line(aes(y = seasonal, color = "Seasonal")) +
  geom_line(aes(y = irregular, color = "Irregular"))+
  xlab('') + ylab("") +
  theme_light() +
  scale_color_manual(
    values = c("Observed" = "grey", "Trend" = "black", "Seasonal" = "green", "Irregular" = "blue"),
    name = ""
  ) +
  scale_y_continuous(
    labels = function(x) format(x, nsmall = 2)
  )+
  scale_x_date(labels = NULL, breaks = NULL, 
               date_minor_breaks = "1 month") + 
  facet_wrap(~year, nrow=1, scales= 'free_x',
             strip.position = 'bottom')+
  theme(panel.spacing.x = unit(0, "lines"),
        panel.grid = element_blank(), 
        legend.position = "top",
        strip.background = element_rect(colour = "white", fill = "grey"))

It produces the plot :

enter image description here

What I am expecting in x-axis labelling .. enter image description here

The current plot is almost what I need, but I want the line plots to be connected across the facet grid. Currently, each line plot is disconnected between years. How can I modify the code to achieve a continuous geom_line across the facet grid?

Any help or suggestions would be greatly appreciated!

Rony Golder
  • 111
  • 6
  • to reduce horizontal gaps between facets (down to zero if desired) see here: https://stackoverflow.com/questions/12252750/alter-just-horizontal-spacing-between-facets-ggplot2 – I_O Jun 04 '23 at 18:23
  • 1
    I think the easiest approach would be to skip facets altogether and fake the facet labels with rectangles and text. I don't know of a way to make data connect across facets without major hacking. – Jon Spring Jun 04 '23 at 18:44

2 Answers2

2

Faking the labels without facets:

geom_vline(xintercept = yrs, alpha = 0.2) +
annotate("rect", xmin = yrs[1:(length(yrs)-1)],
         xmax = yrs[2:length(yrs)], ymin = -150, ymax = -100,
         fill = "gray90", color = "gray70") +
annotate("text", x = yrs[1:(length(yrs)-1)] + 182, label = 1949:1960,
         y = -125) +

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
2

You can do this with facets by setting expand = c(0, 0) in your x axis. You will need to copy over the 1st of January values to 31st December the previous year to ensure the lines are continuous. Although this may feel a bit like cheating, remember that there are far fewer than 365 pixels across each facet, so this will not effect the look of the plot:

combined %>%
  filter(lubridate::month(index) == 1) %>%
  mutate(index = index - 1, 
         year = factor(as.numeric(as.character(year)) - 1)) %>%
  bind_rows(combined) %>%
  filter(year != "1948") %>%
  ggplot(aes(x = index)) +
  geom_line(aes(y = data, color = "Observed")) +
  geom_line(aes(y = trend, color = "Trend"))+
  geom_line(aes(y = seasonal, color = "Seasonal")) +
  geom_line(aes(y = irregular, color = "Irregular"))+
  labs(x = NULL, y = NULL) +
  theme_light() +
  scale_color_manual(NULL,
    values = c("Observed" = "grey", "Trend" = "black", 
               "Seasonal" = "green", "Irregular" = "blue")) +
  scale_y_continuous(labels = ~format(.x, nsmall = 2)) +
  scale_x_date(labels = NULL, breaks = NULL, expand = c(0, 0),
               date_minor_breaks = "1 month") + 
  facet_wrap(~year, nrow = 1, scales= 'free_x',
             strip.position = 'bottom') +
  theme(panel.spacing.x = unit(0, "lines"),
        panel.grid = element_blank(), 
        legend.position = "top",
        strip.background = element_rect(colour = "white", fill = "grey"))

enter image description here

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87