r-lib/gtable

API requests

kohske opened this issue · 7 comments

Here is a wish-list of gtable API.
Sorry if I'm missing current implementation.

  • get one element of gtable by name or location. maybe overriding [[ and [.
  • modify the one element, with several consistency check.
  • remove a row/column
  • replace a row/column/cell/region

will be continued.

Should I create separate issues?

So I think you can now remove a row/col with negative indexing. But I agree gtable needs more tools for working at the grob level.

Maybe gtable_width, gtable_width<-, gtable_height, gtable_height<-, gtable_modify_grob ?

The initial stab for gtable_modify_grob may be like [<-.gtable with dimension check and size adjustment.
Then,

g <- gt[1:2, 1:2]
# modify the elements of g
gt[1:2, 1:2] <- g

So I think you can now remove a row/col with negative indexing

will be useful but now negative indexing only works as row-wise or col-wise deletion.

gt <- gtable_matrix(letters[1:9], matrix(list(grob1), 3, 3), widths = unit(rep(1, 3), "null"), heights = unit(rep(1, 3), "null"))
gt[-2, -2]

Ah, this behavior is compatible with matrix:

m <- matrix(1:9, 3, 3)
m[-2, -2, drop = F]

so, what we need is an interface to remove grob from gtable, like

gt[2, 2] <- NULL

but in gtable, how should it be if multi-cell grob?
I couldn't find best solution... or may be this is unnecessary.

I think the complication is that you want to interact with the gtable on two levels: the table level and the individual grob level. Two-d indexing makes sense for the table level, but I don't think it does for the grob level (because as you pointed out how would multi-cell grobs work?)

One option would be to override [.gtable so when you used a single index it indexed into the grobs. I think this is confusing though. Another option would be create a function that worked in the same way as names, so you could go grobs(gtable)[1] <- new_grob. I think then you'd also need a layout function for modifying their position. (But then how do you keep them in sync if you want to remove a grob? Removing a group would automatically remove the corresponding layout layer?)

Then you could have a find_grob that returned a logical vector of grobs meeting your criteria and use that to index into grobs and layout. You might want to find all the grobs in a given cell, or that cross a given cell, or have a given name, ...

if I think of a gtable as a data.frame rather than a matrix, then locating (a) grob(s) is like applying subset() with t, b, l, r and/or names.

locating and removing grobs is definitely a useful feature to have, see how messy it gets in this example: https://groups.google.com/d/msg/ggplot2/87gdDq0P3x0/WZxs89AY1HwJ