0
votes

In the app.R file below, I'm trying to create a selectInput() box for each column name of the iris dataset. However, I am not sure what must go in place of the ellipsis selectInput(..., 'Sepal.Length', c(0, 1)), in order to make it work, and I also don't like that I had to type out the name of the column itself. Of course, I could have done something like selectInput(..., 'names(iris)[1]', c(0, 1)), instead, but I'm looking to create something even more automated and streamlined (i.e., writing out selectInput(..., 'column name', c(0, 1)), five times for each of the five columns seems grossly inefficient). In other words, perhaps I could make Shiny automatically recognize that the iris dataset has 5 columns by default, which would create the five selectInput() boxes appropriately?

The whole reason why I'm trying to accomplish this is because I would like to create a simple automated character vector (shown in the code below as vec <- c(1,1,0,0,1) #corresponding to c(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)), which automatically updates depending on whether I choose 0 or 1 in the respective selectInput() boxes discussed above.

Complete code (with critical sections marked with a hashtag):

  palette(c("#E41A1C", "#377EB8", "#4DAF4A", "#984EA3",
  "#FF7F00", "#FFFF33", "#A65628", "#F781BF", "#999999"))

server <- shinyServer(function(input, output, session) {

  # Combine the selected variables into a new data frame
  selectedData <- reactive({
    iris[, c(input$xcol, input$ycol)]
  })

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

  output$plot1 <- renderPlot({
    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)
  })

  #vec <- c(1,1,0,0,1)  #corresponding to c(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)

})


ui <- shinyUI(pageWithSidebar(
  headerPanel('Iris k-means clustering'),
  sidebarPanel(
    selectInput('xcol', 'X Variable', names(iris)),
    selectInput('ycol', 'Y Variable', names(iris),
                selected=names(iris)[[2]]),
    #selectInput(..., 'Sepal.Length', c(0, 1)),
    #selectInput(..., 'Sepal.Width', c(0, 1)),
    #selectInput(..., 'Petal.Length', c(0, 1)),
    #selectInput(..., 'Petal.Width', c(0, 1)),
    #selectInput(..., 'Species', c(0, 1)),
    numericInput('clusters', 'Cluster count', 3,
                 min = 1, max = 9)
  ),
  mainPanel(
    plotOutput('plot1')
  )
))


# Return a Shiny app object
shinyApp(ui = ui, server = server)
2
You can use renderUI on the UI side and then generate the selectInput on the server side. Actually, using it as follows is going to work: selectInput('columnName', 'Column Name', names(iris)). Is there a reason you are trying to create a individual drop down for each of the column names?Gopala
I'm trying to create a individual drop down for each of the column names so that I can feed the character vector vec <- c(1,1,0,0,1) (i.e., so I can make it c(0,0,1,0,1) or c(1,0,0,0,0) or whatever, based on what I select in the drop down menu)warship
If you're trying to make it so that certain columns can be selected, why not do one selectInput with multiple = TRUE and then set vec based on the choices selected?tblznbits
@brittenb Could you please demonstrate as answer? This sounds very promising.warship
If you want to be able to select multiple values simultaneously, I suggest using 'checkboxGroupInput' as it is the more appropriate UI element. Yes, multiple = TRUE in selectInput will allow that as well, but that is not a proper choice in my view for this use case.Gopala

2 Answers

1
votes

Here is the use of checkboxGroupInput:

ui <- shinyUI(pageWithSidebar(
  headerPanel('Iris k-means clustering'),
  sidebarPanel(
    selectInput('xcol', 'X Variable', names(iris)),
    selectInput('ycol', 'Y Variable', names(iris),
                selected=names(iris)[[2]]),
    checkboxGroupInput('columnNames', 'Column Name', names(iris)),
    numericInput('clusters', 'Cluster count', 3,
                 min = 1, max = 9)
  ),
  mainPanel(
    plotOutput('plot1')
  )
))

To retrieve the column names selected (1) and not selected (0), you can use the following options on the server side:

> s <- c('Sepal.Length', 'Sepal.Width', 'Petal.Width') # Example vector from checkbox group input
> names(iris) %in% s
[1]  TRUE  TRUE FALSE  TRUE FALSE
> as.integer(names(iris) %in% s)
[1] 1 1 0 1 0
> which(names(iris) %in% s) # Provides vector indices set to 1
[1] 1 2 4
> which(!names(iris) %in% s) # Provides vector indices set to 0
[1] 3 5
> 
1
votes

You could just use the multiple = TRUE value on the selectInput to allow for multiple columns to be selected. Then on your server side, you would just set vec <- as.numeric(names(iris) %in% input$iris_columns) where input$iris_columns refers to your selectInput element.

As an example:

ui <- shinyUI(pageWithSidebar(
  headerPanel('Iris k-means clustering'),
  sidebarPanel(
    selectInput('xcol', 'X Variable', names(iris)),
    selectInput('ycol', 'Y Variable', names(iris), selected=names(iris)[[2]]),
    selectInput('iris_columns', 'Select Columns', choices = names(iris), multiple = TRUE),
    numericInput('clusters', 'Cluster count', 3, min = 1, max = 9)
  ),
  mainPanel(
    plotOutput('plot1')
  )
))

server <- shinyServer(function(input, output, session) {

  # Combine the selected variables into a new data frame
  selectedData <- reactive({
    iris[, c(input$xcol, input$ycol)]
  })

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

  output$plot1 <- renderPlot({
    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)
  })

  vec <- as.numeric(names(iris) %in% input$iris_columns)
})