I would like to add lines between \"mean\" in my boxplot.
My code:
library(ggplot2)
library(ggthemes)
Gp=factor(c(rep(\"G1\",80),rep(\"G2\",80)))
Fc=fac
Another approach, admittedly a bit convoluted, but hopefully it avoids some hardcoding.
The idea is to build a plot object including the stat_summary
call. From this, grab relevant data (ggplot_build(p)$data[[2]]
) to be used for the lines. The second data slot ([[2]]
) corresponds to the second layer in the plot call, i.e. the x
and y
generated by stat_summary
.
Grab x
and y
positions and indices of panel (PANEL
) and x categories (group
).
In the data from the plot object, the 'PANEL' and 'group' variables are not given explicitly by their names, but as numbers corresponding to the different combinations of facet
variables, and variables which eventually will generate a numeric x
position (here both 'the real' x
and fill
).
However, because categorical variables are ordered lexicographically in ggplot
, we can match the numbers with their corresponding variables. The .GRP
function in data.table
is convenient here.
This data can then be used to draw a geom_line
between the means.
# dodge value
pos <- position_dodge(width = 0.75)
# initial plot
p <- ggplot(data = DATA, aes(x = X, y = Y, fill = Z)) +
geom_boxplot(outlier.size = NA, outlier.colour = NA,
position = pos) +
stat_summary(fun.y = mean, geom = "point", shape = 23, position = pos) +
facet_grid(Gp ~ Fc)
# grab relevant data
d <- ggplot_build(p)$data[[2]][ , c("PANEL", "group", "x", "y")]
library(data.table)
setDT(DATA)
# select unique combinations of facet and x variables
# here x includes the fill variable 'Z'
d2 <- unique(DATA[ , .(Gp, Fc, Z, X)])
# numeric index of facet combinations
d2[ , PANEL := .GRP, by = .(Gp, Fc)]
# numeric index of x combinations
d2[ , group := .GRP, by = .(Z, X)]
# add x and y positions by joining on PANEL and group
d2 <- d2[d, on = .(PANEL, group)]
# plot!
p + geom_line(data = d2, aes(x = x, y = y))