如何从data.frame每行提取值为1的列名并整合至原数据?
解决方案:提取每行值为1的列名并重构数据
嘿,我明白你的需求啦!你现在的数据集里每行只有一个1,其余都是0,想要把这些标记列替换成对应的列名,对吧?rowSums确实只能拿到求和结果,没法定位列名,下面给你几种简单的实现方法:
方法一:Base R 用 max.col 快速定位
因为每行只有一个1,max.col 可以直接找到这个最大值所在的列位置,再匹配列名就好:
# 先模拟你的数据(方便测试) users_cluster <- data.frame( user_id = c("u001", "u002", "u003", "u004"), "1" = c(1, 0, 0, 0), "2" = c(0, 1, 0, 0), "5" = c(0, 0, 1, 0), "9" = c(0, 0, 0, 1) ) # 提取每行值为1的列名,新增cluster列 users_cluster$cluster <- colnames(users_cluster[, -1])[max.col(users_cluster[, -1])] # 保留需要的列,删除原1-9列 final_data <- users_cluster[, c("user_id", "cluster")]
方法二:用 apply 逐行匹配
如果想更直观地逐行判断,可以用apply函数:
# 逐行找到值为1的列名 users_cluster$cluster <- apply(users_cluster[, -1], 1, function(row) { names(row)[row == 1] }) # 筛选结果列 final_data <- users_cluster[, c("user_id", "cluster")]
方法三:Tidyverse 风格的转长格式处理
如果你习惯用dplyr和tidyr,转长格式的方法更灵活,还能处理异常情况(比如某行没有1或者多个1):
library(tidyverse) final_data <- users_cluster %>% # 把1-9列转成"cluster"(列名)和"value"(对应值)两列 pivot_longer(cols = -user_id, names_to = "cluster", values_to = "value") %>% # 只保留值为1的行 filter(value == 1) %>% # 只保留需要的列 select(user_id, cluster)
这几种方法都能帮你完成需求,根据自己的习惯选就行~
内容的提问来源于stack exchange,提问作者user3600910
相关产品推荐
相关产品推荐

