Stanley Yu
Stanley Yu

Reputation: 109

Unable to resolve R Shiny error, "'x' and 'units' must have length > 0" when attempting to render a (ggplot) density plot

I'm prototyping a dashboard (R Shiny) to create density plots that can be customized to graph BMI of Hernia patients by different categories, namely Gender, Race, Ethnicity, and Smoker. The categories Gender, Ethnicity, and Smoker all seem to be working perfectly fine, however attempting to plot BMI by Race fails when I run the app and use the drop down menus to select the category 'Race'. Instead, I receive the message, "Error: 'x' and 'units' must have length > 0", which is mystifying. Other posts with the similar error message on Stack Overflow suggest coercing the racial categories to lower case, which I attempted (i.e., df$Race = tolower(df$Race), but that didn't seem to help.

Categories of Race include:

Of these, it appears that our data includes only 1 patient who identifies as 'American Indian or Alaska Native'.

Below you will find the code I've written for 'app.R', and the code I use to plot the data.

First, app.R:

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(DBI)
library(dplyr)
library(DT)
library(tibble)

source("connect.R")
source("density.R")

con = connect()
myquery = as_tibble(dbGetQuery(con,
    "SELECT 
        pat.lngPatientID PatID, 
        pat.lngMRN MRN, 
        pat.strFirstName FirstName, 
        pat.strLastName LastName, 
        pat.dteBirth DOB, 
        pat.lngHeight Height, 
        pat.lngWeight Weight, 
        pat.lngBMI BMI, 
        tpg.strValue Gender,
        tpr.strValue Race,
        eth.strValue Ethnicity, 
        tss.strValue Smoker
    FROM tblPatient pat 
        LEFT JOIN tlkpGender tpg 
            ON pat.lngGender = tpg.lngValue 
        LEFT JOIN tlkpRace tpr 
            ON pat.lngRace = tpr.lngValue 
        LEFT JOIN tlkpEthnicity eth
            ON pat.lngEthnicity = eth.lngValue 
        LEFT JOIN tlkpSmokingStatus tss 
            ON pat.strSmokingStatus = tss.lngValue "
    )
)

df = na.omit(myquery)

# Define UI 
ui <- fluidPage(
    titlePanel("BMI of Hernia Patients"),
    
    sidebarLayout(
        sidebarPanel(
            helpText("Create BMI density plots from the HHC Hernia Database."),
            
            selectInput("variable", 
                        label = "Choose a variable to display",
                        choices = list("BMI"),
                        selected = "BMI"),
            
            selectInput("category", 
                        label = "Choose a category to graph BMI by",
                        choices = list("Gender",
                                       "Race",
                                       "Ethnicity",
                                       "Smoker"),
                        selected = "None"),
        
            sliderInput("range", 
                        label = "Display Range:",
                        min = 0, max = 100, value = c(0, 65))
        ),
    
        mainPanel(
            # DT::dataTableOutput("mytable"),
            plotOutput("dense_plot")
            
        )
    )
)

# Define server logic
server <- function(input, output) {
    #output$mytable = DT::renderDataTable({myquery})
    
    output$dense_plot = renderPlot({
        var = switch(input$variable, 
                     "BMI" = df$BMI)
        cat = switch(input$category,
                     "Gender" = df$Gender,
                     "Race" = df$Race,
                     "Ethnicity" = df$Ethnicity,
                     "Smoker" = df$Smoker)
        density_plots(dataset = df, 
                      variable = var, 
                      category = cat, 
                      x_label = "BMI", 
                      title_card = "Distribution of BMI", 
                      lower = input$range[1], 
                      upper = input$range[2])
    })
}

# Run the app 
shinyApp(ui = ui, server = server)

Next, we've density.R, which contains two functions density_plot() which creates a single density plot for BMI of all patients, and density_plots() which creates a density plot of BMI by a specific category. This second function is what I'm calling in app.R

library(ggplot2)

density_plot <- function(dataset, variable, rm_na = TRUE, border_color = "darkgoldenrod4", fill_color = "dodgerblue4", transparency = 0.25, lower = 0, upper = 65,
                         title_card = "", x_label = "") {
  # plots a single density plot.  Defaults are set to appropriate values for Hernia BMI.
  ggplot(data = dataset) + 
    geom_density(mapping = aes(x = variable), na.rm = rm_na, color = border_color, fill = fill_color, alpha = transparency) + 
    scale_x_continuous(limits = c(lower, upper)) + 
    coord_cartesian(xlim = c(lower, upper)) +
    labs(x = x_label, title = title_card)
}

density_plots <- function(dataset, variable, category, rm_na = TRUE, transparency = 0.25, lower = 0, upper = 65, title_card = "", x_label = "") {
  ggplot(data = dataset) + 
    geom_density(mapping = aes(x = variable, color = category, fill = category), na.rm = rm_na, alpha = transparency) + 
    scale_x_continuous(limits = c(lower, upper)) + 
    coord_cartesian(xlim = c(lower, upper)) +
    labs(x = x_label, title = title_card)
}

Upvotes: 0

Views: 166

Answers (1)

mnist
mnist

Reputation: 6954

Its hard to debug this since its not reproducible but you can try this:

  # Define server logic
  server <- function(input, output) {
    #output$mytable = DT::renderDataTable({myquery})

    output$dense_plot = renderPlot({
      density_plots(dataset = df,
                    variable = input$variable,
                    category = input$category,
                    x_label = "BMI",
                    title_card = "Distribution of BMI",
                    lower = input$range[1],
                    upper = input$range[2])
    })
  }
  
  
  density_plots <- function(dataset, 
                            variable, 
                            category, 
                            rm_na = TRUE, 
                            transparency = 0.25, 
                            lower = 0, upper = 65, 
                            title_card = "", x_label = "") {
    ggplot(data = dataset) + 
      geom_density(mapping = aes_string(x = variable, color = category, fill = category),
                   na.rm = rm_na, alpha = transparency) + 
      scale_x_continuous(limits = c(lower, upper)) + 
      coord_cartesian(xlim = c(lower, upper)) +
      labs(x = x_label, title = title_card)
  }

Upvotes: 0

Related Questions