2016-09-19 74 views
3

我需要制作几个时间序列图,格式如图1所示,我对格式本身很感兴趣。如何用R复制此图?

我将不胜感激您的帮助。

enter image description here

这里一个小例子,有模拟数据

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

+0

什么是 “相同的格式” 是什么意思? – hrbrmstr

+0

主要是x轴和y轴上的相同标签以及相同的图例位置。 –

+0

那么,和回归线。我尝试了与abline函数类似的东西,但它不起作用。 –

回答

6

我假定你的数据是ts对象,如你的榜样。这是一种使用base图形的方法。我们从一个最小的情节开始,然后对元素进行分层。首先,最小的地块,确保留下大量的空间在1侧(即底部):

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) 

注意上面,我们使用forecast::tslm以获取时间序列的时间趋势。现在,添加x轴元素。我用mtext插入刻度标签:

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) 

完成了与传说:

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) 

输出: enter image description here

3

这里有一个ggplot2方法来接近情节格式在你的问题:

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

方面更接近您想要的格式,但在正常的ggplot工作流程内无法实现连接各个方面的线条(AFAIK)。在下面的图中,垂直线显示每个面之间的边界。 There are (somewhat complicated) ways尝试连接各个方面的线条,但我没有在下面的例子中做到这一点。

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