关于绘图:在R中绘制每月时间序列应该更简单

Plotting monthly time series in R should be simpler

R可能同时强大而令人沮丧。这使得向非统计学家(在我的情况下是商科学生)教授R颇具挑战性。让我用一个简单的任务说明一下。

假设您正在使用每月时间序列数据集。大多数业务数据通常以每月时间序列的形式绘制。我们想对数据进行绘图,使x轴描述月份和年份的组合。例如,2017年1月可以描述为2017-01。使用plot命令应该很简单。不对。

资料产生
让我们用一个例子来说明。我将从2007年1月开始至2017年12月结束时生成120个观测值的月度数据的随机时间序列,这些观测值代表10年的信息。这是代码。

1
2
3
4
set.seed(1234)
x <- rnorm(120)
d <-.07
y <- cumsum(x+d)*-1

由于我们尚未将数据声明为时间序列,因此使用plot命令对其进行绘制不会返回x轴的预期标签。请参见下面的代码和图表。

1
plot(y, type="l")

enter image description here

现在在plot或plot.ts命令中应该有一个选项来显示特定于时间序列的x轴。我找不到一个。所以这是解决方法。

  • 将数据集声明为时间序列。
  • 使用tsp和seq生成所需的x轴标签。
  • 绘制图表,但抑制x轴。
  • 使用axis命令添加自定义x轴标签。
  • 添加一个额外的步骤以在2012年绘制一条垂直线。
  • 这是代码。

    1
    2
    3
    4
    5
    6
    7
    my.ts <- ts(y, start=c(2007, 1), end=c(2017, 12), frequency=12)    
    tsp = attributes(my.ts)$tsp
    dates = seq(as.Date("2007-01-01"), by ="month", along = my.ts)
    plot(my.ts, xaxt ="n", main="Plotting outcome over time",
         ylab="outcome", xlab="time")
    axis(1, at = seq(tsp[1], tsp[2], along = my.ts), labels = format(dates,"%Y-%m"))
    abline(v=2012, col="blue", lty=2, lwd=2)

    结果如下图所示。
    enter image description here

    对于大多数数据科学家来说,这是一个可行的解决方案。但是,如果您的受众是商科学生或专业人士,则有太多的代码行需要编写。

    问题:是否可以通过使用带有控制X轴显示方式的format选项的plot命令来绘制时间序列变量(对象)?

    -


    我认为问题归结为想要为您想到的自定义轴提供预编写的功能。请注意,plot(my.ts)确实给出了每个月带有刻度线和每年带有标签的图表,对我来说,它看起来比问题中显示的图表更好,但是如果您想使用自定义轴,因为R是一种编程语言,则可以为从那以后,只需要调用该函数即可。

    例如,要开始使用此函数,该函数接受频率为12 ts的对象。它绘制一个带有刻度的X轴,每个月标记年份和每个月,每个参数都可以除以12。默认值是3,因此每三个月显示一个标签(Jan除外,显示为那一年)。 len是显示的月份的字母数,可以是1、2或3。1表示将Jul表示为J,2表示Ju且3表示Jul。默认值为1。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    xaxis12 <- function(ser, every = 3, len = 1) {
      tt <- time(ser)
      axis(side = 1, at = tt, labels = FALSE)

      is.every <- cycle(ser) %in% seq(1, 12, every)[-1]
      month.labs <- substr(month.abb[cycle(ser)][is.every], 1, len)
      axis(side = 1, at = tt[is.every], labels = month.labs,
        cex.axis = 0.7, tcl = -0.75)

      is.jan <- cycle(ser) == 1
      year.labs <- sprintf("'%02d", as.integer(tt)[is.jan] %% 100)
      axis(side = 1, at = tt[is.jan], labels = year.labs,
        cex.axis = 0.7, tcl = -1)
    }

    # test
    plot(my.ts, xaxt ="n")
    xaxis12(my.ts)

    screenshot


    ggplot2软件包具有scale_x_date功能,可按所需的比例,标签,间隔和限制(日,月,年格式)绘制时间序列。
    您只需要date类对象和值y。例如。

    1
    2
    3
    4
    5
    6
    7
    dates = seq(as.Date("01-01-2007",  format ="%d-%m-%Y"), length.out = 120, by ="month")
    df <- data.frame(dates, y)  

    # use the format you need in your plot using scale_x_date
    library(ggplot2)
    ggplot(df, aes(dates, y)) + geom_line() + scale_x_date(date_labels ="%b-%Y") +
    geom_vline(xintercept = as.Date("01-01-2012",  format ="%d-%m-%Y"), linetype = 'dotted', color = 'blue')

    y vs dates


    Gabor现场演出。这实际上取决于您想要什么,以及您愿意挖掘或更改的内容。这是使用更新和鲜为人知的软件包的一种简单替代方法,该软件包非常适合绘制xts类型:

    1
    2
    3
    4
    5
    6
    ## alternative
    library(rtsplot)            # load the plotting package
    library(xts)                # load the xts time-series container package
    xx <- as.xts(my.ts)         # create an xts object
    rtsplot(xx, main="Plotting outcome over time")
    rtsplot.x.highlight(xx, which(index(xx)=="Jan 2012"), 1)

    如您所见,绘图是两个调用-rtsplot有很多不错的默认值。下面是我很懒的屏幕截图,绘图窗口当然没有标题栏...

    enter image description here