如何在R中基于列标题与值为1的条件创建新列?
实现需求的几种方法
首先,你的初始数据框为:
df <- data.frame(x1=c(1,0,0,0),x2=c(0,1,0,0),x3=c(0,0,0,1),x4=c(0,0,1,0))
需求是新增一列name,每行取值为该行中值为1的列的列名,最终得到目标数据框:
df2 <- data.frame(x1=c(1,0,0,0),x2=c(0,1,0,0),x3=c(0,0,0,1),x4=c(0,0,1,0),name=c("x1","x2","x4","x3"))
以下是几种高效的实现方式:
方法一:基础R的max.col()函数(最简洁)
利用max.col()直接定位每行最大值的列索引,再匹配列名:
df$name <- colnames(df)[max.col(df)]
原理:因为每行仅有一个1,其余为0,max.col(df)会返回每行中值最大(即1)的元素所在的列位置,再通过colnames(df)提取对应的列名。
方法二:基础R的apply()逐行处理
通过apply()对每行执行逻辑判断,筛选出值为1的列名:
df$name <- apply(df, 1, function(row) names(row)[row == 1])
原理:apply(df, 1, ...)表示按行处理数据,匿名函数中row == 1会找出该行值为1的位置,再用names(row)取出对应的列名。
方法三:tidyverse工具链(适合宽表转长表的场景)
如果你习惯使用tidy语法,可以结合dplyr和tidyr实现:
library(dplyr) library(tidyr) df2 <- df %>% # 给每行添加唯一行号,用于后续合并 mutate(row_id = row_number()) %>% # 宽表转长表,保留行号,列名转为name列,值转为value列 pivot_longer(-row_id, names_to = "name", values_to = "value") %>% # 筛选出值为1的行 filter(value == 1) %>% # 移除不必要的value列 select(-value) %>% # 和原表按行号合并 right_join(df, by = "row_id") %>% # 移除行号列 select(-row_id) %>% # 将name列移到最后 relocate(name, .after = last_col())
内容的提问来源于stack exchange,提问作者MAJ
相关产品推荐
相关产品推荐

