{"id":3048,"date":"2023-05-06T15:11:52","date_gmt":"2023-05-06T15:11:52","guid":{"rendered":"http:\/\/optimumsportsperformance.com\/blog\/?p=3048"},"modified":"2023-05-06T15:11:52","modified_gmt":"2023-05-06T15:11:52","slug":"displaying-tables-plots-together","status":"publish","type":"post","link":"https:\/\/optimumsportsperformance.com\/blog\/displaying-tables-plots-together\/","title":{"rendered":"Displaying Tables &#038; Plots Together"},"content":{"rendered":"<p>A common question that I get asked is for a simple way of displaying tables and plots together in the same one-page report. Most in the sport science space that are new to R will copy and paste their plot and table outputs into a word document and then share that with their colleagues. But, this creates extra work &#8212; copying, pasting, making sure you don&#8217;t mess up and forget to paste the latest plot, etc. So, today&#8217;s blog article will walk through a really easy way to create a single page document for combining tables and plots into a single report, which you can save to PDF or jpeg directly from RStudio. This same approach is also useful for researchers looking to combine tables and plots into a single figure for publication. I&#8217;ll show how to do this using both <strong>ggarange()<\/strong> and {<strong>patchwork<\/strong>}.<\/p>\n<p>As always, the full code is available on my <strong><span style=\"color: #0000ff;\"><a style=\"color: #0000ff;\" href=\"https:\/\/github.com\/pw2\/R-Tips-Tricks\/blob\/master\/Displaying%20Tables%20%26%20Plots%20Together.R\">GITHUB page<\/a><\/span><\/strong>.<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Load Libraries and Set a Plotting Theme<\/strong><\/span><\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n### Load libraries\r\nlibrary(tidyverse)\r\nlibrary(ggpubr)\r\nlibrary(gridExtra)\r\nlibrary(patchwork)\r\nlibrary(broom)\r\nlibrary(palmerpenguins)\r\n\r\n## set plot theme\r\ntheme_set(theme_classic() +\r\n            theme(axis.text = element_text(size = 11, face = &quot;bold&quot;),\r\n                  axis.title = element_text(size = 13, face = &quot;bold&quot;),\r\n                  plot.title = element_text(size = 15),\r\n                  legend.position = &quot;top&quot;))\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Load Data<\/strong><\/span><\/p>\n<p>We will use the {<strong>palmerpenguins<\/strong>} data that is freely available in R.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n## load data\r\ndata(&quot;penguins&quot;)\r\nd &lt;- penguins %&gt;%\r\n  na.omit()\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Build the Plots &amp; Table<\/strong><\/span><\/p>\n<p>First we will build our plots. We are going to create two plots and one table. The table will store the information from a linear regression which regresses bill length on flipper length and penguin sex. The plots will be our visualization of these relationships.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n## Create Plots\r\nplt1 &lt;- d %&gt;%\r\n  ggplot(aes(x = flipper_length_mm, y = bill_length_mm)) +\r\n  geom_point(aes(fill = sex),\r\n             size = 4,\r\n             shape = 21,\r\n             color = &quot;black&quot;,\r\n             alpha = 0.5) +\r\n  geom_smooth(method = &quot;lm&quot;,\r\n              aes(color = sex)) +\r\n  scale_fill_manual(values = c(&quot;female&quot; = &quot;green&quot;, &quot;male&quot; = &quot;blue&quot;)) +\r\n  scale_color_manual(values = c(&quot;female&quot; = &quot;green&quot;, &quot;male&quot; = &quot;blue&quot;)) +\r\n  labs(x = &quot;Flipper Length (mm)&quot;,\r\n       y = &quot;Bill Length (mm)&quot;,\r\n       title = &quot;Bill Length ~ Flipper Length&quot;)\r\n\r\n\r\nplt2 &lt;- d %&gt;%\r\n  ggplot(aes(x = sex, y = bill_length_mm)) +\r\n  geom_violin(alpha = 0.5,\r\n              aes(fill = sex)) +\r\n  geom_boxplot(width = 0.2) +\r\n  geom_jitter(alpha = 0.5) +\r\n  labs(x = &quot;Sex&quot;,\r\n       y = &quot;Bill Length (mm)&quot;,\r\n       title = &quot;Bill Length Conditional on Penguin Gender&quot;)\r\n\r\n\r\n## Create table\r\nfit &lt;- d %&gt;%\r\n  lm(bill_length_mm ~ flipper_length_mm + sex, data = .) %&gt;%\r\n  tidy() %&gt;%\r\n  mutate(across(.cols = estimate:statistic,\r\n                ~round(.x, 3)),\r\n         term = case_when(term == &quot;(Intercept)&quot; ~ &quot;Intercept&quot;,\r\n                          term == &quot;flipper_length_mm&quot; ~ &quot;Flipper Length (mm)&quot;,\r\n                          term == &quot;sexmale&quot; ~ &quot;Male&quot;))\r\n\r\n<\/pre>\n<p><span style=\"text-decoration: underline;\"><strong>Convert the table into a ggtextable format<\/strong><\/span><\/p>\n<p>Right now the table is in a tibble\/data frame format. To get it into a format that is usable within the display grid we will convert it to a <strong>ggtextable<\/strong> and use some styling to make it look pretty.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n## Build table into a nice ggtextable() to visualize it\r\ntbl &lt;- ggtexttable(fit, rows = NULL, theme = ttheme(&quot;blank&quot;)) %&gt;%\r\n  tab_add_hline(at.row = 1:2, row.side = &quot;top&quot;, linewidth = 2) %&gt;%\r\n  tab_add_hline(at.row = 4, row.side = &quot;bottom&quot;, linewidth = 3, linetype = 1)\r\n<\/pre>\n<p><span style=\"text-decoration: underline;\"><strong>Display the Table and Plots using ggarrange<\/strong><\/span><\/p>\n<p>We simply add our plot and table elements to the ggarrange() function and get a nice looking report.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n## Plots &amp; Table together using ggarange()\r\nggarrange(plt1, plt2, tbl,\r\n          ncol = 2, nrow = 2)\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-3049\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1024x608.png\" alt=\"\" width=\"625\" height=\"371\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1024x608.png 1024w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-300x178.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-768x456.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-624x370.png 624w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Display the Table and Plots using patchwork<br \/>\n<\/strong><\/span><\/p>\n<p>We can accomplish the same goal using the {<strong>patchwork<\/strong>} package. The only trick here is that we can&#8217;t pass a ggarrange element into patchwork. We need to convert the table into a <strong>tableGrob()<\/strong> to make this work. A <strong>tableGrob()<\/strong> is simple a way for us to capture all of the information that is required for the table structure we&#8217;d like. Also note that we can pass the same <strong>tableGrob()<\/strong> into ggarrange above and it will work.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n## Plots &amp; Table together using patchwork\r\n# Need to build the table as a tableGrob() instead of ggtextable\r\n# to make it work with patch work\r\ntbl2 &lt;- tableGrob(fit, rows = NULL, theme = ttheme(&quot;blank&quot;)) %&gt;%\r\n  tab_add_hline(at.row = 1:2, row.side = &quot;top&quot;, linewidth = 2) %&gt;%\r\n  tab_add_hline(at.row = 4, row.side = &quot;bottom&quot;, linewidth = 3, linetype = 1)\r\n<\/pre>\n<p>Now we wrap the <strong>tableGrob <\/strong>and our plots into the <strong>wrap_plots() <\/strong>function and we are all set!<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n# now visualize together\r\nwrap_plots(plt1, plt2, tbl2, \r\n           ncol = 2,\r\n           nrow = 2)\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-3050\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1-1024x608.png\" alt=\"\" width=\"625\" height=\"371\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1-1024x608.png 1024w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1-300x178.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1-768x456.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-06-at-7.34.50-AM-1-624x370.png 624w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Wrapping Up<\/strong><\/span><\/p>\n<p>Instead of copying and pasting tables and plots into word, try using these two simple approaches to creating a single report page that stores all of the necessary information that you colleagues need to see!<\/p>\n<p>All of the code is available on my <span style=\"color: #0000ff;\"><strong><a style=\"color: #0000ff;\" href=\"https:\/\/github.com\/pw2\/R-Tips-Tricks\/blob\/master\/Displaying%20Tables%20%26%20Plots%20Together.R\">GITHUB page<\/a><\/strong><\/span>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A common question that I get asked is for a simple way of displaying tables and plots together in the same one-page report. Most in the sport science space that are new to R will copy and paste their plot and table outputs into a word document and then share that with their colleagues. But, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[45,43,42],"tags":[],"class_list":["post-3048","post","type-post","status-publish","format-standard","hentry","category-r-tips-tricks","category-sports-analytics","category-sports-science"],"_links":{"self":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts\/3048","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/comments?post=3048"}],"version-history":[{"count":1,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts\/3048\/revisions"}],"predecessor-version":[{"id":3051,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts\/3048\/revisions\/3051"}],"wp:attachment":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/media?parent=3048"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/categories?post=3048"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/tags?post=3048"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}