20 Time Series
This chapter originated as a community contribution created by HaiqingXu
This page is a work in progress. We appreciate any input you may have. If you would like to help improve this page, consider contributing to our repo.
This section discusses drawing graphics for time series data.
20.2 Single/Multiple Time Series
We can draw time series using geom_line() with time on the x-axis. X-axis should be an object in the Date class, assuming there is no hour/minute/second data.
library(tidyverse) ggplot(data = economics, aes(x = date, y = pop))+ geom_line(color = "blue") + ggtitle("US Population, in Thousands") + labs(x = "year", y = "population")
We can also draw multiple time series on one plot for comparison purpose:
<- read_csv("data/mortgage.csv") df <- df %>% gather(key = TYPE, value = RATE, -DATE) %>% df mutate(TYPE = forcats::fct_reorder2(TYPE, DATE, RATE)) # puts legend in correct order <- ggplot(df, aes(DATE, RATE, color = TYPE)) + geom_line() + g ggtitle("U.S. Mortgage Rates") + labs (x = "", y = "percent") + theme_grey(16) + theme(legend.title = element_blank()) g
The following exmaple shows the closing price for four big technology companies in the US. When analyzing GDP, salary level and stock prices, it is often difficult to compare trends since the scales are so different. For example, since AAPL and MSFT prices per share are so much lower than GOOG’s price per share, it’s hard to discern the trends:
library(tidyquant) <- c("AAPL", "GOOG", "IBM", "MSFT") stocks <- tq_get(stocks, from = as.Date("2013-01-01"), df to = as.Date("2013-12-31")) ggplot(df, aes(date, y = close, color = fct_reorder2(symbol, date, close))) + geom_line() + xlab("") + ylab("") + theme(legend.title = element_blank())
In such a case, it can be helpful to rescale the data. We rescaled the data to make sure these four stocks have a price of 100 on Jan 2013:
<- df %>% group_by(symbol) %>% df mutate(rescaled_close = 100*close / close) ggplot(df, aes(date, y = rescaled_close, color = fct_reorder2(symbol, date, rescaled_close))) + geom_line() + xlab("") + ylab("") + theme(legend.title = element_blank())
20.3 Secular Trend
Instead of looking at observations over time, we often want to ovserve overall long-term trend in our time series data. In this case, we can use geom_smooth(). Here we will show secular trend using the Loess Smoother.
<- df %>% filter(symbol == "AAPL") AAPL <- ggplot(AAPL, aes(date, close)) + geom_point() g + geom_line(color = "grey50") + g geom_smooth(method = "loess", se = FALSE, lwd = 1.5) + ggtitle("Loess Smoother for Apple Stock Price") + labs(x = "Date", y = "Price")
Experiment with different smoothing parameters.
+ geom_smooth(method = "loess", span = .5, se = FALSE)g
20.4 Seasonal Trends
In addition to secular trends, there are also seasonal trends in time series data. One way is to visualize seasonal trends is to use fact on season(day of month, day of week etc.).
library(lubridate) <- read_csv("data/ManchesterByTheSea.csv") dfman ggplot(dfman, aes(Date, Gross)) + geom_line() + facet_wrap(~wday(Date, label = TRUE), ncol = 1, strip.position="right")
Or, let us create a monthly plot.
20.5 Frequency of Data
What if you want to observe the frequency of time series data? A simple answer: use geom_point() in addition to geom_line().
# read file <- read_csv("data/WA_Sales_Products_2012-14.csv") %>% mydat mutate(Revenue = Revenue/1000000) # convert Quarter to a single numeric value Q $Q <- as.numeric(substr(mydat$Quarter, 2, 2)) mydat # convert Q to end-of-quarter date $Date <- as.Date(paste0(mydat$Year, "-", mydatas.character(mydat$Q*3), "-30")) <- mydat %>% group_by(Date, `Order method type`) %>% Methoddata summarize(Revenue = sum(Revenue)) <- ggplot(Methoddata, aes(Date, Revenue, g color = `Order method type`)) + geom_line(aes(group = `Order method type`)) + scale_x_date(limits = c(as.Date("2012-02-01"), as.Date("2014-12-31")), date_breaks = "6 months", date_labels = "%b %Y") + ylab("Revenue in mil $") + geom_point()g
There could be NA values in time series data. Using geom_point() with geom_line() is one way to detect missing values. Here we introduce another option: leave gaps.
$Date[year(Methoddata$Date)==2013] <- NA Methoddata<- ggplot(Methoddata, aes(Date, Revenue, g color = `Order method type`)) + geom_path(aes(group = `Order method type`)) + scale_x_date(limits = c(as.Date("2012-02-01"), as.Date("2014-12-31")), date_breaks = "6 months", date_labels = "%b %Y") + ylab("Revenue in mil $") g