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

如何在RMarkdown HTML文档中实现带下拉选择的动态STL时序分解图

无Shiny实现RMarkdown动态切换STL时序分解图

核心思路

不用Shiny框架的话,我们可以通过批量生成各产品的STL分解可视化图表,再结合原生HTML下拉选择框和JavaScript实现动态切换,彻底避免手动逐个处理子集的重复工作。


步骤1:准备数据集

先构造符合要求的2018年起月度销售数据(包含产品A/B/C),如果是自有数据,直接替换这部分即可:

library(tidyverse)
library(tsibble)
library(highcharter)
library(stats)
library(htmltools)

# 生成模拟数据(自有数据可替换此处)
set.seed(123)
date_seq <- seq.Date(as.Date("2018-01-01"), as.Date("2023-12-01"), by = "month")
products <- rep(c("A", "B", "C"), each = length(date_seq))
sales <- c(
  ts(rnorm(length(date_seq), 50, 5) + seq(1, length(date_seq))*0.2, frequency = 12) %>% as.numeric(),
  ts(rnorm(length(date_seq), 40, 6) + seq(1, length(date_seq))*0.15 + sin(seq(1, length(date_seq))*pi/6), frequency = 12) %>% as.numeric(),
  ts(rnorm(length(date_seq), 60, 4) + seq(1, length(date_seq))*0.25 + cos(seq(1, length(date_seq))*pi/4), frequency = 12) %>% as.numeric()
)

sales_data <- tibble(date = rep(date_seq, 3), product = products, sales = sales) %>%
  as_tsibble(key = product, index = date)

步骤2:批量生成STL分解与可视化图表

用group_map按产品分组批量处理STL分解,同时为每个产品的图表分配唯一ID,方便后续切换控制:

# 批量生成各产品的STL分解图
stl_plots <- sales_data %>%
  group_by(product) %>%
  group_map(function(data, key) {
    # 转换为时间序列对象
    ts_data <- ts(data$sales, frequency = 12, start = c(2018, 1))
    # STL时序分解
    stl_result <- stl(ts_data, s.window = "periodic")
    # 生成highcharter可视化图表
    hc <- highchart() %>%
      hc_title(text = paste("产品", key$product, "STL时序分解")) %>%
      hc_xAxis(categories = format(data$date, "%Y-%m")) %>%
      hc_add_series(name = "原始序列", data = stl_result$time.series[, "data"], type = "line") %>%
      hc_add_series(name = "趋势项", data = stl_result$time.series[, "trend"], type = "line") %>%
      hc_add_series(name = "季节项", data = stl_result$time.series[, "seasonal"], type = "line") %>%
      hc_add_series(name = "残差项", data = stl_result$time.series[, "remainder"], type = "line") %>%
      hc_yAxis(title = list(text = "销售额")) %>%
      hc_legend(enabled = TRUE)
    # 将图表包裹在带唯一ID的div中
    div(id = paste0("stl-plot-", key$product), hc)
  }) %>%
  tagList()

步骤3:添加下拉选择框与切换逻辑

在RMarkdown中插入原生HTML下拉框,搭配JavaScript实现图表的显示/隐藏切换:

<div style="margin: 1em 0;">
  <label for="product-select">选择产品:</label>
  <select id="product-select">
    <option value="A" selected>产品A</option>
    <option value="B">产品B</option>
    <option value="C">产品C</option>
  </select>
</div>

<script>
// 初始状态:只显示产品A的图表,隐藏其他
document.querySelectorAll('[id^="stl-plot-"]').forEach(plot => {
  plot.style.display = plot.id === 'stl-plot-A' ? 'block' : 'none';
});

// 监听下拉框变化,切换对应图表
document.getElementById('product-select').addEventListener('change', function() {
  const selected = this.value;
  document.querySelectorAll('[id^="stl-plot-"]').forEach(plot => {
    plot.style.display = plot.id === `stl-plot-${selected}` ? 'block' : 'none';
  });
});
</script>

完整RMarkdown代码整合

将上述内容整合为可直接运行的RMarkdown文档,输出格式设为html_document:

---
title: "动态切换STL时序分解图"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(tsibble)
library(highcharter)
library(stats)
library(htmltools)
# 生成模拟数据(自有数据替换此处)
set.seed(123)
date_seq <- seq.Date(as.Date("2018-01-01"), as.Date("2023-12-01"), by = "month")
products <- rep(c("A", "B", "C"), each = length(date_seq))
sales <- c(
  ts(rnorm(length(date_seq), 50, 5) + seq(1, length(date_seq))*0.2, frequency = 12) %>% as.numeric(),
  ts(rnorm(length(date_seq), 40, 6) + seq(1, length(date_seq))*0.15 + sin(seq(1, length(date_seq))*pi/6), frequency = 12) %>% as.numeric(),
  ts(rnorm(length(date_seq), 60, 4) + seq(1, length(date_seq))*0.25 + cos(seq(1, length(date_seq))*pi/4), frequency = 12) %>% as.numeric()
)

sales_data <- tibble(date = rep(date_seq, 3), product = products, sales = sales) %>%
  as_tsibble(key = product, index = date)
# 批量生成各产品的STL分解图
stl_plots <- sales_data %>%
  group_by(product) %>%
  group_map(function(data, key) {
    ts_data <- ts(data$sales, frequency = 12, start = c(2018, 1))
    stl_result <- stl(ts_data, s.window = "periodic")
    hc <- highchart() %>%
      hc_title(text = paste("产品", key$product, "STL时序分解")) %>%
      hc_xAxis(categories = format(data$date, "%Y-%m")) %>%
      hc_add_series(name = "原始序列", data = stl_result$time.series[, "data"], type = "line") %>%
      hc_add_series(name = "趋势项", data = stl_result$time.series[, "trend"], type = "line") %>%
      hc_add_series(name = "季节项", data = stl_result$time.series[, "seasonal"], type = "line") %>%
      hc_add_series(name = "残差项", data = stl_result$time.series[, "remainder"], type = "line") %>%
      hc_yAxis(title = list(text = "销售额")) %>%
      hc_legend(enabled = TRUE)
    div(id = paste0("stl-plot-", key$product), hc)
  }) %>%
  tagList()
stl_plots
---

内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:15:36