Search code examples
rtidyverseexpss

Add row in etable from expss R package


I want to add rows at specific place to expss output etable. I did that with some brute force method which always add the row at the start of etable. Any method to add rows at specific place.

library(tidyverse)
library(expss)

test1 <-
    mtcars %>% 
    tab_cells(cyl) %>% 
    tab_cols(vs) %>% 
    tab_stat_cpct() %>% 
    tab_pivot()

test1 %>% 
  tibble() %>% 
  tibble::add_row(.data = tibble("", test1[2, -1]/test1[1, -1]*100) %>% 
            set_names(names(test1))
          , .before = 3)

Solution

  • Solution based on @caldwellst code but with automatic ratio calculation:

    insert_ratio <- function(tbl, where) {
        if(is.character(where)) {
            # if where is character we search it in the rowlabels
            where = grep(where, tbl[[1]], fixed = TRUE)[1]
        }
        isTRUE(where>1) || stop("'where' should be greater than 1 for ratio calculation.")
        isTRUE(where<=NROW(tbl)) || stop("'where' should be less or equal than number of rows in the table.")
        tbl1 <- tbl[1:where,]
        to_insert = c(row_labels = tbl[[1]][where], tbl[where, -1]/tbl[where - 1, -1]*100)
        tbl2 <- tbl[(where+1):nrow(tbl),]
        tbl1 %>%
            add_rows(to_insert) %>%
            add_rows(tbl2)
    }
    
    insert_ratio(test1, 2)
     # |     |              |    vs |      |
     # |     |              |     0 |    1 |
     # | --- | ------------ | ----- | ---- |
     # | cyl |            4 |   5.6 | 71.4 |
     # |     |            6 |  16.7 | 28.6 |
     # |     |              | 300.0 | 40.0 |
     # |     |            8 |  77.8 |      |
     # |     | #Total cases |  18.0 | 14.0 |
    
    insert_ratio(test1, "cyl|6")
     # the same result
    

    UPDATE Ratio calculation is moved to separate function:

    ratio = function(tbl, where, label = NULL){
        if(is.character(where)) {
            # if where is character we search it in the rowlabels
            where = grep(where, tbl[[1]], fixed = TRUE)[1]
        }
        isTRUE(where>1) || stop("'where' should be greater than 1 for ratio calculation.")
        isTRUE(where<=NROW(tbl)) || stop("'where' should be less or equal than number of rows in the table.")
        
        if(is.null(label)) label = tbl[[1]][where]
        c(row_labels = label, tbl[where, -1]/tbl[where - 1, -1]*100)
    }
    
    insert_row = function(tbl, where, row) {
        if(is.character(where)) {
            # if where is character we search it in the rowlabels
            where = grep(where, tbl[[1]], fixed = TRUE)[1]
        }
        isTRUE(where<=NROW(tbl)) || stop("'where' should be less or equal than number of rows in the table.")
        first_part = seq_len(where)
        tbl1 <- tbl[first_part,]
        
        tbl2 <- tbl[-first_part,]
        tbl1 %>%
            add_rows(row) %>%
            add_rows(tbl2)
    }
    
    insert_row(test1, 2, ratio(test1, 2))
    insert_row(test1, "cyl|6", ratio(test1, "cyl|6"))