如何在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),可处理百万级数据,仅加载当前页内容,大幅降低前端压力 - 内置分页、排序、过滤等功能,无需额外配置
- 兼容性好,支持旧版本浏览器
- 基于成熟的DataTables.js,支持服务器端数据处理(设置
- reactable包:
- 基于React框架,前端渲染速度快,适合客户端渲染中等规模数据(万级以内)
- 支持虚拟滚动(设置
virtualize = TRUE),可高效展示长列表,但数据量过大时仍需配合服务器端处理 - 自定义性更强,支持React组件扩展,但学习成本略高
总体来说,若数据集规模超过10万行,DT的服务器端处理模式更稳定;若为万级以内数据,reactable的渲染体验更流畅。
内容的提问来源于stack exchange,提问作者Gurkenhals
相关产品推荐
相关产品推荐

