我试图了解如何使用编辑数据表中的值并进行一些计算。
我有一个默认加载的数据框。单击“运行”时,它会根据输入值更新表。
我希望用户在表格中手动编辑值,然后单击“运行”。接下来,我希望应用程序在数据表中获取已编辑的值,运行一些计算并更新表。通过这种方式,用户可以动态地查看其输入在表格上的结果。
library(shiny)
library(DT)
library(dplyr)
#### Module 1 renders the first table
tableMod <- function(input, output, session, modelRun,modelData,budget){
output$x1 <- DT::renderDataTable({
modelRun()
isolate(
datatable(
modelData %>%
mutate(New_Membership = as.numeric(Modified * 0.01)*(budget())),
selection = 'none', editable = TRUE
)
)
})
observeEvent(input$x1_cell_edit, {
df[input$x1_cell_edit$row,input$x1_cell_edit$col] <<- input$x1_cell_edit$value
})
}
tableUI <- function(id) {
ns <- NS(id)
dataTableOutput(ns("x1"))
}
ui <- function(request) {
fluidPage(
tableUI("opfun"),
numericInput("budget_input", "Total Forecast", value = 2),
actionButton("opt_run", "Run")
)
}
server <- function(input, output, session) {
df <- data.frame(Channel = c("A", "B","C"),
Current = c(2000, 3000, 4000),
Modified = c(2500, 3500,3000),
New_Membership = c(450, 650,700),
stringsAsFactors = FALSE)
callModule( tableMod,"opfun",
modelRun = reactive(input$opt_run),
modelData = df,
budget = reactive(input$budget_input))
observeEvent(input$opt_run, {
cat('HJE')
})
}
shinyApp(ui, server, enableBookmarking = "url")
一个干净的解决方案(而不是在其他环境中分配值)将在您的模块中使用与reactiveVal
同步的datatable
。您可以从模块返回此reactive
,以便在主应用程序中使用它:
library(shiny)
library(DT)
library(dplyr)
#### Module 1 renders the first table
tableMod <- function(input, output, session, modelRun, modelData, budget){
df <- reactiveVal(modelData) ## this variable will be in sync with your datatable
output$x1 <- DT::renderDataTable({
modelRun()
isolate(
datatable(
df() %>% ## ...you always use the synced version here
mutate(New_Membership = as.numeric(Modified * 0.01)*(budget())),
selection = 'none', editable = TRUE
)
)
})
observeEvent(input$x1_cell_edit, {
new_df <- df()
row <- input$x1_cell_edit$row
col <- input$x1_cell_edit$col
value <- as.numeric(input$x1_cell_edit$value)
new_df[row, col] <- value
df(new_df) ## ...and you make sure that 'df' stays in sync
})
list(updated_df = df) ## ...finally you return it to make use of it in the main app too
}
tableUI <- function(id) {
ns <- NS(id)
dataTableOutput(ns("x1"))
}
ui <- function(request) {
fluidPage(
tableUI("opfun"),
numericInput("budget_input", "Total Forecast", value = 2),
actionButton("opt_run", "Run")
)
}
server <- function(input, output, session) {
df <- data.frame(Channel = c("A", "B","C"),
Current = c(2000, 3000, 4000),
Modified = c(2500, 3500,3000),
New_Membership = c(450, 650,700),
stringsAsFactors = FALSE)
result <- callModule( tableMod,"opfun",
modelRun = reactive(input$opt_run),
modelData = df,
budget = reactive(input$budget_input))
observeEvent(input$opt_run, {
str(result$updated_df())
})
}
shinyApp(ui, server, enableBookmarking = "url")
这应该有效,但不是“最干净”的实现:
我不得不把df
从光亮中拿出来让你的代码工作。在编辑数据表后,使用assign
替换全局环境中的df
(不是最好的想法......)。但是,数据不会重新计算,直到按下Run
。按下Run
后,modelData被覆盖:(modelData <- df
)。再次不是最好的主意,可能使modelData
反应将是更好的主意。
另外,看看DT::replaceData
。它可能比重新生成全表更好。
library(shiny)
library(DT)
library(dplyr)
df <- data.frame(Channel = c("A", "B","C"),
Current = c(2000, 3000, 4000),
Modified = c(2500, 3500,3000),
New_Membership = c(450, 650,700),
stringsAsFactors = FALSE)
#### Module 1 renders the first table
tableMod <- function(input, output, session, modelRun,modelData,budget){
observeEvent( input$x1_cell_edit, {
cat ('input$x1_cell_edit \n')
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col
v = info$value
df[i, j] <- DT:::coerceValue(v, df[i, j])
assign("df", df, envir = .GlobalEnv)
})
output$x1 <- DT::renderDataTable({
modelRun()
modelData <- df
isolate(
datatable(
modelData %>%
mutate(New_Membership = as.numeric(Modified * 0.01)*(budget())),
selection = 'none', editable = TRUE
)
)
})
}
tableUI <- function(id) {
ns <- NS(id)
dataTableOutput(ns("x1"))
}
ui <- function(request) {
fluidPage(
tableUI("opfun"),
numericInput("budget_input", "Total Forecast", value = 2),
actionButton("opt_run", "Run")
)
}
server <- function(input, output, session) {
callModule( tableMod,"opfun",
modelRun = reactive(input$opt_run),
modelData = df,
budget = reactive(input$budget_input))
observeEvent(input$opt_run, {
cat('HJE')
})
}
shinyApp(ui, server, enableBookmarking = "url")