Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 10fa001

Browse filesBrowse files
authored
Removing direction constraint from geoms (#3506)
1 parent 88c5bde commit 10fa001
Copy full SHA for 10fa001

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner

52 files changed

+1316
-232
lines changed

‎NAMESPACE

Copy file name to clipboardExpand all lines: NAMESPACE
+3
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ export(facet_grid)
316316
export(facet_null)
317317
export(facet_wrap)
318318
export(find_panel)
319+
export(flip_data)
320+
export(flipped_names)
319321
export(fortify)
320322
export(geom_abline)
321323
export(geom_area)
@@ -390,6 +392,7 @@ export(guide_none)
390392
export(guide_train)
391393
export(guide_transform)
392394
export(guides)
395+
export(has_flipped_aes)
393396
export(is.Coord)
394397
export(is.facet)
395398
export(is.ggplot)

‎R/geom-.r

Copy file name to clipboardExpand all lines: R/geom-.r
+6-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,12 @@ Geom <- ggproto("Geom",
153153
},
154154

155155
aesthetics = function(self) {
156-
c(union(self$required_aes, names(self$default_aes)), self$optional_aes, "group")
156+
if (is.null(self$required_aes)) {
157+
required_aes <- NULL
158+
} else {
159+
required_aes <- unlist(strsplit(self$required_aes, '|', fixed = TRUE))
160+
}
161+
c(union(required_aes, names(self$default_aes)), self$optional_aes, "group")
157162
}
158163

159164
)

‎R/geom-bar.r

