setX
setX

Reputation: 45

geom_line with x-axis in order of appearance

this is the first question I post here, so please excuse if I don't provide all information right away.

I'm trying to build a line graph with two lines:

y1 <- c(1000,1500,1000,1500,2000,3000,4000)

y2 <- c(1100,1400,900,1500,2000,2500,3500)

x <- c(49,50,51,1,2,49,50)

df <- data.frame(y1,y2,x)

Imagine x being calendar weeks, I skipped the weeks between 3 and 48 of the second year. Now I want to build a line graph, which display the x-axis values (time series) in this order.

First I tried a really simple approach:

p <- ggplot()

p <- p + geom_line(data=df,aes(x=x,y=y1))

p <- p + geom_line(data=df,aes(x=x,y=y2), color = "red")

p

Problem: R sorts the x values and also sums up same week numbers.

I then tried to change the x values to make them unique, e.g. 49/19,50/19, but R still changes the order. Same happens if I use geom_path instead of geom_line.

I then tried to change x to a factor and use x_scale_discrete, but I couldn't figure out, how to do it, either the lines or the x labels were always missing.

I hope you can give me some kind of advice.

Many thanks,

Andre

Upvotes: 2

Views: 1409

Answers (2)

StupidWolf
StupidWolf

Reputation: 47008

You can add a prefix of the year to your x value, and we pad it using str_pad() from stringr with a zero, so that they will be sorted from 01 all the way to 52:

library(tidyr)
library(stringr)
library(ggplot2)

df$week = paste(rep(c("2019","2020"),c(3,4)),
str_pad(df$x,2,pad="0"),sep="_")

pivot this long, so that we get a legend:

pivot_longer(df[,c("week","y1","y2")],-week)
    # A tibble: 14 x 3
   week    name  value
   <chr>   <chr> <dbl>
 1 2019_49 y1     1000
 2 2019_49 y2     1100
 3 2019_50 y1     1500
 4 2019_50 y2     1400
 5 2019_51 y1     1000
 6 2019_51 y2      900
 7 2020_01 y1     1500
 8 2020_01 y2     1500
 9 2020_02 y1     2000

Then use this directly in ggplot

ggplot(pivot_longer(df[,c("week","y1","y2")],-week),
aes(x=week,y=value,group=name,col=name)) + 
geom_line() + scale_color_manual(values=c("black","red"))

enter image description here

Upvotes: 3

Ian Campbell
Ian Campbell

Reputation: 24888

One approach is to replace x with a sequence of integers and then apply the x-axis labels afterwards.

library(ggplot2)
ggplot(data = df, aes(x = seq(1,nrow(df)))) + 
  geom_line(aes(y=y1)) + 
  geom_line(aes(y=y2), color = "red") + 
  scale_x_continuous(breaks = seq(1,nrow(df)),
                     labels = as.character(df$x)) + 
  labs(x = "Week")

enter image description here

Upvotes: 3

Related Questions