R语言:基于二进制列生成标记值为1的列名的新列集合
解决方案:提取每行取值为1的列名生成新列
你有一个包含0/1二进制列的数据框,需要为每行生成若干path_*列,依次记录该行中值为1的原始列名,无对应值则为空。先看你的输入数据:
df <- data.frame(ID = c(1, 2, 3), `1_0_1_0` = c(1, 0, 0), `1_0_0_0` = c(0, 0, 1), `2_0_1_0` = c(1, 1, 0), `2_0_3_0` = c(0, 0, 0), check.names = FALSE)
对应的期望输出示例:
ID path_1 path_2 1 1 1_0_1_0 2_0_1_0 2 2 2_0_1_0 3 3 1_0_0_0
下面提供两种可行的实现方法:
方法1:Base R 实现
通过遍历每行筛选目标列名,再整理成对应格式:
# 提取所有二进制列(排除ID列) binary_cols <- setdiff(names(df), "ID") # 逐行获取值为1的列名 path_list <- apply(df[binary_cols], 1, function(x) names(x[x == 1])) # 确定需要生成的path列最大数量 max_paths <- max(sapply(path_list, length)) # 将列表转换为数据框,空位置补空字符 path_df <- do.call(rbind, lapply(path_list, function(x) { length(x) <- max_paths x[is.na(x)] <- "" x })) # 重命名path列 colnames(path_df) <- paste0("path_", 1:max_paths) # 合并原ID列与新生成的path列 result <- cbind(df["ID"], path_df) # 查看结果 print(result)
方法2:tidyverse 实现
用管道式操作完成长格式与宽格式的转换:
library(dplyr) library(tidyr) result <- df %>% # 将二进制列转为长格式 pivot_longer(cols = -ID, names_to = "col_name", values_to = "value") %>% # 筛选值为1的记录 filter(value == 1) %>% # 按ID分组,为每个分组内的列名添加序号 group_by(ID) %>% mutate(path_num = paste0("path_", row_number())) %>% ungroup() %>% # 转回宽格式,空值填充"" pivot_wider(id_cols = ID, names_from = path_num, values_from = col_name, values_fill = "") %>% # 确保所有原始ID都被保留 right_join(df["ID"], by = "ID") %>% # 按ID排序 arrange(ID) print(result)
内容的提问来源于stack exchange,提问作者ltong
相关产品推荐
相关产品推荐

