You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中处理forecast包tsdisplay的输出:捕获与修改绘图

问题解决:forecast包中tsdisplay/ggtsdisplay的使用与绘图组合

问题描述

无法理解如何使用forecast包中的tsdisplay函数,生成三个AR(1)时间序列并存储在数据框中:

library(forecast)
N <- 200
ar1_processes <- matrix(nrow = 4, ncol = N)
ar1_processes[1,] <- 1:N
ar1_processes[2,] <- arima.sim(model = list(ar = c(0.1)), n = N)
ar1_processes[3,] <- arima.sim(model = list(ar = c(0.5)), n = N)
ar1_processes[4,] <- arima.sim(model = list(ar = c(0.9)), n = N)
ar1_processes <- as.data.frame(t(ar1_processes)) 
colnames(ar1_processes) <- c("time", "theta_0.1", "theta_0.5", "theta_0.9")

想要对比每个序列的tsdisplay输出(包含时间序列图、ACF图和PACF图的组合图),但当前代码生成三个独立输出且仅保存PACF图:

# saves only PACF plots
for (name in colnames(ar1_processes)[-1]){
  ar1_processes[name] %>% ggtsdisplay(main = paste("AR(1) with", name)) # ggtsdisplay
  ggsave(file.path("ar1_plots", paste(name, ".png", sep = "")))
}

需求:

  1. 将所有输出展示在一个大图中;
  2. 像操作ggplot一样修改绘图元素(如添加图层、修改标题);
  3. 将绘图保存到文件。

已尝试的方法

# doesn't work, only the last figure (ts, ACF, PACF) is displayed
par(mrow = c(3,1)) # c(3,3) doesn't change anything
for (name in colnames(ar1_processes)[-1]){
  ar1_processes[name] %>% tsdisplay(main = paste("AR(1) with", name))
}

# attempt to investigate object returned from ggtsdisplay
ar1_plots <- list()
for (name in colnames(ar1_processes)[-1]){
  ar1_plots[[name]] <- ar1_processes[name] %>% ggtsdisplay(main = paste("AR(1) with", name))
  ggsave(file.path("ar1_plots", paste(name, ".png", sep = "")))
}

ar1_plots[["theta_0.9"]] %>% View() # wasn't useful 

解决方案

核心要点

  • tsdisplay vs ggtsdisplay:tsdisplay基于R基础绘图系统,每次调用会自动创建3行1列的布局,无法通过par()合并多个输出;ggtsdisplay基于ggplot2,返回可编辑、可组合的ggplot对象,更适合你的需求。
  • 组合绘图:使用patchwork包可以轻松将多个ggtsdisplay生成的组合图合并为一个大图。
  • 保存绘图:必须将ggtsdisplay的结果赋值给变量,再用ggsave()保存该变量,避免只保存最后一个子图的问题。

完整代码示例

library(forecast)
library(ggplot2)
library(patchwork) # 用于组合ggplot对象
library(dplyr)

# 生成数据(复用你的代码)
N <- 200
ar1_processes <- matrix(nrow = 4, ncol = N)
ar1_processes[1,] <- 1:N
ar1_processes[2,] <- arima.sim(model = list(ar = c(0.1)), n = N)
ar1_processes[3,] <- arima.sim(model = list(ar = c(0.5)), n = N)
ar1_processes[4,] <- arima.sim(model = list(ar = c(0.9)), n = N)
ar1_processes <- as.data.frame(t(ar1_processes)) 
colnames(ar1_processes) <- c("time", "theta_0.1", "theta_0.5", "theta_0.9")

# 创建保存目录(如果不存在)
dir.create("ar1_plots", showWarnings = FALSE)

# 生成每个序列的ggtsdisplay图,并存入列表
plot_list <- lapply(colnames(ar1_processes)[-1], function(name) {
  # 将数据转换为ts对象(可选,但更符合时间序列分析规范)
  ts_data <- ts(ar1_processes[[name]], start = 1)
  
  # 生成基础组合图
  p <- ggtsdisplay(ts_data, main = paste("AR(1) with", name))
  
  # 像操作ggplot一样修改元素:比如更换主题、添加副标题
  p <- p + 
    theme_minimal() +
    labs(subtitle = paste("AR coefficient =", gsub("theta_", "", name))) +
    theme(plot.title = element_text(size = 12, face = "bold"))
  
  return(p)
})

# 1. 将所有图组合成一个大图:垂直堆叠(3行1列)
combined_plot <- plot_list[[1]] / plot_list[[2]] / plot_list[[3]]
# 若要水平堆叠,使用:plot_list[[1]] + plot_list[[2]] + plot_list[[3]]

# 添加总标题
combined_plot <- combined_plot + 
  plot_annotation(
    title = "Comparison of AR(1) Processes with Different Coefficients",
    theme = theme(plot.title = element_text(hjust = 0.5, size = 16, face = "bold"))
  )

# 2. 展示组合图
print(combined_plot)

# 3. 保存组合图到文件
ggsave(
  file.path("ar1_plots", "combined_ar1_plots.png"),
  combined_plot,
  width = 10,
  height = 12,
  dpi = 300
)

# 保存单个图(可选)
for (i in seq_along(plot_list)) {
  name <- colnames(ar1_processes)[-1][i]
  ggsave(
    file.path("ar1_plots", paste0(name, ".png")),
    plot_list[[i]],
    width = 8,
    height = 6
  )
}

常见问题解释

  1. 为什么par(mrow)不生效?
    tsdisplay内部会调用layout()函数设置3行1列的绘图布局,循环中每次调用都会重置布局,覆盖par()的设置,因此最后只显示最后一个tsdisplay的输出。

  2. 为什么之前的代码只保存PACF图?
    ggtsdisplay生成的是由三个ggplot子图组合成的gtable对象,如果不将其赋值给变量,R绘图环境中最后残留的是最后绘制的子图(PACF),ggsave()会默认保存这个残留图。赋值给变量后再保存即可得到完整的组合图。

内容的提问来源于stack exchange,提问作者stats_b

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:15:54