Shiny Deployment Error

Hello,

I'm trying to deploy my shiny app to shinyapps.io.
I am getting the following error, even though it seems to have deployed successfully.


I do not have any install.packages() call in my code. Another solution suggested by someone was to replace library() with require(). I did that and it still doesn't work.

This is my code:

# require(shiny)
require(shinyWidgets)
require(tidyr)
require(dplyr)
require(plotly)
require(mice)
require(DT)
options(scipen=999)

#-----------------------------------Data loading-----------------------------------
df <- read.csv("Housing_2020.csv")

#-----------------------------------Data cleaning and imputation-----------------------------------
df <- df[which(df$PROPERTY.TYPE == "Single Family Residential" | df$PROPERTY.TYPE == "Townhouse"), ]
mls <- c(14406995, 14414435, 14413706, 14414215, 14413861, 14410893, 14412244, 14410475, 14410950, 14409960, 14406098, 14409280, 14408549, 14409060, 14405753, 14404015, 14398327, 14402565, 14401776, 14401073, 14397227, 14398604, 14398183, 14397920, 14397210, 14396748, 14392264, 14376755, 14390655, 14390228, 14388336, 14389579, 14386430, 14386913, 14383999, 14385197, 14383280, 14380650, 14379630, 14360085, 14376802, 14375232, 14375867, 14334377, 61484, 61155, 14375675)
ls <- c(1559, 5983, 7667, 9705, 7344, 3099, 7658, 9026, 1680, 6721, 1202, 5001, 7500, 6111, 15246, 6775, 8089, 10498, 8015, 17860, 9579, 2914, 9583, 7491, 1891, 4530, 9772, 10001, 9418, 13068, 2439, 8206, 1620, 5022, 13068, 2239, 2605, 9592, 21780, 13068, 10402, 9757, 7479, 4295, 1786, 7187, 3429)
for(i in seq(1,length(mls))){
  df[df$MLS. == mls[i], ]$LOT.SIZE <- ls[i]
}
df[df$MLS. == 14384584, ]$BATHS <- 3
df[df$MLS. == 61484, ]$YEAR.BUILT <- 2006
df[df$MLS. == 61155, ]$YEAR.BUILT <- 1998

#-----------------------------------MICE-----------------------------------
# Application loading take a little longer as imputation needs to be performed.
df1 <- df %>% select(BEDS, BATHS, SQUARE.FEET, LOT.SIZE, YEAR.BUILT, PRICE)
my_imp <- mice(df1, method = c("","","","rf","",""), seed = 0, printFlag = TRUE) #Imputation performed on LOT.SIZE column
df1 <- complete(my_imp)

