Skip to content

Instantly share code, notes, and snippets.

@mathzero
Last active February 19, 2021 11:30
Show Gist options
  • Save mathzero/93bed2b1a9646448a7e2565b34099c81 to your computer and use it in GitHub Desktop.
Save mathzero/93bed2b1a9646448a7e2565b34099c81 to your computer and use it in GitHub Desktop.
Three functions to create table ones / simple cross tabs in R
#### 1. Cross tab function
# Simple cross-tab function, with %s
# Creates a cross tab of categorical variables, with %s in brackets after the number
# You can specify the names of the levels within the variables if you want, or leave blank to use the existing names
# (Be sure to enter the level names in the right order if you do specify them)
crossTab <- function(dat = dfRes, rowvar, colvar, rowvar_levels = NULL,colvar_levels = NULL){
tab <- addmargins(table(pull(dat,rowvar), pull(dat,colvar))) %>% as.data.frame.matrix()
tab.prop <- round(100*prop.table(table(pull(dat,rowvar), pull(dat,colvar)),1),1) %>% as.data.frame.matrix()
for (i in 1:(nrow(tab)-1)){
for(j in 1:(ncol(tab)-1)){
tab[i,j] <- paste0(tab[i,j], " (",tab.prop[i,j],"%)")
}
}
for(j in 1:ncol(tab)){
prop <- round(100*(as.numeric(tab[nrow(tab),j]) / as.numeric(tab[nrow(tab),ncol(tab)])),1)
tab[nrow(tab),j] <- paste0(tab[nrow(tab),j], " (",prop,"%)")
}
if(!is.null(rowvar_levels)){
colnames(tab)[ncol(tab)] <- "Total"
tab$Category <- c(rowvar_levels, "Total")
}
else{
tab$Category <- rownames(tab)
}
if(!is.null(colvar_levels)){
colnames(tab) <- c(colvar_levels,"Total")
}
tab <- tab %>% dplyr::select(Category, everything())
return(tab)
}
#### 2. Function to do x-tab for contiuous variables
# as above, but for continuous variables. Output will be numbers and rowwise percentages in brackets
crossTabContinuous <- function(dat = dfRes, rowvar, colvar, colvar_levels = NULL){
means <- (round(by(pull(dat, rowvar),pull(dat, colvar), mean),2)) %>% as.table()%>% as.data.frame()
sds <- unlist(round(by(pull(dat, rowvar),pull(dat, colvar), sd),2))%>% as.table()%>% as.data.frame()
names(means) <- c("Category", "mean")
names(sds) <- c("Category","sd")
uniques <- unique(pull(dat, colvar))[!is.na(unique(pull(dat, colvar)))] %>% as.character()
tab <- data.frame(matrix(nrow = 1, ncol=1+length(uniques),dimnames = list(NULL,c("Category", uniques))))
names(tab)[c(2:ncol(tab))] <- uniques
tab$Category <- "Mean (SD)"
for (x in 1:length(uniques)){
tab[1,colnames(tab)==uniques[[x]]] <- paste0(means[means$Category == uniques[[x]],]$mean,
" (",
sds[sds$Category == uniques[[x]],]$sd,")")
}
tab$Sum = paste0(round(mean(pull(dat, rowvar)),2), " (",round(sd(pull(dat, rowvar)),2),")")
# tab$Variable = rowva
return(tab)
}
#
### 3. Generalise the xtab functions to do multiple covariates at once
# This function combines the two above functions to create cross-tabs from a list of covariates.
# Rowvar list should be a list of the names of the variables that you want to appear as your rows in the table,
# then convar is your column stratifying variable. If you want your
crossTabMulti <- function(dat = dfRes, rowvar_list, colvar, cov_name_list=cov_name_list){
res_list <- list()
for (i in 1:length(rowvar_list)){
if(class(pull(dat, rowvar_list[[i]])) %in% c("integer", "numeric")){
res <- crossTabContinuous(dat = dat,rowvar = rowvar_list[[i]], colvar = colvar)
}else{
res <- crossTab(dat = dat,rowvar = rowvar_list[[i]], colvar = colvar)
}
res_list[[i]] <- res
}
if(!is.null(cov_name_list)){
names(res_list) <- cov_name_list[rowvar_list]
}else{
names(res_list) <- rowvar_list
}
out <- dplyr::bind_rows(res_list, .id = "Variable") %>% filter(Category != "Sum") %>%
rename(`Sum / mean(SD)`=Sum)
return(out)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment