0

I'm trying to overlay convex hulls on-top of noisy data. I only want the hulls on the main clusters (and not the red outliers).

Toy data

How would I plot every other hull while plotting all the points?

In my workaround attempt, I accidentally made all the outliers disappeared. Additionally, the shapes (21-25) were distorted when plotting my actual data in a Shiny app.

Would this be solved by tinkering when building the stat, or by editing the mapping?

Requirements: I'd also like to keep things to ggplot2 since this will all be wrapped up in a ShinyApp, and the hulls will be plotted if the user clicks on a checkbox. The number of cluster varies per graph, but the first one is ALWAYS the outlier.

Data Generation

library(dbscan)
library(ggplot2)
data("DS3")
DS3_cl <- hdbscan(DS3, minPts = 25)
DS3_comb <- DS3
DS3_comb$cluster <- as.character(DS3_cl$cluster)

Graph functions/parameters

cols <- c('#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#a65628','#f781bf','#999999','#ffff33') 
cols_2 <-  c(NA,'#377eb8','#4daf4a','#984ea3','#ff7f00','#a65628','#f781bf','#999999','#ffff33') 

StatChull <- ggproto("StatChull", Stat, 
                     compute_group = function(data, scales) {
                       data[chull(data$x, data$y), , drop = FALSE]
                     },
                     # Do the outlier removal around here?
                     required_aes = c("x", "y")
)

stat_chull <- function(mapping = NULL, data = NULL, geom = "polygon",
                       position = "identity", na.rm = FALSE, show.legend = NA, 
                       inherit.aes = TRUE, ...) {
  layer(
    stat = StatChull, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}

Plots:

plot_1 <- ggplot(data = DS3_comb, aes(X, Y, color = cluster)) + 
  geom_point(alpha = 0.4) + 
  scale_color_manual(values = cols) +
  theme_bw()

plot_2 <- plot_1 + stat_chull(fill = NA)

Workaround Attempt:

plot_3 <- ggplot(data = DS3_comb, aes(X,Y, fill = cluster, color = cluster)) +
  geom_point(shape = 21, alpha = 0.4) +
  scale_fill_manual(values = cols) +
  scale_color_manual(values = cols_2) +
  theme_bw()

Sources consulted:

A Duv
  • 393
  • 1
  • 17

1 Answers1

1

Just subset the data for that layer. For example

plot_1 + stat_chull(fill = NA, data=subset(DS3_comb,cluster!=0))

enter image description here

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • ... I overthought things. This also worked in the ShinyApp with brush over points! – A Duv Jul 06 '18 at 17:56
  • Hey @MrFlick, I tried to make the color dependent upon a Shiny input. The `stat_chull()` wouldn't change with the changing color unless I got rid of the subset option. I tried re-specifying the hulls mapping by respecifying the color, but that didn't work. Can you point me in the right direction? I'll try to update this post with a minimal example soon if my question is too specific/complex – A Duv Jul 10 '18 at 23:38
  • 1
    @ADuv Don’t update this post. This question has been answered. If you have a new problem, start a new post. – MrFlick Jul 10 '18 at 23:50