Search code examples
rggplot2numericx-axis

How to reorder a numeric x-axis in ggplot2?


First time posting, so please forgive any errors I make.

I'm attempting to plot some monthly values over the course of a year, starting in July. . Here is some sample data:

x <- seq(1, 12, 1)
set.seed(2022)
y <- rnorm(n = 12)

df <- data.frame("x" = x, "y" = y)

ggplot(data = df, aes(x = x, y = y))+
geom_line()

In this case, I would like to start the x-axis in July (x = 7). This is easy enough if I convert my x-axis variables to a factor. But, I need to keep the x-axis as a numeric scale because I'm attempting to use geom_tile to plot a sort of nominal color scale in the background, like so:

tile.df <- data.frame(
"x" = seq(1, 12, by = 1/12), # Note how the color scale is much higher resolution than the data
"y" = -4
)

ggplot(data = df, aes(x = x, y = y))+
theme_classic()+
geom_line()+
scale_x_continuous(breaks = seq(1, 12, 1))+
scale_fill_gradient2(low = "black", mid = "gray", high = "white", midpoint = 6)+
theme(legend.position = "none")+
geom_tile(data = tile.df, aes(y = y, fill = x), height = 0.5)

In my actual dataset, the 'white' portion of the geom_tile() actually starts in July, which is why I'd like my x-axis to start here.

Any help in this would be greatly appreciated!

Cheers,


Solution

  • You could reorder your months numerically then add labels in the correct order:

    library(ggplot2)
    
    x <- seq(1, 12, 1)
    set.seed(2022)
    y <- rnorm(n = 12)
    
    df <- data.frame("x" = x, "y" = y)
    
    df$x <- 1 +(df$x+5) %% 12
    
    tile.df <- data.frame(
      "x" = seq(1, 12, by = 1/12), # Note how the color scale is much higher resolution than the data
      "y" = -4
    )
    
    ggplot(data = df, aes(x = x, y = y))+
      theme_classic()+
      geom_line()+
      scale_x_continuous(breaks = seq(1, 12, 1), labels = c(month.abb[7:12], month.abb[1:6]))+
      scale_fill_gradient2(low = "black", mid = "gray", high = "white", midpoint = 6)+
      theme(legend.position = "none")+
      geom_tile(data = tile.df, aes(y = y, fill = x), height = 0.5)
    

    The line df$x <- 1 +(df$x+5) %% 12 is behind the scenes reordering your months so that July = 1 to be plotted, then the labels of the axis show months in the new order.

    A more intuitive way may be to convert to a factor, put in the order you want, then convert back to an integer when plotting (whilst similarly adding the correctly ordered labels:

    reordered_months <- c(month.abb[7:12], month.abb[1:6])
    
    df$month <- factor(month.abb[df$x], levels = reordered_months)
    
    ggplot(data = df, aes(x = as.numeric(month), y = y)) +
      theme_classic()+
      geom_line()+
      scale_x_continuous(breaks = seq(1, 12, 1), labels = reordered_months)+
      scale_fill_gradient2(low = "black", mid = "gray", high = "white", midpoint = 6)+
      theme(legend.position = "none")+
      geom_tile(data = tile.df, aes(y = y, x = x, fill = x), height = 0.5)
    

    (plots the same graph)

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