Instantly share code, notes, and snippets.

Embed
What would you like to do?
# 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()
@benmarwick

This comment has been minimized.

Show comment
Hide comment
@benmarwick

benmarwick Mar 27, 2016

I think you might have a stray closing parenthesis on L50 (I needed to remove it to make it work with ggplot2_2.1.0).

benmarwick commented Mar 27, 2016

I think you might have a stray closing parenthesis on L50 (I needed to remove it to make it work with ggplot2_2.1.0).

@peterparkerspicklepatch

This comment has been minimized.

Show comment
Hide comment
@peterparkerspicklepatch

peterparkerspicklepatch May 3, 2016

Can someone repost this? It's become a hunt for parenthesis.

peterparkerspicklepatch commented May 3, 2016

Can someone repost this? It's become a hunt for parenthesis.

@mvuorre

This comment has been minimized.

Show comment
Hide comment
@mvuorre

mvuorre Jan 4, 2017

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

mvuorre commented Jan 4, 2017

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

@sahirmoosvi

This comment has been minimized.

Show comment
Hide comment
@sahirmoosvi

sahirmoosvi Jan 18, 2017

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

sahirmoosvi commented Jan 18, 2017

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment