r - 在 Shiny App 中为多个反应式 DF 创建通用过滤器
问题描述
我正在构建一个仪表板,它需要显示多个表,每个表都有一个选项卡。数据都是相关的,我希望有通用过滤器,应用时将过滤所有表。作为一个简化的示例,假设我有以下汽车经销商的表格,其中包含有关客户、他们的车辆以及在车辆上执行的服务的信息:
顾客 | 邮政编码 | 年龄 |
---|---|---|
石匠 | 14350 | 44 |
都乐 | 14352 | 25 |
罗杰斯 | 14358 | 60 |
车辆识别码 | 模型 | 年 | 顾客 |
---|---|---|---|
355 | 翼豹 | 2015 | 石匠 |
1324 | 森林人 | 2020 | 都乐 |
121 | 凯美瑞 | 2018 | 罗杰斯 |
服务编号 | 服务 | 车辆识别码 |
---|---|---|
1 | 换油 | 355 |
2 | 刹车 | 355 |
3 | 传感器更换 | 355 |
4 | 换油 | 1324 |
5 | 刹车 | 121 |
我的目标是将这些表中的每一个都作为数据表呈现在 Shiny App 的自己的选项卡中。然后,我想要基于关系过滤所有表的通用过滤器。例如,如果我将服务表过滤为换油,我希望服务表只过滤换油,但也希望车辆和客户表根据车主/车辆是否符合换油标准进行过滤。
实现这一目标的最佳方法是什么?我试图动态循环遍历这些数据集,并为每个数据集创建一个响应式数据框以及一个输出表,但我正在努力研究如何同时将过滤器应用于所有数据框。在通过为每个视图/框架选择特定列来创建视图的情况下,创建一个大型数据框会是一个更好的选择吗?
解决方案
我们可以将三个表连接在一起,使用 selectizeGroup-module过滤它们,然后再次拆分它们。执行连接然后拆分可能会导致一些重复的行,但使用dplyr::distinct
可以解决它。
应用程序:
library(tidyverse)
library(shiny)
library(shinyWidgets)
library(gt)
customer <-
tribble(
~Customer, ~Zip_Code, ~Age,
"Mason", 14350, 44,
"Dole", 14352, 25,
"Rogers", 14358, 60
)
vehicle <-
tribble(
~Vehicle_ID, ~Model, ~Year, ~Customer,
355, "Impreza", 2015, "Mason",
1324, "Forester", 2020, "Dole",
121, "Camry", 2018, "Rogers"
)
service <-
tribble(
~Service_ID, ~Service, ~Vehicle_ID,
1, "Oil Change", 355,
2, "Brakes", 355,
3, "sensor replacement", 355,
4, "Oil Change", 1324,
5, "Brakes", 121
)
df_joined <- inner_join(customer, vehicle, by = "Customer")
df_joined <- left_join(df_joined, service, by = ("Vehicle_ID"))
nms <- names(df_joined)
params <- nms %>%
map(~ list(inputId = ., title = str_to_title(.))) %>%
set_names(nms)
ui <- fluidPage(
fluidRow(selectizeGroupUI(id = "my_filters", params = params)),
tabsetPanel(
tabPanel("Service", gt_output({
"service_table"
})),
tabPanel("Vehicle", gt_output({
"vehicle_table"
})),
tabPanel("Customer", gt_output({
"customer_table"
}))
)
)
server <- function(input, output, session) {
res_mod <- callModule(
module = selectizeGroupServer,
id = "my_filters",
data = df_joined,
vars = nms
)
df_splitted <- reactive({
map(
map(list(customer, vehicle, service), names),
~ select(res_mod(), all_of(.x))
) %>%
map(distinct) %>%
set_names(c("customer", "vehicle", "service"))
})
observeEvent(df_splitted(), { # the order of the table names matter
walk2(c("customer_table", "vehicle_table", "service_table"), df_splitted(), ~ {
output[[.x]] <<- render_gt({
.y
})
})
})
}
shinyApp(ui, server)
推荐阅读
- python - 为什么 from ... import ... 语句包含隐式导入?
- javascript - js for loop 无限循环
- javascript - 在自己的 npm 包中正确使用 Babel
- amazon-web-services - Lambda 函数未使用 Cron 触发
- android - 在主滚动视图内启用 Webview 内容滚动
- python - 在 Python3 中将小部件应用程序作为线程启动?
- docker - Windows docker 容器中的“无法打开程序数据库”问题
- regex - 正则表达式匹配字符串,与顺序无关
- ios - 在 swift 中根据类别在标题视图中显示数据
- r - 通过R中的选定列跨行查找重复元素