如何在R中用循环或lapply系列函数批量统计数据框两类变量的频数
高效实现主题变量在人口统计变量各水平的频数统计
数据与需求说明
现有如下结构的R数据框,包含人口统计变量(如age、gender,共约17个,水平数3-13)、0-1编码的主题变量(如var1、var2,共约35个),id无实际意义:
age <- c(3,4,3,4,4,5,1) gender <- c(1,1,2,2,1,3,2) var1 <- c(1,0,0,0,0,1,0) var2 <- c(0,0,1,1,1,0,0) id <- c(1:7) df <- data.frame(id, age, gender, var1, var2)
需要将数据处理为各主题变量在各人口统计变量不同水平下的频数统计,目标格式如下:
age1 age3 age4 age5 gender1 gender2 gender3 var1 0 1 0 1 1 0 1 var2 0 1 2 0 1 2 0
现有手动处理方式
目前只能逐个变量手动处理,示例代码如下:
library(data.table) t <- table(df$age, df$var1) dft <- data.frame(t) dft <- subset(dft, dft$Var1 != 0) dft <- dft[,2:3] dft_t <- transpose(dft) age_var1 <- dft_t[2,] colnames(age_var1) <- c("age1", "age3", "age4", "age5") rownames(age_var1) <- c("var1") # 后续需手动处理gender与var1的组合,再cbind;对var2重复全部操作后rbind
优化实现方案
可以利用tidyverse工具链实现批量自动化处理,无需逐个变量手动操作:
完整代码
library(tidyverse) # 定义变量分组:人口统计变量和主题变量 demo_vars <- c("age", "gender") topic_vars <- setdiff(names(df), c("id", demo_vars)) # 批量处理函数 process_demo_topic <- function(demo_var, df, topic_vars) { df %>% select(all_of(c(demo_var, topic_vars))) %>% pivot_longer(cols = all_of(topic_vars), names_to = "topic", values_to = "value") %>% filter(value == 1) %>% count(topic, .data[[demo_var]]) %>% pivot_wider(names_from = .data[[demo_var]], values_from = n, values_fill = 0) %>% rename_with(~ paste0(demo_var, .), -topic) } # 处理所有人口统计变量并合并 result_list <- map(demo_vars, ~ process_demo_topic(.x, df, topic_vars)) final_result <- reduce(result_list, left_join, by = "topic") %>% column_to_rownames("topic") # 查看结果 final_result
运行后输出:
age1 age3 age4 age5 gender1 gender2 gender3 var1 0 1 0 1 1 0 1 var2 0 1 2 0 1 2 0
代码逻辑说明
process_demo_topic函数:针对单个人口统计变量,将主题变量转为长格式,筛选出值为1的记录,统计每个主题在人口变量各水平的频数,再转为宽格式并修改列名为变量名+水平值的格式;map函数:批量遍历所有人口统计变量,生成对应统计结果列表;reduce函数:将多个统计结果按topic列合并,最后将topic转为行名,直接得到目标格式。
如果习惯使用data.table,也可以用类似的批量处理逻辑,核心是利用函数式编程替代手动重复操作,提升效率。
内容的提问来源于stack exchange,提问作者Sointu
相关产品推荐
相关产品推荐

