Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replicate this plot with R?

Tags:

r

ggplot2

lattice

I need to make several time-series graphs in the same format as shown in Fig. I'm interested in the format itself.

I will be grateful for your help.

enter image description here

Here a minimal example with simulated data

    set.seed(1234)
    nobs<-50
    x<-rnorm(nobs,0,10)
    t<-seq(1,nobs)
    data<-ts(20+x+t, freq=4, start=c(2004,1))
    par(family="serif")
    plot(data, lwd=2, col="blue4", ylab="Millions")
    title(main="Gráfico 1. Evolución del ...")
    legend(2010,10,"GDP", col="blue4",lwd=2)
    abline(lm(data~t), lwd=2, col="red") # This does not work 

enter image description here

like image 810
Héctor Garrido Avatar asked Sep 11 '26 17:09

Héctor Garrido


2 Answers

I assume that your data is a ts object, as in your example. Here is an approach using base graphics. We start off with a minimal plot, then layer on elements. First, the minimal plot, making sure to leave lots of space at side 1 (i.e. bottom):

par(mar = c(8, 4, 4, 2), family = "serif", las = 1)
plot(data, 
  frame = FALSE,
  xaxt = "n", 
  ylab = "Millones de pesos", xlab = "", 
  main = "Gráfico 1. Evolución del ...",
  col = "darkblue", lwd = 2)
fit <- forecast::tslm(data ~ trend)
lines(fitted(fit), col = "red", lwd = 2)

Note that above, we use forecast::tslm to get the time trend for the time series. Now, add the x-axis elements. I use mtext to insert the tick labels:

axis(1, at = seq(2003.875, 2015.875, 1), tck = -.2, labels = FALSE)
mtext(rep(c("ener-mar", "abril-jun", "jul-sep", "oct-dic"), l = length(data)),
  side = 1, line = 0.25, las = 2,
  at = seq(tsp(data)[1], tsp(data)[2], by = 1/tsp(data)[3]),
  cex = .6)
mtext(2004:2016, side = 1, line = 3, at = seq(2004.3, 2016.3), cex = .7)
title(xlab = "Trimestres", line = 5, cex.lab = .8)

Finish off with the legend:

par(xpd = TRUE)
legend(2010, -27, c("PIB", "Tendencia PIB"), 
  bty = "n",
  xjust = .5,
  lty = c(1, 1),
  col = c("darkblue", "red"),
  cex = .7,
  horiz = TRUE)

Output: enter image description here

like image 95
Weihuang Wong Avatar answered Sep 14 '26 12:09

Weihuang Wong


Here's a ggplot2 approach that comes close to the plot format in your question:

library(ggplot2)

# Fake data
set.seed(1234)
nobs<-52
t<-seq(1,nobs)
x<-rnorm(nobs,0,10) + t + 20
dat = data.frame(year=rep(2004:2016, each=4), qtr=rep(1:4, 13), x = x)

ggplot(dat, aes(paste(year,qtr), x)) +
  geom_vline(xintercept=seq(4.5,100,4), colour="grey80",lwd=0.3) +
  geom_line(aes(group=1)) +
  annotate(seq(2.5, 2.5 + 12*4, length.out=13), -2, label=2004:2016, 
           geom="text", colour="grey30", size=3.5) +
  theme_bw(base_size=10) +
  theme(axis.text.x=element_text(angl=-90, vjust=0.5, colour="grey30"),
        panel.grid.major.x=element_blank()) +
  scale_x_discrete(name="Quarter",
                   labels=rep(paste0(month.abb[seq(1,12,3)],"-",month.abb[seq(3,12,3)]),20)) +
  coord_cartesian(xlim=c(0,13*4 + 1), ylim=c(-4,max(dat$x + 2)), expand=FALSE) 

enter image description here

Facetting comes closer to the formatting you wanted, but there's no way (AFAIK) within the normal ggplot workflow to connect lines across the facets. In the plot below, the vertical lines show the borders between each facet. There are (somewhat complicated) ways to try and connect lines across facets, but I didn't make it that far in the example below.

dat$qtr = rep(paste0(month.abb[seq(1,12,3)],"-",month.abb[seq(3,12,3)]),13)
dat$qtr = factor(dat$qtr, levels=paste0(month.abb[seq(1,12,3)],"-",month.abb[seq(3,12,3)]))

p=ggplot(dat, aes(qtr, x)) +
  geom_line(aes(group=1)) +
  coord_cartesian(xlim=c(0.5,4.5), expand=FALSE, ylim=c(-2,80)) +
  facet_grid(. ~ year, switch="x") +
  annotate(x=c(0.5, 4.5), xend=c(0.5,4.5), y=-16, yend=-2, geom="segment", 
           colour="grey70", size=0.3) +
  theme_bw(base_size=10) +
  theme(panel.margin=unit(0,"lines"),
        axis.text.x=element_text(angl=-90, vjust=0.5, colour="grey30"),
        panel.border=element_rect(colour="grey70", size=0.3),
        panel.grid.major=element_blank(),
        strip.background=element_rect(fill="grey90", colour="grey20"),
        axis.line=element_line(colour="black")) +
  labs(x="Quarter")

# Turn off clipping and draw plot
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)

enter image description here

like image 27
eipi10 Avatar answered Sep 14 '26 12:09

eipi10