@@ -29,7 +29,7 @@ FacetGrid <- proto(Facet, {
29
29
. $ proto(
30
30
rows = rows , cols = cols , margins = margins ,
31
31
free = free , space_is_free = (space == " free" ),
32
- labeller = list ( labeller ) , as.table = as.table
32
+ labeller = labeller , as.table = as.table
33
33
)
34
34
}
35
35
@@ -143,14 +143,121 @@ FacetGrid <- proto(Facet, {
143
143
144
144
# Create grobs for each component of the panel guides
145
145
add_guides <- function (. , panels_grob , coord , theme ) {
146
+ panels <- . $ panel_info $ PANEL
147
+ coord_details <- llply(panels , function (i ) {
148
+ coord $ compute_ranges(. $ panel_scales(i ))
149
+ })
150
+
151
+ axes <- . $ build_axes(coord , coord_details , theme )
152
+ strips <- . $ build_strips(coord_details , theme )
153
+ panels <- . $ build_panels(panels_grob , coord , coord_details , theme )
154
+ # legend
155
+ # labels
156
+
157
+ # Combine components into complete plot
158
+ centre <- (axes $ l $ clone())$ cbind(panels )$ cbind(strips $ r )
159
+ top <- (strips $ t $ clone())$
160
+ add_cols(strips $ r $ widths )$
161
+ add_cols(axes $ l $ widths , pos = 0 )
162
+ bottom <- (axes $ b $ clone())$
163
+ add_cols(strips $ r $ widths )$
164
+ add_cols(axes $ l $ widths , pos = 0 )
165
+
166
+ complete <- centre $ clone()$
167
+ rbind(top , pos = 0 )$
168
+ rbind(bottom )
169
+ complete $ respect <- panels $ respect
170
+ complete $ name <- " layout"
171
+
172
+ complete
173
+ }
174
+
175
+ build_strips <- function (. , coord_details , theme ) {
176
+ col_vars <- ddply(. $ panel_info , " COL" , uniquecols )
177
+ row_vars <- ddply(. $ panel_info , " ROW" , uniquecols )
178
+
179
+ list (
180
+ r = . $ build_strip(row_vars , theme , " r" ),
181
+ t = . $ build_strip(col_vars , theme , " t" )
182
+ )
183
+ }
184
+
185
+ build_strip <- function (. , label_df , theme , side = " right" ) {
186
+ side <- match.arg(side , c(" t" , " l" , " b" , " r" ))
187
+ horizontal <- side %in% c(" t" , " b" )
188
+ labeller <- match.fun(. $ labeller )
189
+
190
+ label_df <- label_df [setdiff(names(label_df ),
191
+ c(" PANEL" , " COL" , " ROW" , " SCALE_X" , " SCALE_Y" ))]
192
+
193
+ # No labelling data, so return empty row/col
194
+ if (empty(label_df )) {
195
+ if (horizontal ) {
196
+ widths <- unit(rep(1 , max(. $ panel_info $ COL )), " null" )
197
+ return (layout_empty_row(widths ))
198
+ } else {
199
+ heights <- unit(rep(1 , max(. $ panel_info $ ROW )), " null" )
200
+ return (layout_empty_col(heights ))
201
+ }
202
+ }
203
+
204
+ # Create matrix of labels
205
+ labels <- matrix (list (), nrow = nrow(label_df ), ncol = ncol(label_df ))
206
+ for (i in seq_len(ncol(label_df ))) {
207
+ labels [, i ] <- labeller(names(label_df )[i ], label_df [, i ])
208
+ }
209
+
210
+ # Render as grobs
211
+ grobs <- aaply(labels , c(1 ,2 ), ggstrip , theme = theme ,
212
+ horizontal = horizontal , .drop = FALSE )
213
+
214
+ # Create layout
215
+ name <- paste(" strip" , side , sep = " -" )
216
+ if (horizontal ) {
217
+ grobs <- t(grobs )
218
+
219
+ # Each row is as high as the highest as a wide as the panel
220
+ row_height <- function (row ) max(laply(row , height_cm ))
221
+ heights <- unit(apply(grobs , 1 , row_height ), " cm" )
222
+ widths <- unit(rep(1 , ncol(grobs )), " null" )
223
+ } else {
224
+ # Each row is wide as the widest and as high as the panel
225
+ col_width <- function (col ) max(laply(col , width_cm ))
226
+ widths <- unit(apply(grobs , 2 , col_width ), " cm" )
227
+ heights <- unit(rep(1 , nrow(grobs )), " null" )
228
+ }
229
+ strips <- layout_matrix(name , grobs , heights = heights , widths = widths )
230
+
231
+ if (horizontal ) {
232
+ strips $ add_col_space(theme $ panel.margin )
233
+ } else {
234
+ strips $ add_row_space(theme $ panel.margin )
235
+ }
236
+ strips
237
+ }
238
+
239
+ build_axes <- function (. , coord , coord_details , theme ) {
240
+ axes <- list ()
241
+
242
+ # Horizontal axes
243
+ cols <- which(. $ panel_info $ ROW == 1 )
244
+ grobs <- lapply(coord_details [cols ], coord $ guide_axis_h , theme )
245
+ axes $ b <- layout_row(" axis-b" , grobs )$ add_col_space(theme $ panel.margin )
246
+
247
+ # Vertical axes
248
+ rows <- which(. $ panel_info $ COL == 1 )
249
+ grobs <- lapply(coord_details [rows ], coord $ guide_axis_v , theme )
250
+ axes $ l <- layout_col(" axis-l" , grobs )$ add_row_space(theme $ panel.margin )
146
251
252
+ axes
253
+ }
254
+ build_panels <- function (. , panels_grob , coord , coord_details , theme ) {
147
255
aspect_ratio <- theme $ aspect.ratio
148
256
149
257
# If user hasn't set aspect ratio, and we have fixed scales, then
150
258
# ask the coordinate system if it wants to specify one
151
259
if (is.null(aspect_ratio ) && ! . $ free $ x && ! . $ free $ y ) {
152
- ranges <- coord $ compute_ranges(. $ panel_scales(1 ))
153
- aspect_ratio <- coord $ compute_aspect(ranges )
260
+ aspect_ratio <- coord $ compute_aspect(coord_details [[1 ]])
154
261
}
155
262
156
263
if (is.null(aspect_ratio )) {
@@ -159,142 +266,39 @@ FacetGrid <- proto(Facet, {
159
266
} else {
160
267
respect <- TRUE
161
268
}
162
-
163
- panels <- . $ panel_info $ PANEL
164
- cols <- which(. $ panel_info $ ROW == 1 )
165
- rows <- which(. $ panel_info $ COL == 1 )
166
-
167
- coord_details <- llply(panels , function (i ) {
168
- coord $ compute_ranges(. $ panel_scales(i ))
169
- })
170
-
171
- # Horizontal axes
172
- axes_h <- lapply(coord_details [cols ], coord $ guide_axis_h , theme )
173
- axes_h_height <- do.call(" max2" , llply(axes_h , grobHeight ))
174
- axeshGrid <- grobGrid(
175
- " axis_h" , axes_h , nrow = 1 , ncol = length(cols ),
176
- heights = axes_h_height , clip = " off"
177
- )
178
-
179
- # Vertical axes
180
- axes_v <- lapply(coord_details [rows ], coord $ guide_axis_v , theme )
181
- axes_v_width <- do.call(" max2" , llply(axes_v , grobWidth ))
182
- axesvGrid <- grobGrid(
183
- " axis_v" , axes_v , nrow = length(rows ), ncol = 1 ,
184
- widths = axes_v_width , as.table = . $ as.table , clip = " off"
185
- )
186
-
187
- # Strips
188
- labels <- . $ labels_default(. $ shape , theme )
189
-
190
- strip_widths <- llply(labels $ v , grobWidth )
191
- strip_widths <- do.call(" unit.c" , llply(1 : ncol(strip_widths ),
192
- function (i ) do.call(" max2" , strip_widths [, i ])))
193
- stripvGrid <- grobGrid(
194
- " strip_v" , labels $ v , nrow = nrow(labels $ v ), ncol = ncol(labels $ v ),
195
- widths = strip_widths , as.table = . $ as.table
196
- )
197
-
198
- strip_heights <- llply(labels $ h , grobHeight )
199
- strip_heights <- do.call(" unit.c" , llply(1 : nrow(strip_heights ),
200
- function (i ) do.call(" max2" , strip_heights [i , ])))
201
- striphGrid <- grobGrid(
202
- " strip_h" , labels $ h , nrow = nrow(labels $ h ), ncol = ncol(labels $ h ),
203
- heights = strip_heights
204
- )
205
269
206
270
# Add background and foreground to panels
207
- panels_grob <- lapply(panels , function (i ) {
271
+ panels <- . $ panel_info $ PANEL
272
+ panel_grobs <- lapply(panels , function (i ) {
208
273
fg <- coord $ guide_foreground(coord_details [[i ]], theme )
209
274
bg <- coord $ guide_background(coord_details [[i ]], theme )
210
275
grobTree(bg , panels_grob [[i ]], fg )
211
276
})
212
- dim(panels_grob ) <- c(length(rows ), length(cols ))
277
+ nrow <- max(. $ panel_info $ ROW )
278
+ ncol <- max(. $ panel_info $ COL )
279
+ dim(panel_grobs ) <- c(nrow , ncol )
213
280
214
281
if (. $ space_is_free ) {
215
282
size <- function (y ) unit(diff(y $ output_expand()), " null" )
216
- panel_widths <- do.call(" unit.c" , llply(. $ scales $ x , size ))
217
- panel_heights <- do.call(" unit.c" , llply(. $ scales $ y , size ))
283
+ x_scales <- . $ panel_info $ scale_x [. $ panel_info $ ROW == 1 ]
284
+ y_scales <- . $ panel_info $ scale_y [. $ panel_info $ COL == 1 ]
285
+
286
+ panel_widths <- do.call(" unit.c" , llply(. $ scales $ x , size ))[x_scales ]
287
+ panel_heights <- do.call(" unit.c" , llply(. $ scales $ y , size ))[y_scales ]
218
288
} else {
219
- panel_widths <- unit(1 , " null" )
220
- panel_heights <- unit(1 * aspect_ratio , " null" )
289
+ panel_widths <- rep( unit(1 , " null" ), ncol )
290
+ panel_heights <- rep( unit(1 * aspect_ratio , " null" ), nrow )
221
291
}
292
+
222
293
223
- panelGrid <- grobGrid(
224
- " panel" , t(panels_grob ), ncol = length(cols ), nrow = length(rows ),
225
- widths = panel_widths , heights = panel_heights , as.table = . $ as.table ,
226
- respect = respect
227
- )
228
-
229
- # Add gaps and compute widths and heights
230
- fill_tl <- spacer(nrow(labels $ h ), 1 )
231
- fill_tr <- spacer(nrow(labels $ h ), ncol(labels $ v ))
232
- fill_bl <- spacer(1 , 1 )
233
- fill_br <- spacer(1 , ncol(labels $ v ))
234
-
235
- all <- rbind(
236
- cbind(fill_tl , striphGrid , fill_tr ),
237
- cbind(axesvGrid , panelGrid , stripvGrid ),
238
- cbind(fill_bl , axeshGrid , fill_br )
239
- )
240
- # theme$panel.margin, theme$panel.margin
241
-
242
- # from left to right
243
- hgap_widths <- do.call(" unit.c" , compact(list (
244
- unit(0 , " cm" ), # no gap after axis
245
- rep.unit2(theme $ panel.margin , length(cols ) - 1 ), # gap after all panels except last
246
- unit(rep(0 , ncol(stripvGrid ) + 1 ), " cm" ) # no gap after strips
247
- )))
248
- hgap <- grobGrid(" hgap" ,
249
- ncol = ncol(all ), nrow = nrow(all ),
250
- widths = hgap_widths ,
251
- )
252
-
253
- # from top to bottom
254
- vgap_heights <- do.call(" unit.c" , compact(list (
255
- unit(rep(0 , nrow(striphGrid ) + 1 ), " cm" ), # no gap after strips
256
- rep.unit2(theme $ panel.margin , length(rows ) - 1 ), # gap after all panels except last
257
- unit(0 , " cm" ) # no gap after axis
258
- )))
259
-
260
- vgap <- grobGrid(" vgap" ,
261
- nrow = nrow(all ), ncol = ncol(all ) * 2 ,
262
- heights = vgap_heights
263
- )
264
-
265
- rweave(cweave(all , hgap ), vgap )
294
+ panels <- layout_matrix(" panel" , panel_grobs , panel_widths , panel_heights )
295
+ panels $ respect <- respect
296
+ panels $ add_col_space(theme $ panel.margin )
297
+ panels $ add_row_space(theme $ panel.margin )
298
+ panels
266
299
}
267
300
268
301
269
- labels_default <- function (. , gm , theme ) {
270
- col_vars <- ddply(. $ panel_info , " COL" , uniquecols )
271
- row_vars <- ddply(. $ panel_info , " ROW" , uniquecols )
272
-
273
- list (
274
- h = t(. $ make_labels(col_vars , theme )),
275
- v = . $ make_labels(row_vars , theme , horizontal = FALSE )
276
- )
277
- }
278
-
279
- make_labels <- function (. , label_df , theme , ... ) {
280
- labeller <- match.fun(. $ labeller [[1 ]])
281
-
282
- label_df <- label_df [setdiff(names(label_df ),
283
- c(" PANEL" , " COL" , " ROW" , " SCALE_X" , " SCALE_Y" ))]
284
-
285
- labels <- matrix (list (), nrow = nrow(label_df ), ncol = ncol(label_df ))
286
- for (i in seq_len(ncol(label_df ))) {
287
- labels [, i ] <- labeller(names(label_df )[i ], label_df [, i ])
288
- }
289
-
290
- if (nrow(label_df ) == 1 ) {
291
- grobs <- matrix (list (zeroGrob()))
292
- } else {
293
- grobs <- apply(labels , c(1 ,2 ), ggstrip , theme = theme , ... )
294
- }
295
- grobs
296
- }
297
-
298
302
# Documentation ------------------------------------------------------------
299
303
300
304
objname <- " grid"
0 commit comments