如何在R语言中基于值替换并将多列合并为一列
解决方案
针对你的需求,这里提供几种高效的实现方式,都能得到目标df2:
方法一:基础R循环+逐行提取
先将每列的'1'替换为对应列名,再逐行提取非'0'的元素:
# 复制原数据框用于替换操作 df_replaced <- df1 # 遍历每一列,替换'1'为列名 for (col_name in colnames(df_replaced)) { df_replaced[[col_name]][df_replaced[[col_name]] == '1'] <- col_name } # 逐行提取非'0'的元素,生成新列 df2 <- data.frame(fruit = apply(df_replaced, 1, function(row) row[row != '0'])) # 保留原行名 rownames(df2) <- rownames(df1)
方法二:tidyverse 管道式实现
如果你习惯使用tidyverse工具集,这种方式更简洁直观:
library(tidyverse) df2 <- df1 %>% rownames_to_column("row_id") %>% # 将原行名转为列,避免丢失 pivot_longer(-row_id, names_to = "fruit", values_to = "value") %>% # 宽表转长表 filter(value == '1') %>% # 筛选出值为'1'的记录 select(row_id, fruit) %>% # 保留需要的列 column_to_rownames("row_id") # 恢复原行名
方法三:高效索引匹配法(无循环)
利用矩阵索引直接定位'1'的位置,匹配列名,效率更高:
# 获取所有'1'的行列索引(arr.ind=TRUE返回矩阵形式的位置) one_positions <- which(df1 == '1', arr.ind = TRUE) # 按行号排序后,提取对应的列名生成新数据框 df2 <- data.frame(fruit = colnames(df1)[one_positions[order(one_positions[,1]), 2]]) # 恢复原行名 rownames(df2) <- rownames(df1)
验证结果:执行任意一种方法后,用all.equal(df2, 你的预期df2)可以确认结果完全一致。
内容的提问来源于stack exchange,提问作者Sylvia Rodriguez
相关产品推荐
相关产品推荐

