首页 文章

根据用户输入替换数据集中的值

提问于
浏览
1

我想使用另一个数据帧(B)更新数据帧(A) . B在 ui 中,用户可以选择更新表B中的数据 . 根据B中的更新值,我想更新A.请参阅下面的代码,代码允许用户更新B但是A点击后没有得到更新按钮:

df2 <- structure(list(A = c(1L, 4L, 0L, 1L), 
                      B = c("3", "*", "*", "2"), 
                      C = c("4", "5", "2", "*"), 
                      D = c("*", "9", "*", "4")), 
                 .Names = c("A", "B", "C", "D"), 
                 class = "data.frame", 
                 row.names = c(NA, -4L))
df1 <- structure(list(variable = c("A", "B", "C", "D"), 
                      Value = c(2L,1L, 9L, 0L)), 
                 .Names = c("variable", "Value"), 
                 class = "data.frame",
                 row.names = c(NA, -4L))
shinyApp(
  ui <-
    fluidPage(
      titlePanel("Sample"),

      # Create a new row for the table.
      sidebarLayout(
        sidebarPanel(
          selectInput("select", label = h3("Select Variable"), 
                      choices = unique(df1$variable), 
                      selected = unique(df1$variable)[1]),
          numericInput("num", label = h3("Replace * with"), 
                          value = unique(df1$variable)[1]),
          actionButton("applyChanges", "Apply Changes")),
        mainPanel(
          dataTableOutput(outputId="table")
        ))),
  Server <- function(input, output) {

    # Filter data based on selections
    output$table <- renderDataTable({
      df1$Value[df1$variable==input$select] <<- input$num
      df1
    })
    df2_new <- eventReactive(input$applyChanges,{
      df1[as.character(df1$variable)] <- Map(function(x, y)
        replace(x, x=="*", y), df2[as.character(df1$variable)], df1$Value)
      df2_new <- df2
      return(df2_new)
    })
  })

任何帮助将受到高度赞赏 . 谢谢!!

1 回答

  • 1

    这符合你的想法:

    library(shiny)
    # old df2
    dfaa <- data.frame(A = c( 1L, 4L, 0L, 1L), 
                       B = c("3","*","*","2"), 
                       C = c("4","5","2","*"), 
                       D = c("*","9","*","4"),stringsAsFactors = F) 
    # old df1
    dfbb <- data.frame(variable = c("A","B","C","D"), 
                      Value    = c( 2L, 1L, 9L, 0L),stringsAsFactors = F)
    
    ui <-  fluidPage(titlePanel("Sample"),
      sidebarLayout(
        sidebarPanel(
          selectInput("select", label = h3("Select Variable"), 
                      choices = unique(dfbb$variable), 
                      selected = unique(dfbb$variable)[1]),
          numericInput("num", label = h3("Replace * in A with"), 
                       value = unique(dfbb$Value)[1]),
          actionButton("applyChanges", "Apply Changes specified in B to A")),
        mainPanel(
          h3("Table A"),  dataTableOutput(outputId="tableA"),
          h3("Table B"),  dataTableOutput(outputId="tableB")
    )))
    
    server <- function(input, output) {
      rv <- reactiveValues(dfA=dfaa,dfB=dfbb)
      observe({
        # update dfB immediately when the variable or value in the ui changes
        rv$dfB$Value[rv$dfB$variable==input$select] <- input$num
      })
    
      observeEvent(input$applyChanges,{
        # Here we apply the changes that were specified
        dfAcol <-as.character(rv$dfB$variable)
        rv$dfA[dfAcol] <- 
              Map(function(x, y) replace(x, x=="*", y), rv$dfA[dfAcol], rv$dfB$Value)
      })
      output$tableB <- renderDataTable({ rv$dfB })
      output$tableA <- renderDataTable({ rv$dfA })
    }
    shinyApp(ui=ui,server=server)
    

    笔记:

    • 它实际上非常接近您发布的原始代码 .

    • 为了实现数据更新,我使用了 reactiveValuesobserve 而不是 eventReactive ,你可以用我之前提到的 eventReactive 来做,你试过,我也试过了,但这种方式更清洁,更清晰,避免了可怕的 <<- .

    • 将表B添加到主面板,以查看发生了什么 .

    • 我将 df2 重命名为 dfaa ,将 df1 重命名为 dfbb . 我只是不能保持 df1 作为表B和 df2 作为表A在我脑海中,它太混乱了 .

    • 我也使初始化程序更加人性化 - 输出很难读取 dput .

    • 使用 dplyr 可以更清楚地完成 mapinput$num 任务 . 我建议使用 dplyr ,因为它确实可以实现更清晰,更不容易出错的代码 .

    • 我从 shinyApp 调用中取出了 uiserver 函数,这为您提供了更多缩进空间和更常见的模式 .

    强制截图:

    enter image description here

相关问题