如何用通用for循环生成数据框所有可能的双向列联表?
如何遍历数据框生成所有双向列联表?
问题说明
我需要遍历一个全为分类/二元因子变量的数据框,生成所有可能的双向列联表,期望效果和手动编写table(df$amazon, df$age)这类语句完全一致,但尝试的两段代码都没达到预期。
示例数据框
amazon <- c(0,1,0,1,1) age <- c(1,2,4,3,0) income <- c(1,1,1,0,0) delivery <- c(1,2,0,3,4) manhattan <- c("Manhattan", "Other", "Manhattan", "Other", "Manhattan") df <- data.frame(cbind(amazon, age, income, delivery, manhattan)) df <- df %>% mutate(across(everything(), as.factor))
尝试过的无效代码
第一段代码(结果被合并成一个数据框,丢失独立列联表结构):
results <- data.frame() for(i in 1:(ncol(df))){ for(j in (i+1):ncol(df)){ table <- table(df[,i], df[,j], useNA = "ifany") results <- rbind(results,ftable(round(prop.table(table),3))) } }
第二段代码(函数逻辑存在变量未定义问题):
make_p_tab <- function(x) { col_df <- df %>% dplyr::select(var1, all_of(x)) %>% filter(!is.na(x)) %>% table() %>% prop.table(.,1) } to_do <- function(df){ colnames(df) } food_xtab <- map(to_do, make_p_tab)
解决方案
方法1:改进for循环,保留独立列联表
把每个列联表存入列表,同时可直接打印输出,完全还原手动执行的效果:
# 创建列表存储所有列联表,方便后续调用 table_list <- list() current_index <- 1 for(i in 1:(ncol(df))){ for(j in (i+1):ncol(df)){ # 获取变量名,方便识别对应关系 var1 <- colnames(df)[i] var2 <- colnames(df)[j] # 生成双向列联表 cross_tab <- table(df[[var1]], df[[var2]], useNA = "ifany") # 给列联表设置变量名标签 dimnames(cross_tab) <- list(var1, var2) # 存入列表 table_list[[current_index]] <- cross_tab # 直接打印输出,和手动执行效果一致 cat("=== 列联表:", var1, " VS ", var2, " ===\n") print(cross_tab) cat("\n") current_index <- current_index + 1 } } # 后续需要调用某张表时,直接用列表索引,比如取第1张表 # table_list[[1]]
方法2:用purrr批量生成(更简洁)
先生成所有不重复的变量对,再批量生成列联表:
library(purrr) library(dplyr) # 生成所有不重复的变量组合(避免重复生成A-B和B-A的表) var_pairs <- combn(colnames(df), 2, simplify = FALSE) # 定义生成列联表的函数 make_crosstab <- function(pair) { table(df[[pair[1]]], df[[pair[2]]], useNA = "ifany") } # 批量生成所有列联表并存储 all_tables <- map(var_pairs, make_crosstab) # 给列表元素命名,方便识别 names(all_tables) <- map_chr(var_pairs, ~paste(.x[1], "VS", .x[2])) # 逐个打印所有结果 walk2(all_tables, names(all_tables), function(tab, name) { cat("=== ", name, " ===\n") print(tab) cat("\n") })
补充:生成比例表(行/列比例)
如果需要生成比例表,只需要在生成列联表后加上prop.table即可,比如在方法1的循环中添加:
# 生成行比例表(margin=1代表行,margin=2代表列) prop_tab <- prop.table(cross_tab, margin = 1) cat("=== 行比例表:", var1, " VS ", var2, " ===\n") print(round(prop_tab, 3)) cat("\n")
内容的提问来源于stack exchange,提问作者user1366487
相关产品推荐
相关产品推荐

