Skip to content

Commit a45749c

Browse files
committed
Implement widths/heights arguments
1 parent ab2de06 commit a45749c

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ Rapp.history
33
*.Rhistory
44
*.RData
55
*.Rproj.user
6-
.Rproj.user
6+
*.DS_Store
77
build_site.R
8+
todo.R
89
inst/examples/*/*.html
910
inst/examples/*/rsconnect/*

R/subplots.R

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
#' @param ... any number of plotly objects
44
#' @param nrows number of rows for laying out plots in a grid-like structure.
55
#' Only used if no domain is already specified.
6+
#' @param widths relative width of each column on a 0-1 scale. By default all
7+
#' columns have an equal relative width.
8+
#' @param heights relative height of each row on a 0-1 scale. By default all
9+
#' rows have an equal relative height.
10+
#' @param share determines whether x/y/both axes are shared.
611
#' @param which_layout adopt the layout of which plot? If the default value of
712
#' "merge" is used, all plot level layout options will be included in the final
813
#' layout. This argument also accepts a numeric vector which will restric
@@ -20,7 +25,8 @@
2025
#' subplot(p1, p2, p1, p2, nrows = 2)
2126
#' }
2227

23-
subplot <- function(..., nrows = 1, which_layout = "merge", margin = 0.02) {
28+
subplot <- function(..., nrows = 1, widths = NULL, heights = NULL, share = NULL,
29+
which_layout = "merge", margin = 0.02) {
2430
# build each plot and collect relevant info
2531
plots <- lapply(list(...), plotly_build)
2632
traces <- lapply(plots, "[[", "data")
@@ -58,7 +64,9 @@ subplot <- function(..., nrows = 1, which_layout = "merge", margin = 0.02) {
5864
yAxisMap <- split(yAxisMap, rep(seq_along(plots), yAxisN))
5965
# domains of each subplot
6066
# TODO: allow control of column width and row height!
61-
domainInfo <- get_domains(length(plots), nrows, margin)
67+
domainInfo <- get_domains(
68+
length(plots), nrows, margin, widths = widths, heights = heights
69+
)
6270
# reposition shapes and annotations
6371
annotations <- Map(reposition, annotations, split(domainInfo, seq_along(plots)))
6472
shapes <- Map(reposition, shapes, split(domainInfo, seq_along(plots)))
@@ -122,16 +130,40 @@ subplot <- function(..., nrows = 1, which_layout = "merge", margin = 0.02) {
122130
}
123131

124132

125-
get_domains <- function(nplots = 1, nrows = 1, margins = 0.01) {
133+
get_domains <- function(nplots = 1, nrows = 1, margins = 0.01,
134+
widths = NULL, heights = NULL) {
126135
if (length(margins) == 1) margins <- rep(margins, 4)
127136
if (length(margins) != 4) stop("margins must be length 1 or 4", call. = FALSE)
128137
ncols <- ceiling(nplots / nrows)
138+
widths <- widths %||% rep(1 / ncols, ncols)
139+
heights <- heights %||% rep(1 / nrows, nrows)
140+
if (length(widths) != ncols) {
141+
stop("The length of the widths argument must be equal ",
142+
"to the number of columns", call. = FALSE)
143+
}
144+
if (length(heights) != nrows) {
145+
stop("The length of the heights argument must be equal ",
146+
"to the number of rows", call. = FALSE)
147+
}
148+
if (any(widths < 0 | heights < 0)) {
149+
stop("The widths and heights arguments must contain positive values")
150+
}
151+
if (sum(widths) > 1 | sum(heights) > 1) {
152+
stop("The sum of the widths and heights arguments must be less than 1")
153+
}
154+
155+
widths <- cumsum(c(0, widths))
156+
heights <- cumsum(c(0, heights))
157+
# 'center' these values if there is still room left
158+
widths <- widths + (1 - max(widths)) / 2
159+
heights <- heights + (1 - max(heights)) / 2
160+
129161

130162
xs <- vector("list", ncols)
131163
for (i in seq_len(ncols)) {
132164
xs[[i]] <- c(
133-
xstart = ((i - 1) / ncols) + ifelse(i == 1, 0, margins[1]),
134-
xend = (i / ncols) - ifelse(i == ncols, 0, margins[2])
165+
xstart = widths[i] + if (i == 1) 0 else margins[1],
166+
xend = widths[i + 1] - if (i == ncols) 0 else margins[2]
135167
)
136168
}
137169
xz <- rep_len(xs, nplots)
@@ -140,8 +172,8 @@ get_domains <- function(nplots = 1, nrows = 1, margins = 0.01) {
140172
for (i in seq_len(nplots)) {
141173
j <- ceiling(i / ncols)
142174
ys[[i]] <- c(
143-
ystart = 1 - ((j - 1) / nrows) - ifelse(j == 1, 0, margins[3]),
144-
yend = 1 - (j / nrows) + ifelse(j == nrows, 0, margins[4])
175+
ystart = 1 - (heights[j]) - if (j == 1) 0 else margins[3],
176+
yend = 1 - (heights[j + 1]) + if (j == nrows) 0 else margins[4]
145177
)
146178
}
147179
list2df(Map(c, xz, ys))

0 commit comments

Comments
 (0)