如何在编辑列时更新可编辑数据表并使用它在Shiny中执行连续计算

问题描述 投票:0回答:1

我正在尝试制作一个闪亮的计算器,用户可以编辑一列,数据表将更新其他列中的计算,这些计算使用 DT 中的用户输入、侧面板中的用户输入和/或其他列中的其他计算值。

这是我到目前为止所拥有的。我希望用户能够编辑“ppl”列,然后使用它来更新其他列。我刚刚用 72 填充了“ppl”,以便在那里有一些东西。自从我刚接触 R Shiny 以来,我已经被这个问题困扰了一段时间。我见过人们使用observeEvent,但我仍然对如何实现它感到困惑。感谢任何帮助或指导。

library(tidyverse)
library(shiny)
library(DT)

ui <- 
  sidebarLayout(
    sidebarPanel(
      numericInput("price", label = "Price ($)", value = 4.31, min = 0),
      numericInput("sqft", label = "Average Square Footage", value = 4400, min = 0),
      numericInput("delivery", label = "Delivery Cost", value = 2.60, min = 0),
      numericInput("avg_use", label = "Average Annual Use", value = 88000, min = 0),
      numericInput("turf", label = "Percentage (%)", value = 0, min = 0)
    ),
    mainPanel(
      DTOutput("table1")
    )
  )


server <- function(input, output, session) {
  
  df <- reactive({
    
    data.frame(
      behavior = c("A",
                   "B",
                   "C",
                   "D",
                   "E",
                   "F",
                   "G",
                   "H",
                   "I",
                   "J",
                   "K"),
      average = c(2541, 11913, 12707, 16995, 23668, 2859, 2224, 10483, 22555, 8259, 5718),
      ppl = c(72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72)
      
    ) |>
      # If there is an input for 'Percentage', modify E's total_land value by using the input
      mutate(total_land = ifelse(str_detect(behavior, "E") & input$turf > 0,
                                 ppl * input$sqft * input$turf,
                                 ppl * input$sqft),
             all_w = average * (total_land / 1000),
             all_ut = input$price * (all_w / 1000),
             annual_w = all_w / ppl,
             mon_w = annual_w / 12,
             annual_ut = all_ut / ppl,
             mon_ut = annual_ut / 12,
             deliv = (all_w / 1000) * input$delivery,
             supply = all_w / input$avg_use
      )
  })
  
    output$table1 <- renderDT(
      df(),
      selection = 'none',
      editable = list(target = 'column', disable = list(columns = c(0:1, 3:12))),
      server = T,
      rownames = F
    )
}

shinyApp(ui, server)
r shiny dt
1个回答
0
投票
library(tidyverse)
library(shiny)
library(DT)

ui <- 
  sidebarLayout(
    sidebarPanel(
      numericInput("price", label = "Price ($)", value = 4.31, min = 0),
      numericInput("sqft", label = "Average Square Footage", value = 4400, min = 0),
      numericInput("delivery", label = "Delivery Cost", value = 2.60, min = 0),
      numericInput("avg_use", label = "Average Annual Use", value = 88000, min = 0),
      numericInput("turf", label = "Percentage (%)", value = 0, min = 0)
    ),
    mainPanel(
      DTOutput("table1")
    )
  )

dat00 <- data.frame(
  behavior = c("A",
               "B",
               "C",
               "D",
               "E",
               "F",
               "G",
               "H",
               "I",
               "J",
               "K"),
  average = c(2541, 11913, 12707, 16995, 23668, 2859, 2224, 10483, 22555, 8259, 5718),
  ppl = c(72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72)
)

makeData <- function(dat0, turf, sqft, price, delivery, avg_use) {
  dat0 |>
    # If there is an input for 'Percentage', modify E's total_land value by using the input
    mutate(total_land = ifelse(str_detect(behavior, "E") & turf > 0,
                               ppl * sqft * turf,
                               ppl * sqft),
           all_w = average * (total_land / 1000),
           all_ut = price * (all_w / 1000),
           annual_w = all_w / ppl,
           mon_w = annual_w / 12,
           annual_ut = all_ut / ppl,
           mon_ut = annual_ut / 12,
           deliv = (all_w / 1000) * delivery,
           supply = all_w / avg_use
    )
}

server <- function(input, output, session) {
  
  Dat0 <- reactiveVal(dat00)

  output$table1 <- renderDT({
    dat <- makeData(
      isolate(Dat0()), 
      input$turf, input$sqft, input$price, input$delivery, input$avg_use
    )
    datatable(
      dat,
      rownames = FALSE,
      selection = "none",
      editable = list(target = "cell", disable = list(columns = c(0:1, 3:12)))
    )
  }, server = TRUE)
  
  proxy <- dataTableProxy("table1")
  
  observeEvent(input[["table1_cell_edit"]], {
    info <- input[["table1_cell_edit"]] 
    # update Dat0
    dat0 <- editData(Dat0(), info, rownames = FALSE) 
    Dat0(dat0) 
    # update the data in the table
    dat <- makeData(
      dat0, 
      input$turf, input$sqft, input$price, input$delivery, input$avg_use
    )
    replaceData(proxy, dat, resetPaging = FALSE, rownames = FALSE)
  })
  
}

shinyApp(ui, server)
© www.soinside.com 2019 - 2024. All rights reserved.