R语言中将长格式dataframe转换为0-1二元存在性dataframe
R语言长表转0-1宽表实现方法
需求说明
现有长格式数据框,每一行对应「分组-名称」的从属关系,需要转换为以名称为行、分组为列的宽表,单元格值为1代表对应名称属于该分组,0代表不属于。
原始数据结构示例:
| Groups | Names |
|---|---|
| G1 | SP1 |
| G1 | SP2 |
| G1 | SP3 |
| G2 | SP1 |
| G2 | SP4 |
| G3 | SP2 |
| G3 | SP1 |
目标输出结构:
| Names | G1 | G2 | G3 |
|---|---|---|---|
| SP1 | 1 | 1 | 1 |
| SP2 | 1 | 0 | 1 |
| SP3 | 1 | 0 | 0 |
| SP4 | 0 | 1 | 0 |
实现代码
首先加载原始测试数据:
df <- structure(list(Groups = c("G1", "G1", "G1", "G2", "G2", "G3", "G3"), Names = c("SP1", "SP2", "SP3", "SP1", "SP4", "SP2", "SP1" )), class = "data.frame", row.names = c(NA, -7L))
方法1:基础R实现(无需安装任何包)
直接用R内置的交叉表函数table()统计组合出现次数,由于每个组合最多出现1次,统计结果天然就是0/1值:
# 生成交叉频数表 cross_tab <- table(df$Names, df$Groups) # 转为数据框,重置行名 res <- as.data.frame.matrix(cross_tab) res <- cbind(Names = rownames(res), res) rownames(res) <- NULL
方法2:tidyverse流程实现(适合日常用dplyr处理数据的场景)
通过pivot_wider完成长转宽,缺失的组合自动填充0:
library(dplyr) library(tidyr) res <- df %>% mutate(flag = 1) %>% # 给存在的组合打存在标记 pivot_wider( names_from = Groups, values_from = flag, values_fill = 0 # 不存在的组合填0 ) %>% arrange(Names) # 按名称排序对齐示例输出
方法3:data.table实现(适合百万级以上大数据量场景)
用dcast函数做长转宽,运算速度远高于前两种方法:
library(data.table) setDT(df) res <- dcast( df, Names ~ Groups, fun.aggregate = length, # 统计出现次数 fill = 0 # 未出现的组合填0 )
结果验证
运行上述任意一种方法,输出结果均与目标格式完全一致:
> print(res) Names G1 G2 G3 1 SP1 1 1 1 2 SP2 1 0 1 3 SP3 1 0 0 4 SP4 0 1 0
内容的提问来源于stack exchange,提问作者chippycentra
相关产品推荐
相关产品推荐