Copy file name to clipboardExpand all lines: R/geom-bar.r
+24-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#' [position_fill()] shows relative proportions at each `x` by stacking the bars
2020
#' and then standardising each bar to have the same height.
2121
#'
22+
#' @eval rd_orientation()
23+
#'
2224
#' @eval rd_aesthetics("geom", "bar")
2325
#' @eval rd_aesthetics("geom", "col")
2426
#' @eval rd_aesthetics("stat", "count")
@@ -29,6 +31,10 @@
2931
#' @export
3032
#' @inheritParams layer
3133
#' @inheritParams geom_point
34+
#' @param orientation The orientation of the layer. The default (`NA`)
35+
#' automatically determines the orientation from the aesthetic mapping. In the
36+
#' rare event that this fails it can be given explicitly by setting `orientation`
37+
#' to either `"x"` or `"y"`. See the *Orientation* section for more detail.
3238
#' @param width Bar width. By default, set to 90\% of the resolution of the data.
3339
#' @param binwidth `geom_bar()` no longer has a binwidth argument - if
3440
#' you use it you'll get an warning telling to you use
@@ -43,17 +49,18 @@
4349
#' g + geom_bar()
4450
#' # Total engine displacement of each class
4551
#' g + geom_bar(aes(weight = displ))
52+
#' # Map class to y instead to flip the orientation
53+
#' ggplot(mpg) + geom_bar(aes(y = class))
4654
#'
4755
#' # Bar charts are automatically stacked when multiple bars are placed
4856
#' # at the same location. The order of the fill is designed to match
4957
#' # the legend
5058
#' g + geom_bar(aes(fill = drv))
5159
#'
52-
#' # If you need to flip the order (because you've flipped the plot)
60+
#' # If you need to flip the order (because you've flipped the orientation)
5361
#' # call position_stack() explicitly:
54-
#' g +
62+
#' ggplot(mpg, aes(y = class)) +
5563
#' geom_bar(aes(fill = drv), position = position_stack(reverse = TRUE)) +
56-
#' coord_flip() +
5764
#' theme(legend.position = "top")
5865
#'
5966
#' # To show (e.g.) means, you need geom_col()
@@ -77,6 +84,7 @@ geom_bar <- function(mapping = NULL, data = NULL,
7784
width = NULL,
7885
binwidth = NULL,
7986
na.rm = FALSE,
87+
orientation = NA,
8088
show.legend = NA,
8189
inherit.aes = TRUE) {
8290

@@ -99,6 +107,7 @@ geom_bar <- function(mapping = NULL, data = NULL,
99107
params = list(
100108
width = width,
101109
na.rm = na.rm,
110+
orientation = orientation,
102111
...
103112
)
104113
)
@@ -117,16 +126,26 @@ GeomBar <- ggproto("GeomBar", GeomRect,
117126
# limits, not just those for which x and y are outside the limits
118127
non_missing_aes = c("xmin", "xmax", "ymin", "ymax"),
119128

129+
setup_params = function(data, params) {
130+
params$flipped_aes <- has_flipped_aes(data, params, range_is_orthogonal = FALSE)
131+
params
132+
},
133+
134+
extra_params = c("na.rm", "orientation"),
135+
120136
setup_data = function(data, params) {
137+
data$flipped_aes <- params$flipped_aes
138+
data <- flip_data(data, params$flipped_aes)
121139
data$width <- data$width %||%
122140
params$width %||% (resolution(data$x, FALSE) * 0.9)
123-
transform(data,
141+
data <- transform(data,
124142
ymin = pmin(y, 0), ymax = pmax(y, 0),
125143
xmin = x - width / 2, xmax = x + width / 2, width = NULL
126144
)
145+
flip_data(data, params$flipped_aes)
127146
},
128147

129-
draw_panel = function(self, data, panel_params, coord, width = NULL) {
148+
draw_panel = function(self, data, panel_params, coord, width = NULL, flipped_aes = FALSE) {
130149
# Hack to ensure that width is detected as a parameter
131150
ggproto_parent(GeomRect, self)$draw_panel(data, panel_params, coord)
132151
}

‎R/geom-boxplot.r

Copy file name to clipboardExpand all lines: R/geom-boxplot.r
+26-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#' It visualises five summary statistics (the median, two hinges
55
#' and two whiskers), and all "outlying" points individually.
66
#'
7+
#' @eval rd_orientation()
8+
#'
79
#' @section Summary statistics:
810
#' The lower and upper hinges correspond to the first and third quartiles
911
#' (the 25th and 75th percentiles). This differs slightly from the method used
@@ -28,7 +30,7 @@
2830
#' [geom_violin()] for a richer display of the distribution, and
2931
#' [geom_jitter()] for a useful technique for small data.
3032
#' @inheritParams layer
31-
#' @inheritParams geom_point
33+
#' @inheritParams geom_bar
3234
#' @param geom,stat Use to override the default connection between
3335
#' `geom_boxplot` and `stat_boxplot`.
3436
#' @param outlier.colour,outlier.color,outlier.fill,outlier.shape,outlier.size,outlier.stroke,outlier.alpha
@@ -60,7 +62,8 @@
6062
#' @examples
6163
#' p <- ggplot(mpg, aes(class, hwy))
6264
#' p + geom_boxplot()
63-
#' p + geom_boxplot() + coord_flip()
65+
#' # Orientation follows the discrete axis
66+
#' ggplot(mpg, aes(hwy, class)) + geom_boxplot()
6467
#'
6568
#' p + geom_boxplot(notch = TRUE)
6669
#' p + geom_boxplot(varwidth = TRUE)
@@ -116,6 +119,7 @@ geom_boxplot <- function(mapping = NULL, data = NULL,
116119
notchwidth = 0.5,
117120
varwidth = FALSE,
118121
na.rm = FALSE,
122+
orientation = NA,
119123
show.legend = NA,
120124
inherit.aes = TRUE) {
121125

@@ -148,6 +152,7 @@ geom_boxplot <- function(mapping = NULL, data = NULL,
148152
notchwidth = notchwidth,
149153
varwidth = varwidth,
150154
na.rm = na.rm,
155+
orientation = orientation,
151156
...
152157
)
153158
)
@@ -161,9 +166,16 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
161166

162167
# need to declare `width` here in case this geom is used with a stat that
163168
# doesn't have a `width` parameter (e.g., `stat_identity`).
164-
extra_params = c("na.rm", "width"),
169+
extra_params = c("na.rm", "width", "orientation"),
170+
171+
setup_params = function(data, params) {
172+
params$flipped_aes <- has_flipped_aes(data, params)
173+
params
174+
},
165175

166176
setup_data = function(data, params) {
177+
data$flipped_aes <- params$flipped_aes
178+
data <- flip_data(data, params$flipped_aes)
167179
data$width <- data$width %||%
168180
params$width %||% (resolution(data$x, FALSE) * 0.9)
169181

@@ -173,8 +185,8 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
173185
out_max <- vapply(data$outliers, max, numeric(1))
174186
})
175187

176-
data$ymin_final <- pmin(out_min, data$ymin)
177-
data$ymax_final <- pmax(out_max, data$ymax)
188+
data$ymin_final <- pmin(out_min, data$ymin)
189+
data$ymax_final <- pmax(out_max, data$ymax)
178190
}
179191

180192
# if `varwidth` not requested or not available, don't use it
@@ -190,16 +202,16 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
190202
data$width <- NULL
191203
if (!is.null(data$relvarwidth)) data$relvarwidth <- NULL
192204

193-
data
205+
flip_data(data, params$flipped_aes)
194206
},
195207

196208
draw_group = function(data, panel_params, coord, fatten = 2,
197209
outlier.colour = NULL, outlier.fill = NULL,
198210
outlier.shape = 19,
199211
outlier.size = 1.5, outlier.stroke = 0.5,
200212
outlier.alpha = NULL,
201-
notch = FALSE, notchwidth = 0.5, varwidth = FALSE) {
202-
213+
notch = FALSE, notchwidth = 0.5, varwidth = FALSE, flipped_aes = FALSE) {
214+
data <- flip_data(data, flipped_aes)
203215
# this may occur when using geom_boxplot(stat = "identity")
204216
if (nrow(data) != 1) {
205217
stop(
@@ -226,6 +238,7 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
226238
),
227239
common
228240
), n = 2)
241+
whiskers <- flip_data(whiskers, flipped_aes)
229242

230243
box <- new_data_frame(c(
231244
list(
@@ -241,6 +254,7 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
241254
),
242255
common
243256
))
257+
box <- flip_data(box, flipped_aes)
244258

245259
if (!is.null(data$outliers) && length(data$outliers[[1]] >= 1)) {
246260
outliers <- new_data_frame(list(
@@ -254,6 +268,8 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
254268
fill = NA,
255269
alpha = outlier.alpha %||% data$alpha[1]
256270
), n = length(data$outliers[[1]]))
271+
outliers <- flip_data(outliers, flipped_aes)
272+
257273
outliers_grob <- GeomPoint$draw_panel(outliers, panel_params, coord)
258274
} else {
259275
outliers_grob <- NULL
@@ -262,7 +278,7 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
262278
ggname("geom_boxplot", grobTree(
263279
outliers_grob,
264280
GeomSegment$draw_panel(whiskers, panel_params, coord),
265-
GeomCrossbar$draw_panel(box, fatten = fatten, panel_params, coord)
281+
GeomCrossbar$draw_panel(box, fatten = fatten, panel_params, coord, flipped_aes = flipped_aes)
266282
))
267283
},
268284

@@ -271,5 +287,5 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
271287
default_aes = aes(weight = 1, colour = "grey20", fill = "white", size = 0.5,
272288
alpha = NA, shape = 19, linetype = "solid"),
273289

274-
required_aes = c("x", "lower", "upper", "middle", "ymin", "ymax")
290+
required_aes = c("x|y", "lower|xlower", "upper|xupper", "middle|xmiddle", "ymin|xmin", "ymax|xmax")
275291
)