#-----------------------------------APP-----------------------------------
ui <- fluidPage(
  tabsetPanel(
    tabPanel("Tab 1",
             titlePanel("Histogram of Price by ZIP Code"),
             sidebarLayout(
               sidebarPanel(selectInput(inputId = "zip", label = "Select ZIP Code", c(Choose = "", df$ZIP.OR.POSTAL.CODE) , selected = 75080, multiple = TRUE)),
               mainPanel(plotOutput(outputId = "histogram"), textOutput(outputId = "text"))
             )),
    tabPanel("Tab 2",
             titlePanel("Median Property Prices by ZIP Code"),
             dataTableOutput("mytable")),
    tabPanel("Tab 3",
             titlePanel("Boxplot of Prices"),
             sidebarLayout(
               sidebarPanel(
                 sliderTextInput(inputId = "beds", 
                                 label = "Beds:", 
                                 choices = sort(unique(df$BEDS, na.rm = TRUE)),
                                 grid = TRUE,
                                 selected = c(min(sort(unique(df$BEDS, na.rm = TRUE))),max(sort(unique(df$BEDS, na.rm = TRUE))))),
                 sliderTextInput(inputId = "baths", 
                                 label = "Baths:", 
                                 choices = sort(unique(df$BATHS, na.rm = TRUE)),
                                 grid = TRUE,
                                 selected = c(min(sort(unique(df$BATHS, na.rm = TRUE))),max(sort(unique(df$BATHS, na.rm = TRUE))))),
                 sliderTextInput(inputId = "squarefeet", 
                                 label = "Square Feet:", 
                                 choices = sort(unique(df$SQUARE.FEET, na.rm = TRUE)),
                                 grid = TRUE,
                                 selected = c(min(sort(unique(df$SQUARE.FEET, na.rm = TRUE))),max(sort(unique(df$SQUARE.FEET, na.rm = TRUE))))),
                 sliderTextInput(inputId = "lotsize", 
                                 label = "Lot Size:", 
                                 choices = sort(unique(df$LOT.SIZE, na.rm = TRUE)),
                                 grid = TRUE,
                                 selected = c(min(sort(unique(df$LOT.SIZE, na.rm = TRUE))),max(sort(unique(df$LOT.SIZE, na.rm = TRUE))))),
                 sliderTextInput(inputId = "yearbuilt", 
                                 label = "Year Built:", 
                                 choices = sort(unique(df$YEAR.BUILT, na.rm = TRUE)),
                                 grid = TRUE,
                                 selected = c(min(sort(unique(df$YEAR.BUILT, na.rm = TRUE))),max(sort(unique(df$YEAR.BUILT, na.rm = TRUE)))))
               ),
               mainPanel(
                 plotlyOutput(outputId = "boxplot"),
                 br(),
                 textOutput(outputId = "text1"),
                 textOutput(outputId = "text2"),
               )
             )
             
    ),
    tabPanel("Tab 4",
             plotlyOutput(outputId = "map", height = '900px'))
  )
)
server <- function(input, output){
  #TAB 1
  # If the input field is empty, histogram for all the prices is displayed. Otherwise, histogram is displayed only for selected zip code(s).
  # Bin width taken as $50,000.
  # Default zip code is 75080.
  output$text <- renderText("Dashed blue line indicates median")
  output$histogram <- renderPlot(if (is.null(input$zip)){
    ggplot(df, aes(x=PRICE)) + geom_histogram(binwidth = 50000, color = "darkblue", fill = "lightblue") + 
      theme_classic() + 
      labs(title="Histogram Plot",x="Price($)", y = "Count") + 
      geom_vline(aes(xintercept=median(PRICE)),color="blue", linetype="dashed", size=1)
  } else{
    ggplot(df[df$ZIP.OR.POSTAL.CODE == input$zip, ], aes(x=PRICE)) + 
      geom_histogram(binwidth = 50000, color = "darkblue", fill = "lightblue") + 
      theme_classic() + 
      labs(title="Histogram Plot",x="Price($)", y = "Count") + 
      geom_vline(aes(xintercept=median(PRICE)),color="blue", linetype="dashed", size=1)
  })
  #TAB 2
  # Pivot table created using pivot_wider(). Median price has been used to populate each cell (values_fn).
  widedf <- pivot_wider(df, id_cols = c(ZIP.OR.POSTAL.CODE), names_from = PROPERTY.TYPE, values_from = PRICE, values_fn = median)
  widedf <- widedf[order(-widedf$`Single Family Residential`),]
  names(widedf) <- c("ZIP", "Single Family Residential", "Townhouse")
  output$mytable = renderDataTable(datatable(widedf) %>% formatCurrency(2:3,'$'))
  #TAB 3
  # Plotly's boxplot has been used as it provides interactive features like zooming in.
  output$text1 <- renderText(
    paste("Beds:", paste(input$beds, collapse = "-"), ", Baths:", paste(input$baths, collapse = "-"), ", Square Feet:", paste(input$squarefeet, collapse = "-"), ", Lot Size:", paste(input$lotsize, collapse = "-"), ", Year Built:", paste(input$yearbuilt, collapse = "-"))
  ) # Displays the selected ranges for each variable
  output$text2 <- renderText("Values selected in the range slider are inclusive.")
  
  output$boxplot <- renderPlotly(
    plot_ly(x = "", y = df1[df1$BEDS >= input$beds[1] & df1$BEDS <= input$beds[2] & df1$BATHS >= input$baths[1] & df1$BATHS <= input$baths[2] & df1$SQUARE.FEET >= input$squarefeet[1] & df1$SQUARE.FEET <= input$squarefeet[2] & df1$LOT.SIZE >= input$lotsize[1] & df1$LOT.SIZE <= input$lotsize[2] & df1$YEAR.BUILT >= input$yearbuilt[1] & df1$YEAR.BUILT <= input$yearbuilt[2], ]$PRICE, type = "box", jitter = 0.9)
    %>% layout(yaxis = list(title = "PRICE ($)"))
  )
  #TAB 4
  # Leaflet used, however, map rendering times were too long and application would crash. Plotly renders all the ~4000 points smoothly.
  Sys.setenv('MAPBOX_TOKEN' = NA) # Token needed for certain vector maps
  fig <- df %>% plot_mapbox(lat = ~LATITUDE, 
                            lon = ~LONGITUDE,
                            split = ~PROPERTY.TYPE,
                            size=2,
                            mode = 'scattermapbox', 
                            hoverinfo='text',
                            hovertext = paste("<b>Price($):</b>", df$PRICE, "<br>", "<b>Property Type:</b>", df$PROPERTY.TYPE, "<br>", "<b>Square Feet:</b>", df$SQUARE.FEET, "<br>", "<b>Beds:</b>", df$BEDS, "<br>", "<b>Baths:</b>", df$BATHS, "<br>", "<b>MLS#:</b>", df$MLS., "<br>", "<b>City:</b>", df$CITY)
  ) 
  fig <- fig %>% layout(title = 'Housing Map',
                        font = list(color='white'),
                        plot_bgcolor = '#191A1A', 
                        paper_bgcolor = '#000000',
                        mapbox = list(style = "open-street-map", 
                                      zoom = 8.5, 
                                      center = list(lat = ~mean(LATITUDE), lon = ~mean(LONGITUDE))),
                        legend = list(orientation = 'v',
                                      font = list(size = 12)),
                        margin = list(l = 30, r = 30,
                                      b = 30, t = 30,
                                      pad = 2))
  output$map <- renderPlotly(fig)
}
shinyApp(ui = ui, server = server)

