Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gg gt #1015

Closed
wants to merge 8 commits into from
Closed

Gg gt #1015

wants to merge 8 commits into from

Conversation

thebioengineer
Copy link
Collaborator

@thebioengineer thebioengineer commented Aug 18, 2022

Summary

Thank you for contributing to gt! To make this process easier for everyone, please explain the context and purpose of your contribution. Also, list the changes made to the existing code or documentation.

This PR adds "as_grob" to gt. This allows converting a gt table to a native grob. preserving a lot of the aesthetics that are found in html. The benefit is that now the table could be saved directly as a png, without having to round-trip through webshot2.

additionally, this solves #961, making it work nicely with patchwork and cowplot.

More testing and features may be needed to add parity to html functionality, but it does a good chunk at this point.

Related GitHub Issues and PRs

Checklist

@thebioengineer
Copy link
Collaborator Author

Related also to this issue in patchwork: #thomasp85/patchwork/issues/203
@thomasp85 - I do have some questions about how we could get it to potentially do add information to allow the table to alignment with axis lables in a ggplot, but for now this seems to get the job done.

@jthomasmock - tagging for knowledge

@thebioengineer
Copy link
Collaborator Author

Realized there is no documentation. The new function is 'as_grob', call it on a gt table and it will be converted.

Still some to-dos exist, like making footnotes and supporting in-cell ggplots

@thomasp85
Copy link

Amazing - I was planning on haggling this in the autumn so this PR is a blessing

Let me have a deeper look at the PR and see if I can suggest ways to align with ticks but I'm afraid it won't be easy (or at least non-hacky)

@thebioengineer
Copy link
Collaborator Author

Good to hear that it this could be helpful for you, @thomasp85. Yeah, any help is appreciated, my experience with grid is pretty limited, so I did a lot of guess/check when making this and trying to make reasonable decisions. If you have any questions on what and why I did something happy to talk more.

Comment on lines +162 to +163
height <- font_size/9 * cell_rows
width <- max(cell_nchar,1)/column_span

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why you are guessing here and not defering this to when the gross are constructed and you can ask grid what their dimensions are?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None other than I wasn't sure how to do it. If we can easily determine the size of the grobs going in, then I would happily prefer that to trying to calculate it myself

Comment on lines +184 to +192
cell_width_units <- function(x){
convertX(
unit(
(x * (1 + (1/(x + 3)))) / 63,
"strwidth",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 "
),"npc"
)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This confuses me 😬 What is the purpose of this function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to get an estimate for the average character width, then have a scaling factor to pad around the cells. Then I convert it to npc to the table can scale. it is using the derived character width from the prior comment. If we can do away with this, I would prefer it.

Comment on lines +258 to +262
font = "sans",
color = table_font_color,
size = 16,
align = "center",
v_align = "middle",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all styles not modifiable with gt? or is the font, size, and alignment really hardcoded?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the alignment for the "header" of the table (Title and subtitle). The goal is to make them completely customizable like the HTML output. but I was setting them for now to get it to work reasonably. I can look more closely at the code @rich-iannone wrote for html and see how to apply that same sort of logic here.

@thomasp85
Copy link

I've read through the code somewhat, but I'm not deeply familiar with gt at the moments so some of the comments might not make sense.

I think I find the order of operations a bit awkward compared to how I would have chosen to implement it but again there might be very valid reasons for this - would it be possible for you to outline the rendering process a bit with words etc to inform me of your thoughts...

To give an example I think I would naively start by creating a grob of every cell and placing it in a matrix, and then, based on that matrix resolve the width and height of each column and row respectively, then afterwards add surrounding elements to the body of the table...

@thebioengineer
Copy link
Collaborator Author

Thanks for your comments, @thomasp85. They are well taken, and I can add some comments/information around.

I think I find the order of operations a bit awkward compared to how I would have chosen to implement it but again there might be very valid reasons for this - would it be possible for you to outline the rendering process a bit with words etc to inform me of your thoughts...

A lot of what the code is doing is based on how other gt output renderers work. Which is sections of the table are created and then put together into the final output. I liked this approach when I helped with word output, so I kept it here to try to keep it consistent.

The base function behind a lot of this on the creation of the table is the table_cell_grob - which takes in text, and a variety of descriptions of the cell (text, font, background color, text color, column and row spans, etc). This should have most of the things we are looking for. Then we iterate over the gt_tbl sections to create the content to be added. First, the "header" gets created (title & subtitle), then the column labels (including row spans), the body of the table, footer, then finally source notes.

Once we have all the table components (which are contained inside lists), we construct the gtable to slot in the grobs into. I do a quick search across the incoming grobs to define for each row what the tallest grob will be and for each column the widest and set gtable dimensions to that. I determine height based on the text rows in the cell, and width based on the maximum number of characters in a text row. As you pointed out above, we could extract the grob dims, I just didnt know we could or how.

Finally I insert the grobs into the gtable entries based on their set column, row, and spans(if any).

Based on your comment, we had a similar thought on constructing a grob for every cell, but the rest is shaped based on trying to be consistent with how other rendering functions behave and the builder/helper functions from gt.

@teunbrand teunbrand mentioned this pull request Feb 1, 2024
3 tasks
@rich-iannone
Copy link
Member

Thanks for the contribution here but going to close the PR as we have this feature now with #1563.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants