table1() and t1kable() Ignoring named level of a factor

Viewed 202

I am trying to use RMarkdown to automatically generate summary tables that are part of reports that get knitted to pdf. I am using table1() to create the initial table, and t1kable() to convert the table for pdf-knitting, and kable_styling() to center the table on the page. Here is my reproducible example:

library(tidyverse)
library(ggplot2)
library(table1)
library(kableExtra)

# Create df for reproducible example
df <- tibble(grad_term = c(rep("Fall '15 to Summer '20", 3), "Spring '12 to Summer '15",rep("Fall '15 to Summer '20", 5), "Spring '12 to Summer '15"),
       enrollment_age = c("23-29", "30-39", rep("23-29",8)),
       gender = c(rep("Male", 6), rep("Female", 2), rep("Male", 2)),
       racial_group = c("2+ groups", rep("White", 7), NA_character_, "White"),
       citizenship_status = c(rep("Since birth", 10))
       ) %>%
  mutate(across(.cols = everything(), ~ factor(.x)))

# Create necessary components of table1() object
labels <- list(
  variables=list(gender="Gender",
                 racial_group="Race/Ethnicity",
                 citizenship_status="Citizenship Status",
                 enrollment_age="Age at Enrollment",
                 grad_term = "Graduation Term"))

strata <- c(list(Total = df))

# Creating my own "render categorical variable" function is necessary to round to 0 decimals
my.render.cat <- function(x) {
  c("", sapply(stats.default(x), function(y) with(y,
      sprintf("%d (%.0f %%)", FREQ, PCT))))
}

# Put it all together and pass through t1kable() for knitting to pdf and kable_styling() for LateX formatting
table1(strata, 
       labels,
       render.categorical = my.render.cat) %>%
  t1kable() %>%
  kable_styling(., latex_options = "hold_position", position = "center")

Here is the result: bad table :(

As you can see, 2 undesired outcomes are happening:

  1. The value "1" is being displayed in the "Citizenship status" row, rather than "Since birth". You can check in the console, that levels(df$citizenship_status) returns [1] "Since birth"

This dataset represents one of ~50 like this; a separate report_driver.R file uses map() to, for each of these 50 groups: filter the large data frame for only those individuals, call droplevels() to only have the factor levels represented inside that group remain, and execute markdown::render(input = "report.Rmd") . The code you see here is what is inside report.Rmd.

Citizenship status, here in this particular group's data frame, is the only time I encounter this "1" issue. It is also the only instance of only one level being present in the filtered data frame (In other words, the other ~49 groups all have multiple levels, such as "Since birth" and "Naturalized" present for citizenship_status, as well as for all the other demographic variables. This one group, with only 10 people, just happens to have all "Since birth").

I have no idea why having only one level present of these factor variables causes this erroneous labeling, but they seem to be 1:1 correlated across my data.

  1. Nearly all levels are rounding with 0 decimal places, except for the Missing row (which corresponds to the NAs). This occurs in any of the other ~50 datasets and automatically generated tables, but only for "Missing"/NA values.

Thus, I have deduced that table1() and possibly kable() in general treat NA values differently, but I am not well-versed enough to "open up the hood" and make any modifications myself.

Please let me know if you can help with either the (1) factor level issue or (2) the rounding of NA rows. Have a great day and thanks so much!

0 Answers
Related