‎R/geom-col.r

Copy file name to clipboardExpand all lines: R/geom-col.r
+14-4
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,26 @@ GeomCol <- ggproto("GeomCol", GeomRect,
3737
# limits, not just those for which x and y are outside the limits
3838
non_missing_aes = c("xmin", "xmax", "ymin", "ymax"),
3939

40+
setup_params = function(data, params) {
41+
params$flipped_aes <- has_flipped_aes(data, params)
42+
params
43+
},
44+
45+
extra_params = c("na.rm", "orientation"),
46+
4047
setup_data = function(data, params) {
48+
data$flipped_aes <- params$flipped_aes
49+
data <- flip_data(data, params$flipped_aes)
4150
data$width <- data$width %||%
4251
params$width %||% (resolution(data$x, FALSE) * 0.9)
43-
transform(data,
44-
ymin = pmin(y, 0), ymax = pmax(y, 0),
45-
xmin = x - width / 2, xmax = x + width / 2, width = NULL
52+
data <- transform(data,
53+
ymin = pmin(y, 0), ymax = pmax(y, 0),
54+
xmin = x - width / 2, xmax = x + width / 2, width = NULL
4655
)
56+
flip_data(data, params$flipped_aes)
4757
},
4858

49-
draw_panel = function(self, data, panel_params, coord, width = NULL) {
59+
draw_panel = function(self, data, panel_params, coord, width = NULL, flipped_aes = FALSE) {
5060
# Hack to ensure that width is detected as a parameter
5161
ggproto_parent(GeomRect, self)$draw_panel(data, panel_params, coord)
5262
}

‎R/geom-crossbar.r

Copy file name to clipboardExpand all lines: R/geom-crossbar.r
+14-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ geom_crossbar <- function(mapping = NULL, data = NULL,
55
...,
66
fatten = 2.5,
77
na.rm = FALSE,
8+
orientation = NA,
89
show.legend = NA,
910
inherit.aes = TRUE) {
1011
layer(
@@ -18,6 +19,7 @@ geom_crossbar <- function(mapping = NULL, data = NULL,
1819
params = list(
1920
fatten = fatten,
2021
na.rm = na.rm,
22+
orientation = orientation,
2123
...
2224
)
2325
)
@@ -28,18 +30,26 @@ geom_crossbar <- function(mapping = NULL, data = NULL,
2830
#' @usage NULL
2931
#' @export
3032
GeomCrossbar <- ggproto("GeomCrossbar", Geom,
33+
setup_params = function(data, params) {
34+
GeomErrorbar$setup_params(data, params)
35+
},
36+
37+
extra_params = c("na.rm", "orientation"),
38+
3139
setup_data = function(data, params) {
3240
GeomErrorbar$setup_data(data, params)
3341
},
3442

3543
default_aes = aes(colour = "black", fill = NA, size = 0.5, linetype = 1,
3644
alpha = NA),
3745

38-
required_aes = c("x", "y", "ymin", "ymax"),
46+
required_aes = c("x", "y", "ymin|xmin", "ymax|xmax"),
3947

4048
draw_key = draw_key_crossbar,
4149

42-
draw_panel = function(data, panel_params, coord, fatten = 2.5, width = NULL) {
50+
draw_panel = function(data, panel_params, coord, fatten = 2.5, width = NULL, flipped_aes = FALSE) {
51+
data <- flip_data(data, flipped_aes)
52+
4353
middle <- transform(data, x = xmin, xend = xmax, yend = y, size = size * fatten, alpha = NA)
4454

4555
has_notch <- !is.null(data$ynotchlower) && !is.null(data$ynotchupper) &&
@@ -85,6 +95,8 @@ GeomCrossbar <- ggproto("GeomCrossbar", Geom,
8595
group = rep(seq_len(nrow(data)), 5) # each bar forms it's own group
8696
))
8797
}
98+
box <- flip_data(box, flipped_aes)
99+
middle <- flip_data(middle, flipped_aes)
88100

89101
ggname("geom_crossbar", gTree(children = gList(
90102
GeomPolygon$draw_panel(box, panel_params, coord),

‎R/geom-density.r

Copy file name to clipboardExpand all lines: R/geom-density.r
+8-1
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
#' the histogram. This is a useful alternative to the histogram for continuous
55
#' data that comes from an underlying smooth distribution.
66
#'
7+
#' @eval rd_orientation()
8+
#'
79
#' @eval rd_aesthetics("geom", "density")
810
#' @seealso See [geom_histogram()], [geom_freqpoly()] for
911
#' other methods of displaying continuous distribution.
1012
#' See [geom_violin()] for a compact density display.
1113
#' @inheritParams layer
12-
#' @inheritParams geom_point
14+
#' @inheritParams geom_bar
1315
#' @param geom,stat Use to override the default connection between
1416
#' `geom_density` and `stat_density`.
1517
#' @export
1618
#' @examples
1719
#' ggplot(diamonds, aes(carat)) +
1820
#' geom_density()
21+
#' # Map the values to y to flip the orientation
22+
#' ggplot(diamonds, aes(y = carat)) +
23+
#' geom_density()
1924
#'
2025
#' ggplot(diamonds, aes(carat)) +
2126
#' geom_density(adjust = 1/5)
@@ -49,6 +54,7 @@ geom_density <- function(mapping = NULL, data = NULL,
4954
stat = "density", position = "identity",
5055
...,
5156
na.rm = FALSE,
57+
orientation = NA,
5258
show.legend = NA,
5359
inherit.aes = TRUE) {
5460

@@ -62,6 +68,7 @@ geom_density <- function(mapping = NULL, data = NULL,
6268
inherit.aes = inherit.aes,
6369
params = list(
6470
na.rm = na.rm,
71+
orientation = orientation,
6572
...
6673
)
6774
)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.