2

If I have a data.frame df

library(lubridate)
library(ggplot2)
library(dplyr)

day.start = today()

df = data.frame(date = seq.Date(from = today() - days(10), to = today() + days(10), 'day'))
df$day.idx = as.numeric(df$date - day.start + 1)
df$day.idx = ifelse(df$day.idx < 1, df$day.idx + nrow(df), df$day.idx)
df = df %>% arrange(day.idx)            
df$value = 1:nrow(df)

I can plot the values vs dates like this

ggplot(df) + 
  geom_line(aes(x = date, y = value))

However I want to make an adjustment for a custom year so I want the x axis to start at today's date.

## I want the x axis to start with day.start
df = df %>% mutate(date = factor(date, levels = as.character(df$date)))

## how to change x axis to behave like dates again?
ggplot(df) + 
  geom_point(aes(x = date, y = value)) +
  geom_line(aes(x = date, y = value)) ## where is this line?

So the second plot looks better but how do I format the x-axis to look like (nicely spaced) dates again?

 for

Rafael
  • 3,096
  • 1
  • 23
  • 61

4 Answers4

0

With your code as is, I get the following message:

geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

So ggplot doesn't know to "connect the dots", this is why the message mentions adjusting the group aesthetic. To combat this, I assigned 1 to gorup.

ggplot(df, aes(x = date, y = value, group = 1)) + 
  geom_point() +
  geom_line()

enter image description here

However, I wouldn't recommend this approach because your dates are then out of order, as can be seen if we adjust your x-axis text:

df %>% 
  ggplot(aes(x = date, y = value, group = 1)) + 
  geom_point() +
  geom_line() + 
  theme(axis.text.x = element_text(angle = 75, hjust = 1))

enter image description here

Edit: I'd recommend keeping your date field as a date, and using filter to keep only the observations you want before piping into ggplot:

df %>% 
  mutate(date = as_date(date)) %>% 
  filter(date >= today()) %>% 
  ggplot(aes(x = date, y = value)) + 
  geom_line() + 
  scale_x_date()

enter image description here

OTStats
  • 1,820
  • 1
  • 13
  • 22
0

Try:

df[df$date > today(), ] %>% 
   mutate(date = as.Date(date)) %>% 
   ggplot(aes(x = date, y = value)) + geom_line() + geom_point()

EDIT: An option would be to use filter rather than df[df$date > today(), ](check @OTStats's answer)

warnbergg
  • 552
  • 4
  • 14
0

If you want the x-axis to stay in the same order as in your example, and you just want it to be readable, I recommend changing the angle of the text:

ggplot(df) + 
  geom_point(aes(x = date, y = value), group = 1) +
  geom_line(aes(x = date, y = value), group = 1) +  
  theme(axis.text.x = element_text(angle = 75, hjust = 1))
mmyoung77
  • 1,343
  • 3
  • 14
  • 22
0

Found a solution from this answer: https://stackoverflow.com/a/26611593/5319229

Turns out it has nothing to do with factors.

The bdscale package came in handy.

library(lubridate)
library(ggplot2)
library(dplyr)

day.start = today()

df = data.frame(date = seq.Date(from = today() - days(10), to = today() + days(10), 'day'))
df$day.idx = as.numeric(df$date - day.start + 1)
df$day.idx = ifelse(df$day.idx < 1, df$day.idx + nrow(df), df$day.idx)
df = df %>% arrange(day.idx)            
df$value = 1:nrow(df)

ggplot(df) + 
  geom_point(aes(x = date, y = value)) +
  geom_line(aes(x = date, y = value, group = 1))+
  bdscale::scale_x_bd(business.dates = df$date, labels = scales::date_format('%b %d'))
Rafael
  • 3,096
  • 1
  • 23
  • 61