如何交互式更新外部文件中R闪亮输入窗口小部件中的默认(selected =)值,而不使用类似函数的update_Input?

时间:2017-09-10 02:54:30

标签: r shiny

我正在开发一个基于用户输入创建新数据(Excel)文件的应用程序,还允许用户重新加载以前创建的文件,根据需要显示/更新内容。据我所知,这需要更新各种输入函数中的默认值(selected =)。

该应用程序的工作方式如下:用户选择页面数量和填充数据,每个页面都保存为Excel文件中的工作表。当用户想要更新文件以添加或删除页面时,用户从访问受限文件夹加载excel文件,并且每个页面中的每个选项卡中的数据都会填充。然后,用户根据需要编辑输入值并保存数据。

我可以使用updateSelectInput和类似的函数来更新字段。挑战在于,每页有大约30个输入字段,最多需要600页,需要600个更新语句。我正在寻找一种简单有效的方法来实现这一目标。以下是一个示例,几乎展示了我想要实现的基本概念。

library(shiny)

Sel <- data.frame(list(x = c("Sepal.Length", "Petal.Length","3" )))

ui <- fluidPage(

  pageWithSidebar(

    headerPanel('Iris k-means clustering'),
    sidebarPanel(
      fileInput("File1", "Load File", multiple = FALSE, accept = NULL, width = NULL,
                buttonLabel = "Browse...", placeholder = "No file selected"),
      actionButton("NewValues", "Values from file"), 
      tags$br(),tags$br(),
      selectInput('xcol', 'X Variable', names(iris), selected = Sel$x[1]),
      selectInput('ycol', 'Y Variable', names(iris), selected = Sel$x[2]),
      selectInput('clusters', 'Cluster count', choices = seq(1:9), selected = Sel$x[3])
    ),

    mainPanel(
      plotOutput('plot1')
    )
  )
)

server <- function(input, output) {

  Sel <- eventReactive(input$NewValues, {
    inFile <- input$File1
    read.csv(inFile$datapath, header = TRUE)
     # The output of eventReactive function will be something equivalent to this: 
     # Sel <- data.frame(list(x = c("Petal.Length", "Sepal.Length","5" )))
  })

  selectedData <- reactive({
    iris[, c(input$xcol, input$ycol)]
  })

  clusters <- reactive({
    kmeans(selectedData(), input$clusters)
  })

  output$plot1 <- renderPlot({
    palette(c("#E41A1C", "#377EB8", "#4DAF4A", "#984EA3",
              "#FF7F00", "#FFFF33", "#A65628", "#F781BF", "#999999"))
    par(mar = c(5.1, 4.1, 0, 1))
    plot(selectedData(),
         col = clusters()$cluster,
         pch = 20, cex = 3)
    points(clusters()$centers, pch = 4, cex = 4, lwd = 4)
  })
}

shinyApp(ui = ui, server = server)

加载数据(CSV)文件时,从eventReactive函数创建的Sel数据框将等同于:

 Sel <- data.frame(list(x = c("Petal.Length", "Sepal.Length","5" )))

1 个答案:

答案 0 :(得分:2)

这是我能得到的最接近的:

library(shiny)

Sel2 <- data.frame(list(x = c("Sepal.Length", "Petal.Length","3" )))

ui <- fluidPage(

  pageWithSidebar(

    headerPanel('Iris k-means clustering'),
    sidebarPanel(
      fileInput("File1", "Load File", multiple = FALSE, accept = NULL, width = NULL,
                buttonLabel = "Browse...", placeholder = "No file selected"),
      actionButton("NewValues", "Values from file"), 
      tags$br(),tags$br(),
      uiOutput("select1"),
      #selectInput('xcol', 'X Variable', names(iris), selected = Sel$x[1]),
      #selectInput('ycol', 'Y Variable', names(iris), selected = Sel$x[2]),
      selectInput('clusters', 'Cluster count', choices = seq(1:9), selected = Sel2$x[3])
    ),

    mainPanel(
      plotOutput('plot1')
    )
  )
)

server <- function(input, output) {

  Sel <- eventReactive(input$NewValues, {
    inFile <- input$File1
    read.csv(inFile$datapath, header = TRUE)
    # The output of eventReactive function will be something equivalent to this: 
    # Sel <- data.frame(list(x = c("Petal.Length", "Sepal.Length","5" )))
  })

  output$select1<-renderUI({
    element_number<- length(Sel2$x) - 1 
    lapply(1:element_number, function(i) {
      selectInput(inputId=paste0("col",i),paste0("Col ",i),
                choices = names(iris), selected = Sel2$x[i])})}) 

  selectedData <- reactive({
    element_number<- length(Sel2$x) - 1 
    vector <- lapply(1:element_number, function(i) {
      a <- eval(parse(text=paste0("input$col",i)))})
      b <-unlist(strsplit(as.character(vector), ","))
      data <- iris[, b]
  })

  clusters <- reactive({
    kmeans(selectedData(), input$clusters)
  })

  output$plot1 <- renderPlot({
    palette(c("#E41A1C", "#377EB8", "#4DAF4A", "#984EA3",
              "#FF7F00", "#FFFF33", "#A65628", "#F781BF", "#999999"))
    par(mar = c(5.1, 4.1, 0, 1))
    plot(selectedData(),
         col = clusters()$cluster,
         pch = 20, cex = 3)
    points(clusters()$centers, pch = 4, cex = 4, lwd = 4)
  })
}

shinyApp(ui = ui, server = server)

有一个函数可以根据文件中的参数长度自动创建selectInput,该文件被读取(但是长度 - 1,(Sel2$x) - 1,因为最后一个参数是群集号,我找不到简单的解决方案来应对,但如果群集号始终是最后一个参数,那么它应该不是问题):

  output$select1<-renderUI({
    element_number<- length(Sel2$x) - 1 
    lapply(1:element_number, function(i) {
      selectInput(inputId=paste0("col",i),paste0("Col ",i),
                choices = names(iris), selected = Sel2$x[i])})}) 

此外,在创建的小部件的基础上,我能够将数据子集化以供进一步分析:

  selectedData <- reactive({
    element_number<- length(Sel2$x) - 1 
    vector <- lapply(1:element_number, function(i) {
      a <- eval(parse(text=paste0("input$col",i)))})
      b <-unlist(strsplit(as.character(vector), ","))
      data <- iris[, b]
  })