Dataset

I always recommend starting simple and building up to complicated.
So, can you deploy the following mini app:

# require(shiny)
require(shinyWidgets)
require(tidyr)
require(dplyr)
require(plotly)
require(mice)
require(DT)


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

shinyApp(ui="HelloWorld", server)

I followed your advise and identified the problem.

my_imp <- mice(df1, method = c("","","","rf","",""), seed = 0, printFlag = TRUE) #Imputation performed on LOT.SIZE column

The above line is causing the application to crash after being deployed. If I remove the following two lines, my application runs on the website. How do I resolve this issue? - I mean I want mice imputation to be done before my app is loaded.

my_imp <- mice(df1, method = c("","","","rf","",""), seed = 0, printFlag = TRUE) #Imputation performed on LOT.SIZE column
df1 <- complete(my_imp)

try this app?

# require(shiny)
require(shinyWidgets)
require(tidyr)
require(dplyr)
require(plotly)
require(mice)
require(DT)

ui <- fluidPage(DT::dataTableOutput("show_premice"),
                DT::dataTableOutput("show_postmice"))
                
server <- function(input, output, session) {

  
  output$show_premice <- renderDT(nhanes)
  output$show_postmice <- renderDT(mice(nhanes, method = c("","rf","rf","rf"), 
                                        seed = 0, printFlag = FALSE) %>% complete())
}

shinyApp(ui=ui, server)

show_premice gets displayed but show_postmice doesn't. I finally checked the logs and realized that mice requires randomForest package to run. However, I did not explicitly load that package. Adding library(randomForest) solved this problem.

The same fix works for my original app as well.

Thank you for your time.

1 Like