-
-
Save dgrtwo/eb7750e74997891d7c20 to your computer and use it in GitHub Desktop.
# somewhat hackish solution to: | |
# https://twitter.com/EamonCaddigan/status/646759751242620928 | |
# based mostly on copy/pasting from ggplot2 geom_violin source: | |
# https://github.com/hadley/ggplot2/blob/master/R/geom-violin.r | |
library(ggplot2) | |
library(dplyr) | |
"%||%" <- function(a, b) { | |
if (!is.null(a)) a else b | |
} | |
geom_flat_violin <- function(mapping = NULL, data = NULL, stat = "ydensity", | |
position = "dodge", trim = TRUE, scale = "area", | |
show.legend = NA, inherit.aes = TRUE, ...) { | |
layer( | |
data = data, | |
mapping = mapping, | |
stat = stat, | |
geom = GeomFlatViolin, | |
position = position, | |
show.legend = show.legend, | |
inherit.aes = inherit.aes, | |
params = list( | |
trim = trim, | |
scale = scale, | |
... | |
) | |
) | |
} | |
#' @rdname ggplot2-ggproto | |
#' @format NULL | |
#' @usage NULL | |
#' @export | |
GeomFlatViolin <- | |
ggproto("GeomFlatViolin", Geom, | |
setup_data = function(data, params) { | |
data$width <- data$width %||% | |
params$width %||% (resolution(data$x, FALSE) * 0.9) | |
# ymin, ymax, xmin, and xmax define the bounding rectangle for each group | |
data %>% | |
group_by(group) %>% | |
mutate(ymin = min(y), | |
ymax = max(y), | |
xmin = x, | |
xmax = x + width / 2) | |
) | |
}, | |
draw_group = function(data, panel_scales, coord) { | |
# Find the points for the line to go all the way around | |
data <- transform(data, xminv = x, | |
xmaxv = x + violinwidth * (xmax - x)) | |
# Make sure it's sorted properly to draw the outline | |
newdata <- rbind(plyr::arrange(transform(data, x = xminv), y), | |
plyr::arrange(transform(data, x = xmaxv), -y)) | |
# Close the polygon: set first and last point the same | |
# Needed for coord_polar and such | |
newdata <- rbind(newdata, newdata[1,]) | |
ggplot2:::ggname("geom_flat_violin", GeomPolygon$draw_panel(newdata, panel_scales, coord)) | |
}, | |
draw_key = draw_key_polygon, | |
default_aes = aes(weight = 1, colour = "grey20", fill = "white", size = 0.5, | |
alpha = NA, linetype = "solid"), | |
required_aes = c("x", "y") | |
) | |
### Example: | |
ggplot(diamonds, aes(cut, carat)) + | |
geom_flat_violin() + | |
coord_flip() |
In case someone needs to find that comma... The mutate
command has two end braces when it should just have one.
mutate(ymin = min(y),
ymax = max(y),
xmin = x,
xmax = x + width / 2)
) # <---- Take this one out
This is so great! I will most definitely use this for a figure within a manuscript which I am preparing for publication. Please let me know if there is any need to cite the code and how. And thanks for this great contribution!
Has anyone managed to extend this example to include quantile bars?
One question, what does the vertical line inside the violin plot represents?
I am running your script to produce Raincloud plots and receieve the following error:
Error in layer(data = data, mapping = mapping, stat = stat, geom = GeomFlatViolin, :
unused arguments (data = data, mapping = mapping, stat = stat, geom = GeomFlatViolin, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(trim = trim, scale = scale, ...))
Any idea where this comes from?
Hi, are there any plans to include this in future versions of ggplot2? The geom is great and would be great to have it more easily accessible.
Thanks for sharing