How to make to read vectors with inputs/outputs in shiny?

I´m making a shiny app using lineal regression. I have a problem with inputs/outputs function, so I use SelectInput because I wand to the user can choose de variable to compare. But the trouble is that the input/output don´t take the values what came from a csv file. How can I solve it?

The code is:

datos <- read.csv("C:/Users/jerez/OneDrive/Escritorio/UAL/Datos1.csv", sep=";", header = TRUE, stringsAsFactors = FALSE)

ui <- fluidPage(
  headerPanel("Analisis de Regresion"), 
  sidebarPanel(
    #Eleccion de variable x
    p("Selecciona la primera variable a comparar"),
    selectInput(inputId = "varX", label = "Variable eje X", multiple = FALSE, choices = list("NumBusquedas", "FrecuenciaAsistente", "FrecuenciasCorreos", "NumMensajes", "FreqDiscover", "NumUsosApp", "NumPublicidad","NumSuscripciones","NumBusquedasYoutube")),
    #Eleccion de variable y
    p("Selecciona la segunda variable a comparar"),
    selectInput(inputId = "varY", label = "Variable eje Y", multiple = FALSE, choices = list("NumBusquedas", "FrecuenciaAsistente", "FrecuenciasCorreos", "NumMensajes", "FreqDiscover", "NumUsosApp", "NumPublicidad","NumSuscripciones","NumBusquedasYoutube"))
  ),
  mainPanel(
    #verbatimTextOutput(outputId = "Datos"),
    verbatimTextOutput(outputId = "X"),
    verbatimTextOutput(outputId = "Y"),
    verbatimTextOutput(outputId = "coefCorr"),
    plotOutput(outputId = "Grafico")
    
   
    
  )
)

server <- function(input, output) {
  
  output$coefCorr <- renderPrint(cor(input$varX, input$varY))
  output$Grafico <- renderPlot(ggplot(datos, aes(input$varX, input$varY)))
  output$X <- renderPrint({input$varX})
  output$Y <- renderPrint({input$varY})
  
}
# Run the application 
shinyApp(ui = ui, server = server)

And this is the result: result

Thank you! :)

Upvotes: 0

Views: 267

Answers (1)

r2evans
r2evans

Reputation: 160687

Two problems:

  1. input$* variables are character, not the numbers you think they are. Use datos[[input$*]].

  2. Similarly for ggplot; the preferred programmatic way to specify aesthetics is via .data[[ input$* ]] instead. (I previously suggested that aes_string was preferred, it is deprecated. Thanks to @starja for helping me to see that.)

How to figure this out the next time you get in this bind: insert browser() somewhere towards the beginning of a block that is causing problems. (An alternative is to use a technique I've included on the bottom of this answer.) For now, I'll choose:

  output$coefCorr <- renderPrint({
    browser()
    cor(input$varX, input$var)
  })

(Since I don't have your data, I'll start with datos <- mtcars, and change both select inputs to choices=names(datos).)

When you run that app, it should immediately drop into a debugger on your console, waiting to execute the next line of code (cor(...)). As luck would have it, we're inside a renderPrint which will sink(.) all of the output. While this is by design, we will get zero interaction on the console until we stop the sinking. To do that, sink(NULL) stops it.

sink(NULL)
input$varX
# [1] "mpg"
input$varY
# [1] "mpg"
cor("mpg", "mpg")
# Error in cor("mpg", "mpg") : 'x' must be numeric

Does it make sense to run correlation on two strings? What you likely need is datos[[input$varX]]:

cor(datos[[input$varX]], datos[[input$varY]])
# [1] 1

Of course this is perfect "1", both are the same variable this time. For the sake of demonstration, I'll back out of the debugger, change the Y variable to "disp", then re-enter the debugger:

cor(datos[[input$varX]], datos[[input$varY]])
# [1] -0.8475514

That resolves the numeric error.

Once you get to the point of trying to plot, though, you'll see that you have another problem. (I'm continuing in the current debugger within renderPrint, just because it's convenient.) I'll add geom_point() so that there is something to show.

ggplot(datos, aes(input$varX, input$varY)) + geom_point()

ggplot, single categorical point

That is just a single point. Both axes are categorical variables with the value "mpg" and "disp". In this case, we're up against ggplot2's non-standard evaluation with aes(). Instead, tell ggplot that you're giving it strings, with

ggplot(datos, aes(.data[[ input$varX ]], .data[[ input$varY ]])) + geom_point()

ggplot, fixed

Bottom line, this is what those two server blocks should look like:

  output$coefCorr <- renderPrint({ cor(datos[[input$varX]], datos[[input$varY]]) })
  output$Grafico <- renderPlot(ggplot(datos, aes(.data[[ input$varX ]], .data[[ input$varY ]])) + geom_point())

(I'm still inferring geom_point, though again that's just for demonstration.)


Side note: when learning and developing shiny apps, I often insert a button and observe solely to give me direct access, not within a render block. For instance,

ui <- fluidPage(
  headerPanel("Analisis de Regresion"), 
  sidebarPanel(
    actionButton("debug", "DEBUG!"),
    # ...
  ),
  mainPanel(
    # ...
  )
)
server <- function(input, output) {
  observeEvent(input$debug, { req(input$debug); browser(); 1; })
  # ...
}

When you run into a problem and don't want to stop the shiny app just to insert browser() and re-run it, just press the button.

(This should not be deployed to a shiny server, it is only relevant in local mode. In fact, I believe that attempts to deploy an app with browser() should trigger a warning if not more. Either way, don't try to use the debug button on a remote server :-)

Upvotes: 4

Related Questions