Skip to content

Commit 9476a5c

Browse files
committed
Merge branch 'boxplot_varwidth3' of github.com:tsieger/ggplot2 into tsieger-boxplot_varwidth3
Conflicts: man/geom_boxplot.Rd
2 parents 18b150f + 5dc188a commit 9476a5c

File tree

4 files changed

+67
-31
lines changed

4 files changed

+67
-31
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ ggplot2 0.9.3.1.99
2727
fledged mapping projection as `coord_map()` does and therefore is much
2828
faster. Yet, it gives a correct approximation for small scale maps (a few
2929
degrees in either direction) at medium to low latitudes (@jiho, #922).
30+
* `geom_boxplot` gain new `varwidth` argument for controlling whether or not
31+
the width of boxplots should be proportional to the size of the groups
32+
(@tsieger, #927).
3033

3134
* Allow specifying only one of the limits in a scale and use the automatic
3235
calculation of the other limit by passing NA to to the limit function,

R/geom-boxplot.r

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
#' the medians differ.
3333
#' @param notchwidth for a notched box plot, width of the notch relative to
3434
#' the body (default 0.5)
35+
#' @param varwidth if \code{FALSE} (default) make a standard box plot. If
36+
#' \code{TRUE}, boxes are drawn with widths proportional to the
37+
#' square-roots of the number of observations in the groups (possibly
38+
#' weighted, using the \code{weight} aesthetic).
3539
#' @export
3640
#'
3741
#' @references McGill, R., Tukey, J. W. and Larsen, W. A. (1978) Variations of
@@ -92,13 +96,17 @@
9296
#' b + geom_boxplot(stat = "identity")
9397
#' b + geom_boxplot(stat = "identity") + coord_flip()
9498
#' b + geom_boxplot(aes(fill = X1), stat = "identity")
99+
#'
100+
#' # Using varwidth
101+
#' p + geom_boxplot(varwidth = TRUE)
102+
#' qplot(factor(cyl), mpg, data = mtcars, geom = "boxplot", varwidth = TRUE)
95103
#' }
96104
geom_boxplot <- function (mapping = NULL, data = NULL, stat = "boxplot", position = "dodge",
97105
outlier.colour = "black", outlier.shape = 16, outlier.size = 2,
98-
notch = FALSE, notchwidth = .5, ...) {
106+
notch = FALSE, notchwidth = .5, varwidth = FALSE, ...) {
99107
GeomBoxplot$new(mapping = mapping, data = data, stat = stat,
100108
position = position, outlier.colour = outlier.colour, outlier.shape = outlier.shape,
101-
outlier.size = outlier.size, notch = notch, notchwidth = notchwidth, ...)
109+
outlier.size = outlier.size, notch = notch, notchwidth = notchwidth, varwidth = varwidth, ...)
102110
}
103111

104112
GeomBoxplot <- proto(Geom, {
@@ -118,14 +126,24 @@ GeomBoxplot <- proto(Geom, {
118126
df$ymax_final <- pmax(out_max, df$ymax)
119127
}
120128

121-
transform(df,
122-
xmin = x - width / 2, xmax = x + width / 2, width = NULL
123-
)
129+
# if `varwidth` not requested or not available, don't use it
130+
if (is.null(params) || is.null(params$varwidth) || !params$varwidth || is.null(df$relvarwidth)) {
131+
df$xmin <- df$x - df$width / 2
132+
df$xmax <- df$x + df$width / 2
133+
} else {
134+
# make `relvarwidth` relative to the size of the largest group
135+
df$relvarwidth <- df$relvarwidth / max(df$relvarwidth)
136+
df$xmin <- df$x - df$relvarwidth * df$width / 2
137+
df$xmax <- df$x + df$relvarwidth * df$width / 2
138+
}
139+
df$width <- NULL
140+
if (!is.null(df$relvarwidth)) df$relvarwidth <- NULL
124141

142+
df
125143
}
126144

127145
draw <- function(., data, ..., fatten = 2, outlier.colour = NULL, outlier.shape = NULL, outlier.size = 2,
128-
notch = FALSE, notchwidth = .5) {
146+
notch = FALSE, notchwidth = .5, varwidth = FALSE) {
129147
common <- data.frame(
130148
colour = data$colour,
131149
size = data$size,

R/stat-boxplot.r

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ StatBoxplot <- proto(Stat, {
7676

7777
transform(df,
7878
x = if (is.factor(x)) x[1] else mean(range(x)),
79-
width = width
79+
width = width,
80+
relvarwidth = sqrt(n)
8081
)
8182
})
8283
}

man/geom_boxplot.Rd

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,49 @@
55
\usage{
66
geom_boxplot(mapping = NULL, data = NULL, stat = "boxplot",
77
position = "dodge", outlier.colour = "black", outlier.shape = 16,
8-
outlier.size = 2, notch = FALSE, notchwidth = 0.5, ...)
8+
outlier.size = 2, notch = FALSE, notchwidth = 0.5, varwidth = FALSE,
9+
...)
910
}
1011
\arguments{
11-
\item{outlier.colour}{colour for outlying points}
12+
\item{outlier.colour}{colour for outlying points}
1213

13-
\item{outlier.shape}{shape of outlying points}
14+
\item{outlier.shape}{shape of outlying points}
1415

15-
\item{outlier.size}{size of outlying points}
16+
\item{outlier.size}{size of outlying points}
1617

17-
\item{notch}{if \code{FALSE} (default) make a standard box plot. If
18-
\code{TRUE}, make a notched box plot. Notches are used to compare groups;
19-
if the notches of two boxes do not overlap, this is strong evidence that
20-
the medians differ.}
18+
\item{notch}{if \code{FALSE} (default) make a standard
19+
box plot. If \code{TRUE}, make a notched box plot.
20+
Notches are used to compare groups; if the notches of two
21+
boxes do not overlap, this is strong evidence that the
22+
medians differ.}
2123

22-
\item{notchwidth}{for a notched box plot, width of the notch relative to
23-
the body (default 0.5)}
24+
\item{notchwidth}{for a notched box plot, width of the
25+
notch relative to the body (default 0.5)}
2426

25-
\item{mapping}{The aesthetic mapping, usually constructed with
26-
\code{\link{aes}} or \code{\link{aes_string}}. Only needs to be set
27-
at the layer level if you are overriding the plot defaults.}
27+
\item{varwidth}{if \code{FALSE} (default) make a standard
28+
box plot. If \code{TRUE}, boxes are drawn with widths
29+
proportional to the square-roots of the number of
30+
observations in the groups (possibly weighted, using the
31+
\code{weight} aesthetic).}
2832

29-
\item{data}{A layer specific dataset - only needed if you want to override
30-
the plot defaults.}
33+
\item{mapping}{The aesthetic mapping, usually constructed
34+
with \code{\link{aes}} or \code{\link{aes_string}}. Only
35+
needs to be set at the layer level if you are overriding
36+
the plot defaults.}
3137

32-
\item{stat}{The statistical transformation to use on the data for this
33-
layer.}
38+
\item{data}{A layer specific dataset - only needed if you
39+
want to override the plot defaults.}
3440

35-
\item{position}{The position adjustment to use for overlapping points
36-
on this layer}
41+
\item{stat}{The statistical transformation to use on the
42+
data for this layer.}
3743

38-
\item{...}{other arguments passed on to \code{\link{layer}}. This can
39-
include aesthetics whose values you want to set, not map. See
40-
\code{\link{layer}} for more details.}
44+
\item{position}{The position adjustment to use for
45+
overlapping points on this layer}
46+
47+
\item{...}{other arguments passed on to
48+
\code{\link{layer}}. This can include aesthetics whose
49+
values you want to set, not map. See \code{\link{layer}}
50+
for more details.}
4151
}
4252
\description{
4353
The upper and lower "hinges" correspond to the first and third quartiles
@@ -58,8 +68,8 @@ This gives a roughly 95% confidence interval for comparing medians.
5868
See McGill et al. (1978) for more details.
5969
}
6070
\section{Aesthetics}{
61-
62-
\Sexpr[results=rd,stage=build]{ggplot2:::rd_aesthetics("geom", "boxplot")}
71+
\Sexpr[results=rd,stage=build]{ggplot2:::rd_aesthetics("geom",
72+
"boxplot")}
6373
}
6474
\examples{
6575
\donttest{
@@ -116,6 +126,10 @@ b <- ggplot(abc, aes(x = X1, ymin = `0\%`, lower = `25\%`, middle = `50\%`, uppe
116126
b + geom_boxplot(stat = "identity")
117127
b + geom_boxplot(stat = "identity") + coord_flip()
118128
b + geom_boxplot(aes(fill = X1), stat = "identity")
129+
130+
# Using varwidth
131+
p + geom_boxplot(varwidth = TRUE)
132+
qplot(factor(cyl), mpg, data = mtcars, geom = "boxplot", varwidth = TRUE)
119133
}
120134
}
121135
\references{

0 commit comments

Comments
 (0)