title: How to create weighted, labelled summary tables for both html and pdf?
body: <p>I'd like to create large crosstables with summary statistics of multiple row variables by multiple column variables - and found two packages that make it very easy to beautiful large tables: the <code>tables</code> package by Duncan Murdoch and the <code>expss</code> package by Gregory Demin (which does amazing things beside tables). There are some other packages, as <code>moonBook</code> (which works together with <code>ztable</code> package by the same author), but as far as I saw most of them lack something I need:</p>
  
  <p>I want to ... </p>
  
  <ol>
  <li>(reproducibly) create large summary tables</li>
  <li>use case weights for these summary statistics</li>
  <li>use variable and value labels for the variables</li>
  <li>create both html and pdf tables without too much effort (w/o changing function options/chunk options).</li>
  </ol>
  
  <p>ad 1) Both <code>tables</code> and <code>expss</code> make it easy to create complex tables with multiple row and col vars. As an example we produce a summary table of the iris data with <code>tables</code> and the table functions in <code>expss</code>. </p>
  
  <pre><code>library(magrittr)  # Pipes %&gt;% 
  
  data(iris)  # Use iris data for examples
  
  ## Tables with the `tables` packages
  library(tables)
  tabular( (Species + 1) ~ (n=1) + Format(digits=2)*(Sepal.Length + Sepal.Width)*(mean + sd + Format(digits=0)*(n=1)), data=iris )
  
  ## Tables with the `expss` package
  library(expss)
  iris %&gt;%
    tab_cells(Sepal.Length, Sepal.Width) %&gt;% 
    tab_cols(Species, total()) %&gt;% 
    tab_stat_mean_sd_n() %&gt;% 
    tab_transpose() %&gt;% 
    tab_pivot() 
  </code></pre>
  
  <p>ad 2) With <code>expss</code> it's easy to use labels</p>
  
  <pre><code>iris_raw &lt;- iris  # Save iris for later without any labels (they cause some problems with tabular)
  
  iris &lt;- apply_labels(iris,
                       Sepal.Length = "Sepal Length",
                       Sepal.Width = "Sepal With",
                       Species = "Species of Iris", 
                       Species = c("Setosa" = "setosa",
                                   "Versicolor" = "versicolor",
                                   "Virginica" = "virginica"))
  str(iris)  # we can see the labels
  
  library(expss)
  expss_digits(digits = 2)
  iris %&gt;%
    tab_cells(Sepal.Length, Sepal.Width) %&gt;% 
    tab_cols(Species, total()) %&gt;% 
    tab_stat_mean_sd_n() %&gt;% 
    tab_transpose() %&gt;% 
    tab_pivot()
  </code></pre>
  
  <p>ad 3) For surveys we often need case weights, e.g. sampling design weights, nonresponse weights, post-stratification weights - that determine how much weight a single case has in the computation of descriptive statistics and in for model estimation. <code>expss</code> makes it possible to use case weights just by adding one single line: <code>tab_weight(caseweight)</code></p>
  
  <pre><code>set.seed(123)  # Make following random numbers reproducible
  iris$caseweight &lt;- rnorm(nrow(iris), mean = 1, sd = .5) %&gt;% abs() # Add some positive random caseweight to each case
  
  library(expss)
  expss_digits(digits = 2)
  iris %&gt;%
    tab_cells(Sepal.Length, Sepal.Width) %&gt;% 
    tab_cols(Species, total()) %&gt;% 
    tab_weight(caseweight) %&gt;%  # Weight the cases
    tab_stat_mean_sd_n(weighted_valid_n = TRUE) %&gt;% 
    tab_last_round(digits = 2) %&gt;% 
    tab_transpose() %&gt;% 
    tab_pivot() 
  </code></pre>
  
  <p>In <code>tables</code> it's also possible to use (custom) functions for calculating weighted summary statistics, but not as easy as with <code>expss</code> (I might be wrong here - if that's the case, please correct me). </p>
  
  <p>ad 4) Coming to the last point of my wishlist: both html and pdf tables. Now that's easy with <code>tables</code> and much harder with <code>expss</code>. In <code>tables</code> the function <code>toKable()</code> and piping the output to the <code>kableExtra</code> for further refinement is the key.</p>
  
  <pre><code>library(tables)
  tab &lt;- tabular( (Species + 1) ~ (n=1) + Format(digits=2)*(Sepal.Length + Sepal.Width)*(mean + sd + Format(digits=0)*(n=1)), data=iris_raw)
  tab %&gt;% 
    toKable() %&gt;%  # Translates the tabular-object to a kable-object
    kable_styling(full_width = TRUE) %&gt;%  # Functions from kableExtra
    column_spec(2, color = "red")
  
  
  # Remark: in expss it's possible to transform the (html-) table output to a data frame via `split_table_to_df()`, s. https://stackoverflow.com/questions/55542838/formatting-tables-in-r-markdown-to-export-to-ms-word-document/55576202#55576202
  # But all the formatting gets lost - since it's just a df then.
  
  library(expss)
  expss_digits(digits = 2)
  tab &lt;- iris %&gt;%
    tab_cells(Sepal.Length, Sepal.Width) %&gt;% 
    tab_cols(Species, total()) %&gt;% 
    tab_stat_mean_sd_n() %&gt;% 
    tab_transpose() %&gt;% 
    tab_pivot()
  
  tab.df &lt;- split_table_to_df(tab)  # Here the table 
  str(tab.df)  # a df with the numbers and the labels
  kable(tab.df)  # We could use kable on this (but the result does not look like a usual kable table) 
  </code></pre>
  
  <p>So each of the two packages has its superpowers: <code>expss</code> does an amazing job in creating tables with labels and case weights and <code>tables</code> makes it easy to use the table output from <code>tabular()</code> to create both html and pdf tables via via <code>toKable</code>, kable and kableExtra - and because the <code>kableExtra</code> package by Hao Zhu produces html or pdf depending on the type of document that gets knit - that's really simple, without changing any code (e.g. from "html" to "latex"), just by pressing <code>Knit to</code> pdf/html -- and that works perfectly well.</p>
  
  <p><a href="https://i.stack.imgur.com/iu6Af.png" rel="nofollow noreferrer">the rendered table for html</a></p>
  
  <p><a href="https://i.stack.imgur.com/l5kij.png" rel="nofollow noreferrer">the rendered table in the pdf</a></p>
  
  <p><strong>Question</strong>: For an easy reproducible workflow it would be great to have all these features (1 to 4) at once and thus to combine <code>expss</code> with <code>knitrExtra</code> - are there any functions like <code>toKable</code> for tables from expss (or more general for html tables) that would make a refinement via <code>kableExtra</code> and easy html and pdf export without changing any options possible? Or are there other workflows to achieve 1 to 4? Thanks for your time and any hint!</p>