Skip to content

Instantly share code, notes, and snippets.

@mbedward
Last active June 10, 2019 19:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mbedward/26296da610fd747a9b9f62672f57e9c1 to your computer and use it in GitHub Desktop.
Save mbedward/26296da610fd747a9b9f62672f57e9c1 to your computer and use it in GitHub Desktop.
Example of drawing convex hulls around grouped points in R using dplyr and ggplot.
# This is adapted from a nice example at:
# http://f.briatte.org/r/convex-hulls-with-dplyr-and-ggplot2
# https://gist.github.com/briatte/50cb31531966c99a9acc
#
library(ggplot2)
library(dplyr)
# Parameters for test data and graph
Ngroups <- 4
GroupSize <- sample(4:20, Ngroups, replace = TRUE)
Facets <- TRUE
# Convex hull function. Takes a data frame with:
#
# - x,y columns
# - an optional group column
# - any additional columns
#
# Returns a new data frame with rows reduced to those
# for convex hull vertices and a new hull column giving
# the order in which to plot (e.g. with geom_polygon).
#
hullfn <- function(dat,
xcol = "x", ycol = "y",
groupcol = NULL,
hullcol = "hull") {
do_hull <- function(xs, ys) {
ii <- 1:length(xs)
hi <- chull(xs, ys)
match(ii, hi)
}
cols <- colnames(dat)
ix <- match(xcol, cols)
iy <- match(ycol, cols)
colnames(dat)[c(ix, iy)] <- c("x", "y")
grps <- !is.null(groupcol)
if (grps) {
dat <- group_by_(dat, .dots = groupcol)
}
dat <- dat %>%
mutate(hull = do_hull(x, y)) %>%
arrange(hull) %>%
filter(!is.na(hull))
if (grps) dat <- ungroup(dat)
# restore original column names
colnames(dat) <- c(cols, hullcol)
dat
}
# Generate some test data
xy <- data_frame(
igrp = rep(1:Ngroups, GroupSize),
grp = LETTERS[igrp]) %>%
group_by(grp) %>%
mutate(x = runif(n(), igrp/2, igrp/2 + 1),
y = runif(n(), 0, 1)) %>%
ungroup()
# Get data for convex hulls
hulls <- hullfn(xy, groupcol = "grp")
# Plot points and convex hulls
g <- ggplot(data = xy, aes(x, y, colour = grp, fill = grp)) +
geom_polygon(data = hulls, alpha = 0.4) +
geom_point() +
guides(colour = FALSE, fill = FALSE) +
coord_equal() +
theme_bw() +
theme(axis.text = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank())
if (Facets) {
g <- g +
facet_wrap(~ grp, scales = "free") +
theme(strip.background = element_blank())
}
print(g)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment