Reputation: 37
I'm publishing a Shiny app for a current project and while it runs with no errors, locally, I get a generic error ('An error has occurred') when it is published to shinyapps.io.
I've tried adjusting plot margins, fiddling with the code and debugging.
library(shiny)
library(markdown)
library(dplyr)
library(lubridate)
library(ggplot2)
pdat <- read.csv("data/all_data.csv")
pdat <- pdat[order(pdat$species),]
pdat$visit_date <- as.Date(pdat$visit_date, format="%d/%m/%Y")
sp.nam <- unique(pdat$species)
pdat2 <- pdat %>% group_by(species) %>% filter(n() > 16) # Only include species with >16 records (power analysis - 0.95 power, 0.01 significance, r = 0.8)
pdat2$visit_date <- as.Date(pdat2$visit_date, format="%d/%m/%Y")
# Dataframe for summary data
pdat3 <- pdat %>% group_by(species) %>% summarize(
Count = length(species),
Male = length(sex[sex == "M"]),
Female = length(sex[sex == "F"]),
Weight_m = round(mean(weight, na.rm=TRUE),1),
Weight_SD = round(sd(weight, na.rm=TRUE),1),
Wing_m = round(mean(wing, na.rm=TRUE),1),
Wing_SD = round(sd(wing, na.rm=TRUE),1),
Max_t_m = round(mean(max_t, na.rm=TRUE),1),
Max_t_SD = round(sd(max_t, na.rm=TRUE),1),
Min_t_m = round(mean(min_t, na.rm=TRUE),1),
Min_t_SD = round(sd(min_t, na.rm=TRUE),1)
)
names(pdat3)[1] <- "Species"
ui <- navbarPage("Passerine biometrics",
tabPanel("Correlation plot",
sidebarLayout(
sidebarPanel(
h4("Subsetted to only include species with more than 16 records."),
selectInput('var', 'Species', unique(pdat2$species),
selected = unique(pdat2$species)[[1]]),
selectInput('xcol', 'X variable', names(pdat2)[c(8:11)],
selected = names(pdat2)[10]),
selectInput('ycol', 'Y variable', names(pdat2)[c(8:11)],
selected = names(pdat2)[11]),
hr(),
helpText("Wing, weight and tarsus measurements for passerine species collected as part of an ongoing study.")
),
mainPanel(
plotOutput('plot1'),
textOutput('count'),
textOutput("correlation")
)
)
),
tabPanel("Resampling",
sidebarLayout(
sidebarPanel(
h4("Variance in tarsus measurements"),
selectInput('sp', 'Species', unique(pdat2$species),
selected = unique(pdat2$species)[[1]]),
actionButton("update", "Update"),
sliderInput(inputId = 'max_grp',
label = "Maximum group size:",
min = 5, max = 250,value = 16),
sliderInput(inputId = 'reps',
label = "Number of iterations:",
min = 1, max = 100, value = 10),
hr(),
helpText("Mean & SD R^2 for a given species, based on minimum and maximum tarsus measurements. Data are randomly resampled-with-replacement, across X individuals ('group size') and Y iterations. Data are cleaned prior to processing - outliers are identified according to Tukey's 1.5*IQR threshold applied to the interaction between minimum and maximum tarsus measurements.")
),
mainPanel(
plotOutput('plot2')
)
)
),
tabPanel("Summary data",
sidebarLayout(
sidebarPanel(
checkboxGroupInput("show_vars", label = "Columns to show:",
choices = names(pdat3), selected = names(pdat3)),
hr(),
helpText("m = mean; SD = standard deviation.")
),
mainPanel(
DT::dataTableOutput("summary")
)
)
),
tabPanel("Raw data",
DT::dataTableOutput("raw")
)
)
server <- function(input, output, session) {
selectedData <- reactive({
a <- subset(pdat2, pdat2$species %in% input$var)
a <- droplevels(a)
a <- a[, c(input$xcol, input$ycol)]
names(a) <- c("x", "y")
a <- a[complete.cases(a), ]
})
selectedData2 <- reactive({
a <- subset(pdat2, pdat2$species %in% input$sp)
a <- droplevels(a)
a$temp <- a$min_t*a$max_t
})
pTResample <- function(df, mi = 1, ma = input$max_grp){
outlierKD <- function(dt, var) {
var_name <- eval(substitute(var),eval(dt))
na1 <- sum(is.na(var_name))
m1 <- mean(var_name, na.rm = T)
outlier <- boxplot.stats(var_name)$out
mo <- mean(outlier)
var_name <- ifelse(var_name %in% outlier, NA, var_name)
na2 <- sum(is.na(var_name))
m2 <- mean(var_name, na.rm = T)
dt[as.character(substitute(var))] <- invisible(var_name)
assign(as.character(as.list(match.call())$dt), dt, envir = .GlobalEnv)
dt <- dt[complete.cases(dt),] # data frame minus outliers
return(invisible(dt))
}
b <- outlierKD(a, temp)
b$temp <- NULL
grpResample <- function(f, v1, v2){
d <- data.frame(groupsize = c(mi:ma), s = NA)
for(i in nrow(d)){
for(i in mi:ma){
a <- f[sample(x = 1:nrow(f), size = i, replace = T), ]
d$s[i] <- cor(a$min_t,a$max_t)^2
}
return(d)
}
}
r <- replicate(input$reps, grpResample(b))
d <- data.frame(t((matrix(unlist(r), nrow=length(r), byrow=T))))
d <- d[,seq(2,ncol(d),2)]
w <- d %>% mutate(avg = apply(.,1,mean),
sd = apply(.,1,sd))
w$groupsize <- c(mi:ma)
w[is.na(w)] <- 0
return(w)
}
selectedData3 <- reactive({
input$update
tmp <- pTResample(selectedData2())
})
output$plot1 <- renderPlot({
par(mar = c(5.1, 4.1, 0, 1))
ggplot(selectedData(), aes(x=x, y=y)) +
stat_smooth(method=lm, fullrange=FALSE) +
geom_point()
})
output$plot2 <- renderPlot({
par(mar = c(5.1, 4.1, 3, 3))
ggplot(selectedData3(), aes(x = groupsize, y = avg)) +
geom_point(size = 2) +
geom_errorbar(aes(ymin = avg-sd, ymax = avg+sd)) +
geom_smooth()
})
output$count <- renderText({
paste("Count (n) = ", count(selectedData()))
})
output$correlation <- renderText({
paste("Correlation (R) = ", round(cor(selectedData()$x,selectedData()$y),2))
})
output$summary <- DT::renderDataTable({
DT::datatable(pdat3[, input$show_vars, drop = FALSE])
})
output$raw <- DT::renderDataTable({
DT::datatable(pdat)
})
}
shinyApp(ui, server)
I expected a plot of avg ~ groupsize, with groupsize variable and dependent on slide inputs, on the second tab, 'Resampling'. Instead, the Main Panel contains the error 'An error has occurred. Check your logs or contact the app author for clarification.'
Update [08/08/19 16:12]
Following Kelly's advice, I re-named the t
argument and that seemed to help. But when I cleared the environment, I still ran into issues. Loading things piece-by-piece on my local machine, it looks as though there's an issue between selectedData2 and selectedData3. If I manually load the data frame a
then it works. If the environment is clear then I get a closure error.
I've updated the code, above, following my edits.
Latest log:
2019-08-08T15:18:43.544466+00:00 shinyapps[631266]: Warning: Error in eval: invalid 'envir' argument of type 'closure'
2019-08-08T15:18:43.554480+00:00 shinyapps[631266]: 199: outlierKD [/srv/connect/apps/exploration_app/app.R#112]
2019-08-08T15:18:43.554481+00:00 shinyapps[631266]: 198: pTResample [/srv/connect/apps/exploration_app/app.R#125]
2019-08-08T15:18:43.554482+00:00 shinyapps[631266]: 197: <reactive:selectedData3> [/srv/connect/apps/exploration_app/app.R#148]
2019-08-08T15:18:43.554478+00:00 shinyapps[631266]: 200: eval
2019-08-08T15:18:43.554483+00:00 shinyapps[631266]: 195: .func
2019-08-08T15:18:43.554484+00:00 shinyapps[631266]: 192: contextFunc
2019-08-08T15:18:43.554485+00:00 shinyapps[631266]: 191: env$runWith
2019-08-08T15:18:43.554485+00:00 shinyapps[631266]: 184: ctx$run
2019-08-08T15:18:43.554486+00:00 shinyapps[631266]: 183: self$.updateValue
2019-08-08T15:18:43.554489+00:00 shinyapps[631266]: 137: drawPlot
2019-08-08T15:18:43.554487+00:00 shinyapps[631266]: 181: selectedData3
2019-08-08T15:18:43.554488+00:00 shinyapps[631266]: 179: renderPlot [/srv/connect/apps/exploration_app/app.R#161]
2019-08-08T15:18:43.554489+00:00 shinyapps[631266]: 177: func
2019-08-08T15:18:43.554490+00:00 shinyapps[631266]: 123: <reactive:plotObj>
2019-08-08T15:18:43.554491+00:00 shinyapps[631266]: 107: drawReactive
2019-08-08T15:18:43.554518+00:00 shinyapps[631266]: 94: origRenderFunc
2019-08-08T15:18:43.554519+00:00 shinyapps[631266]: 93: output$plot2
2019-08-08T15:18:43.554521+00:00 shinyapps[631266]: 13: runApp
2019-08-08T15:18:43.554522+00:00 shinyapps[631266]: 12: fn
2019-08-08T15:18:43.554522+00:00 shinyapps[631266]: 7: connect$retry
2019-08-08T15:18:43.554523+00:00 shinyapps[631266]: 6: eval
2019-08-08T15:18:43.554524+00:00 shinyapps[631266]: 5: eval
Upvotes: 0
Views: 95
Reputation: 26
I think the issue is happening here:
var_name <- eval(substitute(var),eval(dt))
The second argument of "eval" should be an environment. You call the parent function here:
b <- outlierKD(a, t)
I don't see t
defined anywhere, so presumably it's trying to use the transpose function t()
instead.
Hence the error from your logs:
Warning: Error in eval: invalid 'envir' argument of type 'closure'
The second argument to eval()
was t()
, which is a function (or closure).
(This is one of the reasons that style guides typically suggest not using short variable names - they clash with functions and lead to confusing errors about "closures"!)
On your home computer, you probably had t
defined properly in your environment from previous testing, so it didn't throw an error then.
Upvotes: 1