【问题标题】:Allow users to add new variables to a dataset in Shiny App允许用户在 Shiny App 中向数据集添加新变量
【发布时间】:2017-06-16 21:56:52
【问题描述】:

嗨,Shiny 用户,

我希望我的用户能够将新变量添加到主数据框中。用户将使用 textInput 键入定义。然后我们将使用 server.R 将其添加到数据框中。这是我的代码。我无法让它工作。任何帮助将不胜感激。谢谢!

原始数据:

colA <- c('1','2','3','3','2')
colB <- c('1','1','3','3','2')
colC <- c('14','12','33','33','26')
colD <- c('Value','Mainstream','Value','Premium','Premium')
colE <- c(1,2,3,4,5)
rawdata <- as.data.frame(cbind(colA,colB, colC, colD, colE))
View(rawdata)

ui.R:

fluidPage(
            sidebarLayout(
                sidebarPanel(
                    textInput("addVar", "New attribute definition"),
                    helpText("Note: Type the attribute definition using R code."),
                    helpText("For example:"), 
                    helpText("data$Value <- ifelse (data$price_tiers_new == 'Value', 1, 0)"),

                    br(),
                    actionButton("addButton", strong("Add!")),
                    width = 3
                ),

                mainPanel(
                    verticalLayout(
                        br()
                        #Will display histogram of the newly added variables       
                    )
                )
           )
)

服务器.R:

function(input, output, session) {

    curr <- reactiveValues()
    curr$df <- rawdata

    observeEvent(input$addButton, {

        eval(parse(text=input$filter))

    })
}

例如,这里有两个新的变量定义可供尝试。如果我们添加第一个定义,rawdata 将有一个额外的列(值)。如果我们添加第二个定义,rawdata 将有两个额外的列(Value 和 Premium)。

curr$df$Value <- ifelse(curr$df$colD == 'Value', 1, 0)
curr$df$Premium <- ifelse(curr$df$colD == 'Premium', 1, 0)

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    使用eval(parse(text=input$addVar)) 应该可以工作。

    您还可以为textInput() 添加默认文本,以使textInput() 的使用(非常规但有趣)更加清晰。

    textInput("addVar", "New attribute definition", 
              "curr$df$Value <- ifelse(curr$df$colD == 'Value', 1, 0)")
    

    完整的应用程序(包括用于检查结果的 textOutput)将显示为:

    colA <- c('1','2','3','3','2')
    colB <- c('1','1','3','3','2')
    colC <- c('14','12','33','33','26')
    colD <- c('Value','Mainstream','Value','Premium','Premium')
    colE <- c(1,2,3,4,5)
    rawdata <- as.data.frame(cbind(colA, colB, colC, colD, colE))
    
    ui <- fluidPage(
      sidebarLayout(
        sidebarPanel(
          textInput("addVar", "New attribute definition", "curr$df$Value <- ifelse(curr$df$colD == 'Value', 1, 0)"),
          helpText("Note: Type the attribute definition using R code."),
          helpText("For example:"), 
          helpText("data$Value <- ifelse (data$price_tiers_new == 'Value', 1, 0)"),
          br(),
          actionButton("addButton", strong("Add!")),
          width = 3
        ),
    
        mainPanel(
          verticalLayout(
            br(),
            verbatimTextOutput("txt")
            #Will display histogram of the newly added variables       
          )
        )
      )
    )
    
    server <- function(input, output, session) {
      output$txt <- renderPrint(curr$df)
      curr <- reactiveValues()
      curr$df <- rawdata
    
      observeEvent(input$addButton, {
        eval(parse(text=input$addVar))
      })
    }
    
    shinyApp(ui, server)
    

    【讨论】:

    • eval(parse(text=)) 的范围是全球性的,这不是有风险吗?恶作剧或错误可能会影响当前文件夹中的所有文件。例如,您可以在文本框中添加文本mt3 &lt;&lt;- mtcars,退出程序后您将拥有 mt3 等着您。如果它可以创建,它可以删除或更改。请参阅 SO/SE 上的“eval(parse()) 的风险”讨论
    • 对不起,我听不懂,你指的是哪些文件?我还建议在闪亮中使用&lt;&lt;-。但如果你有更好的解决方案,你应该添加它!
    • 1. ('which files') 执行闪亮应用程序的命令行中可用的文件;例如(感谢@flodel)如果用户在 textInput 中输入rm(list=ls()) 以创建新变量,它将删除所有文件。 2.我没有劝阻在shiny中使用&lt;&lt;-。 3. 拥有更好的*解决方案并不是指出解决方案的既定风险的先决条件(Stack Exchange 指南)。 *更好
    • (续)...是主观的。我假设您的意思是没有所述风险的解决方案;请参阅下面的替代答案。
    【解决方案2】:

    虽然这个问题有一个公认的答案,但值得注意的是eval(parse()) 如果不小心使用会有很大的风险(例如:评估传入的文本按原样。请参阅@ 上的 SO 讨论987654321@).

    解决这些风险的一种方法是变异(无意双关)传入的文本和eval(parse()) 变异的文本。这样您就可以获得预期的结果或错误,但几乎不会像运行带有T &lt;- FALSE(感谢@flodel)或其他一些植入错误的长代码这样的灾难。

    例如:input_vectorname_vector分别是新变量定义条件和新变量名的列表。

    input_vector <- list()
    input_vector[[1]] <- "ifelse(am == 1, 'wohoo', 'io')"
    input_vector[[2]] <- "vs == 1"
    input_vector[[3]] <- "cyl >= 6" 
    input_vector[[4]] <- "0"    
    name_vector <- list()
    name_vector[[1]] <- "automatic_"
    name_vector[[2]] <- "VS_Equals_1_"
    name_vector[[3]] <- "HighCylinder_"
    name_vector[[4]] <- "Blank_"    
    new_var_count <- 1:4
    
    mutated_data <- reactive({
      mt %>% 
      {eval(parse(text=
      paste0("mutate_(.,", 
          paste0(name_vector, as.character(new_var_count),"= input_vector[[", 
          as.character(new_var_count), "]]", collapse= " , "),
          ")"
      )
    ))}
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 2021-01-23
      • 2012-07-01
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多