提问人:Curious Jorge - user9788072 提问时间:8/10/2023 最后编辑:Curious Jorge - user9788072 更新时间:8/10/2023 访问量:40
如何在R模块之间相互传输无功值?
How to reciprocally transmit reactive values between R modules?
问:
我正在尝试找到一种系统、稳健的方式,以双向流程在 R 模块之间传输反应式数据,我可以将其用作未来的模板。我还不清楚如何在模块之间传输数据。
在运行本文底部所示的示例 R Shiny 代码时,第一个模块将基本数据帧值乘以用户滑块输入值,第二个模块将 10 添加到 .然后,通过 in 函数,将表的第一列传输回,并将表中添加的列命名为“colA_mod2”。到目前为止一切正常。您可以运行底部发布的代码,看看它是如何工作的。mod1
df
mod2
mod1
observe()
mod1_server()
mod2
mod1
但是,如何将“colA_mod2”中的值乘以 100 并将这些值传回表并将这些值作为列附加到表中,以标记为“colA_mod2_mod1”?我想,如果我能看到这一步是如何工作的,我终于可以了解在模块之间双向传输值了。mod2
mod2
法典:
library(shiny)
library(DT)
mod1_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod2_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod1_server <- function(input, output, session, common) {
new_dat <- reactive({
df <- common$df
svc <- common$svc()
df * as.numeric(svc)
})
# the below transmits mod2 data back to mod1
observe({
common$mod1_dat <- new_dat()
common$colA_mod2 <- common$mod2_table$A
})
output$tbl <- renderDT({
dat <- new_dat()
dat$colA_mod2 <- common$colA_mod2
dat
})
}
mod2_server <- function(input, output, session, common) {
output$tbl <- renderDT({
mod1_dat <- common$mod1_dat
dat <- data.frame(mod1_dat + 10)
common$mod2_table <- dat
dat
})
}
ui <- fluidPage(
mainPanel(
h5(strong("Base table:")),
DTOutput("table"),
h5(strong(paste(
"Module 1 multiplies slider input by values in above table",
"and then tacks on column A from mod2 called `ColA_mod2´:"))),
sliderInput("svc", "", min = 0, max = 10, value = 1),
mod1_ui("mod1"),
h5(strong(paste(
"Module 2 then adds 10 to those Module 1 products [and then tacks on",
"a new column called `ColA_mod2_mod1` which is `ColA_mod2` from mod1",
"multipled by 100]:"))),
mod2_ui("mod2")
)
)
server <- function(input, output, session) {
common <- reactiveValues(df = data.frame(A = 1:2, B = 3:4))
output$table <- renderDT({datatable(common$df)})
common$svc <- reactive(input$svc)
callModule(mod1_server, "mod1", common)
callModule(mod2_server, "mod2", common)
}
shinyApp(ui, server)
答:
1赞
YBS
8/10/2023
#1
试试这个
library(shiny)
library(DT)
mod1_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod1_server <- function(id, common) {
moduleServer(id, function(input, output, session) {
new_dat <- reactive({
df <- common$df
svc <- common$svc()
df * as.numeric(svc)
})
# the below transmits mod2 data back to mod1
observe({
common$mod1_dat <- new_dat()
common$colA_mod2 <- common$mod2_table$A
})
output$tbl <- renderDT({
dat <- new_dat()
dat$colA_mod2 <- common$colA_mod2
dat
})
})
}
mod2_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod2_server <- function(id, common) {
moduleServer(id, function(input, output, session) {
output$tbl <- renderDT({
mod1_dat <- common$mod1_dat
dat <- data.frame(mod1_dat + 10)
if (!is.null(common$colA_mod2)) dat$colA_mod2_mod1 <- common$colA_mod2 * 10
common$mod2_table <- dat
dat
})
})
}
ui <- fluidPage(
mainPanel(
h5(strong("Base table:")),
DTOutput("table"),
h5(strong(paste(
"Module 1 multiplies slider input by values in above table",
"and then tacks on column A from mod2 called `ColA_mod2´:"))),
sliderInput("svc", "", min = 0, max = 10, value = 1),
mod1_ui("mod1"),
h5(strong(paste(
"Module 2 then adds 10 to those Module 1 products [and then tacks on",
"a new column called `ColA_mod2_mod1` which is `ColA_mod2` from mod1",
"multipled by 100]:"))),
mod2_ui("mod2")
)
)
server <- function(input, output, session) {
common <- reactiveValues(df = data.frame(A = 1:2, B = 3:4))
output$table <- renderDT({datatable(common$df)})
common$svc <- reactive(input$svc)
mod1_server("mod1", common)
mod2_server("mod2", common)
}
shinyApp(ui, server)
0赞
Curious Jorge - user9788072
8/10/2023
#2
我很难找到有关管理 R 模块之间数据流的好教程。但是,这篇文章对我很有帮助:https://rviews.rstudio.com/2021/10/20/a-beginner-s-guide-to-shiny-modules/
下面我为 YBS 解决方案添加注释,我还发布了一个我认为有用的数据流图。
法典:
library(shiny)
library(DT)
mod1_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod1_server <- function(id, common) {
moduleServer(id, function(input, output, session) {
# Create a reactive expression to perform data multiplication on base DF
new_dat <- reactive({
df <- common$df
svc <- common$svc()
df * as.numeric(svc)
})
# When the new_dat is updated, store it in common$mod1_dat
observe({
common$mod1_dat <- new_dat()
# Below pulls in Col A from mod2 for appending to mod1 table:
common$colA_mod2 <- common$mod2_table$A
})
# Render the DT table with mod1 data, including the appended column
output$tbl <- renderDT({
dat <- new_dat()
dat$colA_mod2 <- common$colA_mod2
dat
})
})
}
mod2_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod2_server <- function(id, common) {
moduleServer(id, function(input, output, session) {
# Render the DT table with mod2 data, including added columns
output$tbl <- renderDT({
mod1_dat <- common$mod1_dat
dat <- data.frame(mod1_dat + 10) # add 10 to mod1 cols A and B
# Below pulls in last added column from mod1 and multiply by 100 for
# appending to mod2 table:
if (!is.null(common$colA_mod2)) {
dat$colA_mod2_mod1 <- common$colA_mod2 * 100
}
common$mod2_table <- dat
dat
})
})
}
ui <- fluidPage(
mainPanel(
h5(strong("Base table:")),
DTOutput("table"),
h5(strong(paste(
"Module 1 multiplies slider input by values in above table and",
" then tacks on column A from mod2 called `ColA_mod2´:"))),
sliderInput("svc", "", min = 0, max = 10, value = 1),
mod1_ui("mod1"),
h5(strong(paste(
"Module 2 adds 10 to those Module 1 products for cols A and B and",
"then tacks on a new column called `ColA_mod2_mod1` which is",
"`ColA_mod2` from mod1 multiplied by 100:"))),
mod2_ui("mod2")
)
)
server <- function(input, output, session) {
# Create a reactiveValues object to store common data across modules
common <- reactiveValues(df = data.frame(A = 1:2, B = 3:4))
# Render the base table
output$table <- renderDT({datatable(common$df)})
# Store the slider input as a reactive value
common$svc <- reactive(input$svc)
# Call the server modules
mod1_server("mod1", common)
mod2_server("mod2", common)
}
shinyApp(ui, server)
图:
下面是另一个可能更易于理解的代码数据流图:
评论