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! :)
Two problems:
input$*
variables are character
, not the numbers you think they are. Use datos[[input$*]]
.
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 sink
ing. 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 cor
relation 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()
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()
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 :-)