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

如何在R Shiny Dashboard用DT实现表间联动及大数据集包对比

问题解答

1. 基于DT包实现表联动的Dashboard

下面是修改后的完整代码,实现点击表1的行跳转到表2并展示对应用户的详情数据:

library(shiny)
library(shinydashboard)
library(DT)

d1 <- data.frame(
  name = c("Frank", "Emma", "Kurt", "Johanna", "Anna", "Ben", "Chris", "David", "Eva", "Felix", "Gina", "Hannah", "Iris", "Jack", "Karen", "Leo", "Mia", "Nina", "Omar", "Paul"),
  team = c("A", "A", "B", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B"),
  score = c(12, 15, 13, 13, 14, 11, 10, 16, 9, 8, 17, 14, 12, 13, 15, 16, 11, 10, 9, 8)
)

d2 <- data.frame(
  name = c(
    "Frank", "Frank", "Frank",
    "Emma", "Emma", "Emma",
    "Kurt", "Kurt", "Kurt",
    "Johanna", "Johanna", "Johanna",
    "Anna", "Anna", "Anna",
    "Ben", "Ben", "Ben",
    "Chris", "Chris", "Chris",
    "David", "David", "David",
    "Eva", "Eva", "Eva",
    "Felix", "Felix", "Felix",
    "Gina", "Gina", "Gina",
    "Hannah", "Hannah", "Hannah",
    "Iris", "Iris", "Iris",
    "Jack", "Jack", "Jack",
    "Karen", "Karen", "Karen",
    "Leo", "Leo", "Leo",
    "Mia", "Mia", "Mia",
    "Nina", "Nina", "Nina",
    "Omar", "Omar", "Omar",
    "Paul", "Paul", "Paul"
  ),
  match = c(
    1, 2, 3,  # Frank
    1, 2, 3,  # Emma
    1, 2, 3,  # Kurt
    1, 2, 3,  # Johanna
    1, 2, 3,  # Anna
    1, 2, 3,  # Ben
    1, 2, 3,  # Chris
    1, 2, 3,  # David
    1, 2, 3,  # Eva
    1, 2, 3,  # Felix
    1, 2, 3,  # Gina
    1, 2, 3,  # Hannah
    1, 2, 3,  # Iris
    1, 2, 3,  # Jack
    1, 2, 3,  # Karen
    1, 2, 3,  # Leo
    1, 2, 3,  # Mia
    1, 2, 3,  # Nina
    1, 2, 3,  # Omar
    1, 2, 3   # Paul
  ),
  score = c(
    4, 4, 4,  # Frank (12)
    5, 5, 5,  # Emma (15)
    4, 4, 5,  # Kurt (13)
    4, 4, 5,  # Johanna (13)
    5, 4, 5,  # Anna (14)
    4, 4, 3,  # Ben (11)
    4, 3, 3,  # Chris (10)
    6, 5, 5,  # David (16)
    3, 3, 3,  # Eva (9)
    3, 3, 2,  # Felix (8)
    6, 6, 5,  # Gina (17)
    5, 5, 4,  # Hannah (14)
    4, 4, 4,  # Iris (12)
    4, 4, 5,  # Jack (13)
    5, 5, 5,  # Karen (15)
    6, 5, 5,  # Leo (16)
    4, 4, 3,  # Mia (11)
    4, 3, 3,  # Nina (10)
    3, 3, 3,  # Omar (9)
    3, 3, 2   # Paul (8)
  )
)
ui <- dashboardPage(
  dashboardHeader(title = "Test"),
  dashboardSidebar(
    sidebarMenu(
      id = "tabs",
      menuItem("Table 1", tabName = "table1", icon = icon("table")),
      menuItem("Table 2", tabName = "table2", icon = icon("table"))
    )
  ),
  dashboardBody(
    tabItems(
      tabItem(tabName = "table1",
              fluidRow(
                box(width = 12,
                    title = "Table 1(点击行查看详情)",
                    dataTableOutput("table1"))
              )
      ),
      tabItem(tabName = "table2",
              fluidRow(
                box(width = 12,
                    title = textOutput("table2_title"),
                    dataTableOutput("table2"))
              )
      )
    )
  )
)

server <- function(input, output, session) {
  
  # 存储选中的用户名
  selected_name <- reactiveVal(NULL)
  
  output$table1 <- renderDataTable({
    datatable(
      d1,
      rownames = FALSE,
      editable = FALSE,
      selection = "none",
      filter="top",
      # 添加点击事件回调
      callback = JS("
        table.on('click.dt', 'tr', function() {
          var data = table.row(this).data();
          Shiny.setInputValue('selected_name', data[0]);
          Shiny.setInputValue('tabs', 'table2');
        });
      ")
    )
  })
  
  # 更新表2标题
  output$table2_title <- renderText({
    if (!is.null(selected_name())) {
      paste0("Table 2 - ", selected_name(), " 的比赛详情")
    } else {
      "Table 2(请先在表1中选择用户)"
    }
  })
  
  # 渲染过滤后的表2数据
  output$table2 <- renderDataTable({
    if (!is.null(selected_name())) {
      filtered_data <- d2[d2$name == selected_name(), ]
    } else {
      filtered_data <- d2
    }
    datatable(
      filtered_data,
      rownames = FALSE,
      editable = FALSE,
      selection = "none",
      filter="top"
    )
  })
  
  # 监听选中的用户名,确保切换标签后数据正确
  observeEvent(input$selected_name, {
    selected_name(input$selected_name)
  })

}

shinyApp(ui, server)

关键修改说明:

  • 新增selected_name响应式变量存储点击的用户名
  • 在表1的datatable中加入JS回调,点击行时自动获取用户名并发送给Shiny,同时切换到table2标签页
  • 表2根据selected_name过滤数据,动态更新标题显示当前用户信息

2. DT与reactable在大数据集上的对比

两者在大数据集展示上各有侧重,核心差异如下:

  • DT包:
    • 基于成熟的DataTables.js,支持服务器端数据处理(设置server = TRUE),可处理百万级数据,仅加载当前页内容,大幅降低前端压力
    • 内置分页、排序、过滤等功能,无需额外配置
    • 兼容性好,支持旧版本浏览器
  • reactable包:
    • 基于React框架,前端渲染速度快,适合客户端渲染中等规模数据(万级以内)
    • 支持虚拟滚动(设置virtualize = TRUE),可高效展示长列表,但数据量过大时仍需配合服务器端处理
    • 自定义性更强,支持React组件扩展,但学习成本略高

总体来说,若数据集规模超过10万行,DT的服务器端处理模式更稳定;若为万级以内数据,reactable的渲染体验更流畅。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:30:56