Вставка отредактированных значений Datatable в блестящее приложение - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь понять, как использовать значения из отредактированной таблицы данных и сделать некоторые вычисления.

У меня есть фрейм данных, который загружается по умолчанию.Когда вы нажимаете «выполнить», он обновляет таблицы на основе входного значения.

Я хочу, чтобы пользователь вручную отредактировал значения в таблице и затем щелкнул «выполнить».Затем я хочу, чтобы приложение взяло отредактированные значения в таблице данных, выполнило некоторые вычисления и обновило таблицу.Таким образом, пользователь может динамически видеть результат своего ввода в таблицу.

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")

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Чистым решением (вместо присвоения значений в других средах) было бы использование 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")
0 голосов
/ 03 марта 2019

Это должно работать, но не самая «чистая» реализация:

Мне пришлось взять df из блеска, чтобы ваш код работал.Используется assign для замены df в глобальной среде (не лучшая идея ...) после редактирования данных.Но данные не пересчитываются до тех пор, пока не будет нажата Run.После нажатия Run данные модели перезаписываются: (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")
...