Shiny issues can be challenging to resolve relative to other problems with your code or statistical methods. Shiny apps are often large, complex projects with interacting files.
When seeking help from others it is considered polite to:
- First, do your best to work through RStudio's debugging tools to diagnose your issue on your own. Often those shiny logs and tracebacks are useful to others trying to help out.
- Second, strive to minimize the effort required to replicate your issue. You can do this with a reproducible example ("reprex").
Shiny Debugging
Errors in Shiny code can be difficult to track down. If you don't know where your problem is coming from, you can track it down with some of the techniques here:
Add browser()
in strategic places. When R executes browser()
, it will stop the application and let you run commands at the console to poke around and inspect values. For example, here is a browser()
call inserted at the top of some plotting code:
output$plot <- renderPlot({
browser()
n <- input$n * 2
plot(head(cars, n))
})
When R reaches the browser()
, it will pause execution of the application and show you this at the console:
Called from: top level
Browse[1]>
You can inspect variables (like input$n
), modify variables, and step through the code. When R is at the debug prompt, it supports the following special commands:
- Type
n
then Enter: this runs the next line of code. - Type
c
then Enter: this continues normal execution and exits the debugger prompt. - Type
s
then Enter: this steps into the a function.
For more information about debugging R in general, see this chapter in Hadley Wickham's Advanced R book.
Also see the article on Debugging Shiny applications if you want to learn more about debugging Shiny applications in particular.
Creating Shiny reprexes
If you need to ask for help, you are much more likely to get help if you have a minimal reproducible example ("reprex") which other people can copy and paste to see the same problem. When the code is minimal, it makes it easy for others to see where the problem is. And if the problem can be reproduced by copying and pasting, it makes it much easier for others to debug the problem.
Here is an example of a reprex. If you copy and paste the code in an R console, the application will show an error: non-numeric argument to binary operator
.
shinyApp(
ui = fluidPage(
selectInput("n", "N", 1:10),
plotOutput("plot")
),
server = function(input, output, session) {
output$plot <- renderPlot({
n <- input$n * 2
plot(head(cars, n))
})
}
)
Because anyone can reproduce the problem by just copying and pasting the code, they can easily explore your code and test possible solutions.
How do I create a reprex from my application?
If you don't know what part of your code is triggering the problem, a good way to find it is to remove sections of code from your application, piece by piece, until the problem goes away. If removing a particular piece of code makes the problem stop, it's likely that that code is related to the problem. Once you've isolated the code that triggers the problem, you can go on to the next step.
To create a minimal example, you can go one of two ways: you can either keep removing code from your application until all the extraneous parts are gone, or you can construct a new Shiny application and copy the problem code into the new application. It's generally easier for others to understand the problem when you construct a new example, although either way is much better than not having a reproducible example at all.
If you want to construct a minimal example from scratch, you can start with this template of very basic application, which you can always find by running ?shinyApp
(that shows the documentation for the function).
shinyApp(
ui = fluidPage(
numericInput("n", "n", 1),
plotOutput("plot")
),
server = function(input, output, session) {
output$plot <- renderPlot( plot(head(cars, input$n)) )
}
)
Start with the template and modify it by adding code that reproduces your problem. In many cases, the act of creating a reproducible example will reveal to you the cause of the problem, before you even ask for help.
Dealing with data
If your reproducible example uses a data set that is stored on your computer, it will be difficult for others to reproduce the problem, because they won't be able to just copy and paste your code; they'll have to download the data, run R in the correct directory, and so on.
You can make it easier for others by providing a data set in a way that can be copied and pasted. This can be either your original data set, or a simplified version of it that still causes the issue. For example, if you have a data frame with 1,000 rows, you might try to take the first 20 rows and see if that will still cause the problem. In general it is best to provide a simplified version of the data set, so that it is easy for others to understand it.
Option 1: Provide regular R code that generates a data set. For example:
mydata <- data.frame(x = 1:5, y = c("a", "b", "c", "d", "e"))
Option 2: Use dput()
. If you have an object x
, calling dput(x)
will print out code that will generate an object just like x
. For example, if you use dput(mydata)
, it will print the following:
> dput(mydata)
structure(list(x = 1:5, y = structure(1:5, .Label = c("a", "b",
"c", "d", "e"), class = "factor")), class = "data.frame", row.names = c(NA,
-5L))
If you run the structure(list(....))
code, it will return a data frame exactly like mydata
. Once you have that code, you can put this in your application to generate mydata
:
mydata <- structure(list(x = 1:5, y = structure(1:5, .Label = c("a", "b",
"c", "d", "e"), class = "factor")), class = "data.frame", row.names = c(NA,
-5L))
If dput()
on your original data generates too much code, try taking a subset of your data and see if it will reproduce the problem.
Please bear in mind that dput()
is not perfect, and cannot faithfully reproduce every kind of R object. It will, however, work for most objects, like data frames and vectors.
Option 3: If your data set can't be put in your code in a way that can be copied and pasted, you might have to just upload it so that others can download it. It is best to avoid this if possible.
Personal and Private Information
Users should not share personal or protected information in topic threads or reprex data.
What if you need to share contact info or an ip, or discuss data for a reprex related to a protected dataset? What if you see a violation of this policy? Check out Personally Identifiable & Protected Information Guide guide and our Privacy Policy