Search code examples
rggplot2shinyconvex-hull

ggplot visual of convex hull - shiny


I want to create a ggplot visual of convex hull for any numeric variables the user provides while allowing the hull to split into several hulls for a chosen categorical input variable.

Something like this in shiny where users can pick as many x variables as they want

library(datasets)
library(ggplot2)
library(ggpubr)

df<- iris
str(df)

b <- ggplot(df, aes(x = Sepal.Length+Sepal.Width, y = Petal.Width))
 
# Convex hull of groups
b + geom_point(aes(color = Species, shape = Species)) +
  stat_chull(aes(color = Species, fill = Species), 
             alpha = 0.1, geom = "polygon") +
  scale_color_manual(values = c("#00AFBB", "#E7B800", "#FC4E07")) +
  scale_fill_manual(values = c("#00AFBB", "#E7B800", "#FC4E07"))

Here is my shiny code so far, which, needless to say does not work.Any help will be greatly appreciated

library(shiny)
library(dplyr)
library(ggplot2)
library(ggpubr)
df<- mtcars
numeric_cols <- df %>% select(where(is.numeric))
categorical_cols <- df %>% select(where(is.factor))
ui <- fluidPage(
  titlePanel("MTCARS"),
  selectInput("Columns","Numeric Columns",
              names(numeric_cols), multiple = TRUE),
  selectInput("Columns","Categorical Columns",
              names(categorical_cols), multiple = TRUE),
  plotOutput("myplot")
)

server <- function(input, output) {
  Dataframe2 <- reactive({
    mtcars[,input$Columns] 
  })
  
  my_plot<- reactive({ggplot(Dataframe2(), aes(mpg, cyl))+geom_point()})
  output$myplot <- renderPlot({
    my_plot()
  })
}

shinyApp(ui, server)

Solution

  • You have 3 issues here. First, you have zero categorical variables in mtcars. Second, you should use unique IDs, but you are using same IDs for both selectInputs. Lastly, for the plot you need to use the selected columns, and not specify mpg and cyl. Try this

    library(shiny)
    library(dplyr)
    library(ggplot2)
    library(ggpubr)
    df<- mtcars
    numeric_cols <- df %>% dplyr::select(where(is.numeric))
    categorical_cols <- df %>% dplyr::select(where(is.factor))
    ui <- fluidPage(
      titlePanel("MTCARS"),
      selectInput("Columns","Numeric Columns",
                  names(numeric_cols), multiple = TRUE),
      # selectInput("Columns","Categorical Columns",
      #             names(categorical_cols), multiple = TRUE),
      plotOutput("myplot")
    )
    
    server <- function(input, output) {
      Dataframe2 <- reactive({
        req(length(input$Columns)>=2)
        mtcars[,input$Columns] 
      })
      
      my_plot<- reactive({ggplot(Dataframe2(), aes(.data[[input$Columns[1]]],.data[[input$Columns[2]]] ))+geom_point()})
      output$myplot <- renderPlot({
        my_plot()
      })
    }
    
    shinyApp(ui, server)