Marble
Marble

Reputation: 125

Sorting out dataframe axis labels in ggplot

I have a data frame (df) in simple form looking like this:

   year    month  place  Value
1  2017     11     A     8
2  2017     11     B     14
3  2017     11     C     17
4  2017     12     A     55
5  2017     12     B     12
6  2017     12     C     69
7  2018     11     A     42
8  2018     11     B     25
9  2018     11     C     21
10 2018     12     A     26
11 2018     12     B     81
12 2018     12     C     14

I am trying to plot multiple graphs for each A, B, and C to observe the changes over the month from that of the previous month

library(zoo)
library(ggplot2)
df$time <- as.yearmon(paste(df$Year,df$month), "%Y %m")
ggplot(df, aes(x=as.character(time), y= Value, color= as.factor(place))) 
+geom_point()+geom_line(aes(group=1))+ facet_grid(place~., scales = "free_y")

But this isn't working. Even though the x-axis is sorted out in the data frame, it is getting scrambled as the x-axis gets labeled as Nov 2017, then Nov 2018 instead of Nov 2017, then Dec 2017. What am I doing wrong here?

Upvotes: 0

Views: 103

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269644

There are several problems with the code in the question:

  1. the yearmon column is converted to character so it is no longer continuous
  2. df contains year but the code uses Year

Fixing those problems would be sufficient but suggest that instead use autoplot. Using the input shown reproducibly in the Note at the end convert df to a zoo object z and then it is a simple one line autoplot command using scale_x_yearmon.

Be sure that df is the one shown at the top of the question and also in the Note at the end and does NOT include the time column that is added in the question's code.

In read.zoo the index argument indicates which columns the time index lies in (year and month) the split argument indicates how to split the result into columns (one column for each place) and the FUN argument provides a function to convert the two index columns to a yearmon index. Then as mentioned, use autoplot.zoo with scale_x_yearmon.

Some optional items are that if a single panel showing all the plots is wanted then add the argument facets=NULL to the autoplot call. Also add +facet_free() if you want freely varying scales although it will be asier to make comparisons if the same scale is use don each as done below.

library(ggplot2)
library(zoo)

to_ym <- function(y, m) as.yearmon(paste(y, m, sep = "-"))
z <- read.zoo(df, index = c("year", "month"), split = "place", FUN = to_ym)

autoplot(z, col = Series) + scale_x_yearmon(n = 20)

screenshot

Note

Input in reproducible form:

Lines <- "year    month  place  Value
1  2017     11     A     8
2  2017     11     B     14
3  2017     11     C     17
4  2017     12     A     55
5  2017     12     B     12
6  2017     12     C     69
7  2018     11     A     42
8  2018     11     B     25
9  2018     11     C     21
10 2018     12     A     26
11 2018     12     B     81
12 2018     12     C     14"
df <- read.table(text = Lines)

Upvotes: 0

TarJae
TarJae

Reputation: 78927

Update see comments of OP:

  library(ggplot2)
df %>% 
  mutate(time = as.Date(paste(year, month,"01", sep = "-"))) %>% 
  ggplot(aes(x=time, y= Value, color= as.factor(place))) +
  geom_point()+
  geom_line(aes(group=place))+
  scale_x_date(date_labels="%b %y",date_breaks  ="1 month")+
  facet_grid(place~., scales= "free_y") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

enter image description here

First answer: With facet_grid

library(ggplot2)
df %>% 
  mutate(time = paste(month, year, sep = "-")) %>% 
  ggplot(aes(x=time, y= Value, color= as.factor(place))) +
  geom_point()+
  geom_line(aes(group=place))+
  facet_grid(place~., scales= "free_y")

enter image description here

Without facet_grid as State is not in the provided dataframe.

  1. you don't need first apply yearmon and then change class back to character
library(ggplot2)
library(dplyr)
df %>% 
  mutate(time = paste(month, year, sep = "-")) %>% 
  ggplot(aes(x=time, y= Value, color= as.factor(place))) +
  geom_point()+
  geom_line(aes(group=place))

enter image description here

data:

structure(list(year = c(2017L, 2017L, 2017L, 2017L, 2017L, 2017L, 
2018L, 2018L, 2018L, 2018L, 2018L, 2018L), month = c(11L, 11L, 
11L, 12L, 12L, 12L, 11L, 11L, 11L, 12L, 12L, 12L), place = c("A", 
"B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C"), Value = c(8L, 
14L, 17L, 55L, 12L, 69L, 42L, 25L, 21L, 26L, 81L, 14L), time = structure(c(NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_), class = "yearmon")), row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"), class = "data.frame")

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 388982

This works for me -

library(zoo)
library(ggplot2)

df$time <- as.yearmon(paste(df$year,df$month), "%Y %m")

ggplot(df, aes(x=time, y= Value, color= as.factor(place))) + 
  geom_point() +
  geom_line(aes(group=1)) + 
  facet_grid(place~., scales = "free_y")

enter image description here

data

df <- structure(list(year = c(2017L, 2017L, 2017L, 2017L, 2017L, 2017L, 
2018L, 2018L, 2018L, 2018L, 2018L, 2018L), month = c(11L, 11L, 
11L, 12L, 12L, 12L, 11L, 11L, 11L, 12L, 12L, 12L), place = c("A", 
"B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C"), Value = c(8L, 
14L, 17L, 55L, 12L, 69L, 42L, 25L, 21L, 26L, 81L, 14L)), 
class = "data.frame", row.names = c(NA, -12L))

Upvotes: 1

Related Questions