1
votes

I am trying to create a UI which will let the user change non numeric inputs (they are all limits such as < 3), and then be able to do some further analysis on the new vector. Say for example they have a vector X = (1, 2, 3, <1, 5, 3). I would like to have a numeric input called '<3', and whatever value is entered is what it is replaced with.

I am able to create an input for each non numeric input, however it has the title I want, and div form-group shiny-input-container.

When I add the part to overwrite a copy of the original data it does not compile, and I get the error message: Warning: Error in subset.default: argument "subset" is missing, with no default

So far the best I can do is:

l <- c(1,2,3,4,5,7, '<1', 4,5, 7, '<3') # Example input

library(shiny)

ui <- fluidPage(

   titlePanel("Plot non numeric Data"),

   sidebarLayout(
      sidebarPanel(
         uiOutput("LowerLimits")
      ),

      mainPanel(
         plotOutput("distPlot")
      )
   )
)

server <- function(input, output) {

  l2 = l

  data <- reactiveValues(nonN = factor(l[which(is.na(suppressWarnings(as.numeric(l))))]) )

  # Bad bit of code
  output$LowerLimits <- renderUI({
    LL <- list()
    if(length(data$nonN) > 0){
      for(i in 1:length(data$nonN)){
        assign(paste("Test", levels(data$nonN)[i]),numericInput(levels(data$nonN)[i],paste("Test", levels(data$nonN)[i]), value = NULL) )
        LL <- c(LL, get(paste("Test", levels(data$nonN)[i])))
      }
    }
    LL
  })

  # Really bad bit of code that crashes the app
  observe({
    if(length(data$nonN) > 0){
      for(i in 1:length(data$nonN)){
        l2[which(is.na(suppressWarnings(as.numeric(l))))][i] = subset(x = input, select = levels(data$nonN)[i])
      }
    }
  })



   output$distPlot <- renderPlot({
      plot(l2)
   })
}

# Run the application 
shinyApp(ui = ui, server = server)


Is there any way to 1) Not have the *div form-group ...` part in the input 2) Be able to change my data

The example input on the first line is just that, an example. It can have any length, and any number of numeric or non numeric values.

Thanks in advance.

1

1 Answers

1
votes

So, it turns out this can be done using lapply and reactiveValuesToList, as shown below. unique also needed to be added in a number of spaces with the nonN argument as duplicated non numeric inputs are also possible (which I forgot to mention, but was an easy fix). The final code for this is:

l <- c(1,2,3,4,5,7, '<1', 4,5, 7, '<3', '<3')

library(shiny)
test = NULL

ui <- fluidPage(

  titlePanel("Plot non numeric Data"),

  sidebarLayout(
    sidebarPanel(
      uiOutput("LowerLimits")
    ),

    mainPanel(
      plotOutput("distPlot")
    )
  )
)

server <- function(input, output) {

  l2 = l
  data <- reactiveValues(nonN = factor(l[which(is.na(suppressWarnings(as.numeric(l))))]) )

  # Bad bit of code
  output$LowerLimits <- renderUI({
    if(length(unique(data$nonN)) > 0){
      lapply(1:length(unique(data$nonN)), function(i){
        numericInput(levels(data$nonN)[i],paste("Test", levels(data$nonN)[i]), value = NULL)
      })
    }
  })

  # Really bad bit of code

  output$distPlot <- renderPlot({
    if(length(data$nonN) > 0){
      for(i in 1:length(unique(data$nonN))){
        l2[l2 == levels(unique(data$nonN))[i]] = subset(as.matrix(t(reactiveValuesToList(input))), select = levels(unique(data$nonN))[i])
      }
    }
    plot(as.numeric(l2))
  })
}

# Run the application 
shinyApp(ui = ui, server = server)