Search code examples
rgroupingexpss

Add and stack subgroups in a single expss table


A special request this time since a know how to get to my desired table output but would like to know if a less-wordy solution exists with expss. First off, this topic can be considered an extension of this discussion --> Complex tables with expss package, and is also related to this other one --> How to display results from only select subgroups + the whole data frame in an expss table?

My table construct is the following: showing results on total dataframe rows first, then split by subgroups. As of today, below is how I proceed (example with infert dataset):

1) Table template

### Banner set up
my_banner = infert %>%
  tab_cols(total())
my_custom_table = . %>%  
  tab_significance_options(sig_level=0.2, keep="none", sig_labels=NULL, subtable_marks="greater", mode="append") %>%
  tab_stat_cases(label="N", total_row_position="above", total_statistic="u_cases", total_label="TOTAL") %>% 
  tab_stat_cpct(label="%Col.", total_row_position="above", total_statistic="u_cpct", total_label="TOTAL") %>%
  # Parity x Education
  tab_cols(education) %>%
  tab_stat_cases(label="N", total_row_position="above", total_statistic="u_cases", total_label="TOTAL") %>% 
  tab_last_add_sig_labels() %>%
  tab_stat_cpct(label="%Col.", total_row_position="above", total_statistic="u_cpct", total_label="TOTAL") %>%
  tab_last_add_sig_labels() %>%
  tab_last_sig_cpct(label="T.1", compare_type="subtable")

2) Creation of 3 distinct tables (1 for total and 1 for each subgroup), merged into one:

tab1 <- my_banner %>%
  tab_cells(parity) %>%
  my_custom_table() %>%
  tab_pivot(stat_position="inside_columns")
tab2 <- infert %>%
  apply_labels(education="education (CASE 0)") %>%
  tab_cells(parity) %>%
  tab_cols(total(label = "CASE 0")) %>%
  tab_subgroup(case==0) %>%
  my_custom_table() %>%
  tab_pivot(stat_position="inside_columns")
tab3 <- infert %>%
  apply_labels(education="education (CASE 1)") %>%
  tab_cells(parity) %>%
  tab_cols(total(label = "CASE 1")) %>%
  tab_subgroup(case==1) %>%
  my_custom_table() %>%
  tab_pivot(stat_position="inside_columns")

final_tab <- tab1 %merge% tab2 %merge% tab3

All this piece of code only for 1 table, you understand my concern. Any good practice tip to avoid this lengthy (yet working) sequence? My first guess was:

my_banner %>%
  tab_cells(parity) %>%
  my_custom_table() %>%
  tab_subgroup(case==0) %>%
  my_custom_table() %>%
  tab_subgroup(case==1) %>%
  my_custom_table() %>%
  tab_pivot(stat_position="inside_columns")

A table is computed but the output is nowhere near the objective, there is probably a fix but I have no idea where to look for. Any help would be appreciated, thank you! (Note: if a simple solution involves getting rid of #TOTAL columns, it's also fine to me)


Solution

  • The key idea is to use %nest% in the tab_cols instead of tab_subgroup:

    library(expss)
    data(infert)
    my_banner = infert %>%
        apply_labels(
            education = "education",
            case = c(
                "CASE 0" = 0,
                "CASE 1" = 1
            )
        ) %>% 
        tab_cols(total(), education, case %nest% list(total(label = ""), education))
    
    my_custom_table = . %>%  
        tab_significance_options(sig_level=0.2, keep="none", sig_labels=NULL, subtable_marks="greater", mode="append") %>%
        tab_stat_cases(label="N", total_row_position="above", total_statistic="u_cases", total_label="TOTAL") %>% 
        tab_last_add_sig_labels() %>%
        tab_stat_cpct(label="%Col.",
                      total_row_position="above", 
                      total_statistic=c("u_cases", "u_cpct"), 
                      total_label=c("TO_DELETE_TOTAL", "TOTAL")) %>%
        tab_last_add_sig_labels() %>%
        tab_last_sig_cpct(label="T.1", compare_type="subtable") %>% 
        tab_pivot(stat_position="inside_columns") %>% 
        # drop auxilary rows and columns
        where(!grepl("TO_DELETE", row_labels)) %>% 
        except(fixed("Total|T.1"), fixed("CASE 0|T.1"), fixed("CASE 1|T.1"))
    
    my_banner %>% 
        tab_cells(parity) %>% 
        my_custom_table()