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

如何在Shiny中创建可定时更新数据的交互式Donut Chart

实现Shiny动态甜甜圈图(定时更新)

核心方案

要实现每隔1-2秒从tibble数据框取对应行更新甜甜圈图,关键是用reactiveTimer()创建定时触发器,配合响应式变量跟踪当前行索引,每次触发时切换数据并重新渲染图表。

完整可运行代码

假设你的示例数据框结构如下(每行对应一组甜甜圈切片数据):

library(tibble)
df <- tibble(
  group = list(c("A", "B", "C")),
  value = list(c(30, 50, 20), c(40, 40, 20), c(20, 60, 20), c(50, 30, 20))
)

修改后的Shiny代码:

library(shiny)
library(ggplot2)
library(tibble)

# 示例数据框
df <- tibble(
  group = list(c("A", "B", "C")),
  value = list(c(30, 50, 20), c(40, 40, 20), c(20, 60, 20), c(50, 30, 20))
)

ui <- fluidPage(
  plotOutput("donut_plot")
)

server <- function(input, output, session) {
  # 创建1-2秒的随机定时触发器(避免机械重复感)
  auto_refresh <- reactiveTimer(sample(1000:2000, 1))
  
  # 跟踪当前数据行的索引
  current_row <- reactiveVal(1)
  
  # 响应式获取当前行数据
  current_donut_data <- reactive({
    auto_refresh() # 触发定时更新
    row_num <- current_row()
    
    # 循环切换行:到最后一行后回到第一行
    if (row_num >= nrow(df)) {
      current_row(1)
    } else {
      current_row(row_num + 1)
    }
    
    # 提取当前行数据并转为ggplot可用格式
    tibble(
      group = df$group[[current_row()]],
      value = df$value[[current_row()]]
    )
  })
  
  # 渲染动态甜甜圈图
  output$donut_plot <- renderPlot({
    plot_data <- current_donut_data()
    # 可选:添加百分比标签
    plot_data$percent <- paste0(round(plot_data$value / sum(plot_data$value) * 100), "%")
    
    ggplot(plot_data, aes(x = 2, y = value, fill = group)) +
      geom_col(color = "white") +
      coord_polar(theta = "y") +
      xlim(0.5, 2.5) # 挖空中间形成甜甜圈效果
      geom_text(aes(label = percent), position = position_stack(vjust = 0.5)) +
      theme_void() +
      theme(legend.position = "bottom")
  })
}

shinyApp(ui, server)

关键修改说明

  • 定时触发:reactiveTimer()生成1-2秒的随机间隔,每次触发会强制current_donut_data()重新计算。
  • 行索引管理:用reactiveVal()保存当前行号,每次更新时自动切换到下一行,循环遍历整个数据框。
  • 响应式数据处理:current_donut_data()作为响应式数据源,每次定时触发都会提取最新行的数据,确保图表用的是最新切片长度。
  • 甜甜圈实现:通过coord_polar(theta = "y")和xlim()的组合,把柱状图转为甜甜圈样式。

适配调整提示

  • 如果你的df结构不同(比如group是独立列而非列表),只需修改current_donut_data()中提取数据的逻辑即可。
  • 若需要固定间隔更新,把sample(1000:2000, 1)改成固定数值(比如1500代表1.5秒)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:55:24