如何将响应计数的DataFrame展开为响应记录的DataFrame?
将计数聚合的DataFrame展开为原始响应记录
我需要把包含不同响应计数的DataFrame,转换为每条记录对应一个实际响应的格式,替代当前的聚合计数形式。
示例数据
set.seed(44) data <- data.frame(ID = LETTERS[1:5] , Count_1 = sample(c(3:8), 5) , Count_2 = sample(c(3:8), 5) , Count_3 = sample(c(3:8), 5))
数据结构:
ID Count_1 Count_2 Count_3 1 A 3 8 3 2 B 8 7 4 3 C 7 4 8 4 D 4 3 5 5 E 5 5 6
期望结果
展开后每条记录对应单个响应,示例片段如下:
ID Response 1 A 1 2 A 1 3 A 1 4 B 1 5 B 1 ... 79 E 2 80 E 2
原本计划用for循环逐列生成重复向量,但想找更高效的实现方式。
解决方案
1. 使用tidyverse工具链(简洁高效)
先通过pivot_longer将宽表转为窄表,再用uncount根据计数值展开记录:
library(tidyverse) # 转换为窄表,提取响应编号 long_df <- data %>% pivot_longer( cols = starts_with("Count_"), names_to = "Response", names_prefix = "Count_", values_to = "Count" ) # 按Count值展开记录 expanded_df <- long_df %>% uncount(Count) %>% select(ID, Response) # 查看结果 head(expanded_df, 30)
2. Base R实现(无需额外包)
通过转置和重复序列生成完成展开:
# 提取响应编号 response_ids <- sub("Count_", "", colnames(data)[-1]) # 生成每个响应组的展开数据 expanded_list <- lapply(seq_along(response_ids), function(i) { counts <- data[[i + 1]] data.frame( ID = rep(data$ID, counts), Response = rep(response_ids[i], sum(counts)) ) }) # 合并所有组 expanded_df <- do.call(rbind, expanded_list) # 查看结果 head(expanded_df, 30)
两种方法都能避免手动循环的低效,tidyverse写法更直观,Base R则适合不想加载额外包的场景。
内容的提问来源于stack exchange,提问作者JLC
相关产品推荐
相关产品推荐

