如何高效比对DataFrame的class列与其余逻辑列提取对应列名
高效实现方案
你原有代码的性能问题来自R的显式for循环逐行操作会产生大量中间副本,以下三种全向量化实现方案性能远高于循环,适合大数据量场景:
1. Base R 方案(无额外依赖)
# 提取除class列外的所有列转为逻辑矩阵 logic_mat <- as.matrix(df[, setdiff(colnames(df), "class")]) # 匹配每行第一个TRUE对应的列索引,全为FALSE的行后续统一处理 col_pos <- max.col(logic_mat, ties.method = "first") # 标记该行是否存在TRUE值 has_true <- rowSums(logic_mat) > 0 # 生成结果表 new_df <- data.frame( class = df$class, new_col = ifelse(has_true, colnames(logic_mat)[col_pos], "") )
核心函数max.col、rowSums均为底层C实现,百万行级数据处理仅需毫秒级耗时。
2. Tidyverse 方案(可读性强)
library(dplyr) library(tidyr) new_df <- df %>% # 转为长表结构批量匹配 pivot_longer(-class, names_to = "col_name", values_to = "value") %>% filter(value == TRUE) %>% # 保留所有原始class行,无匹配的补空 right_join(select(df, class), by = "class") %>% mutate(new_col = replace_na(col_name, "")) %>% select(class, new_col)
3. data.table 方案(超大数据量最优)
library(data.table) setDT(df) # 长表转换+匹配 dt_long <- melt(df, id.vars = "class", variable.factor = FALSE) dt_match <- dt_long[value == TRUE, .(class, new_col = as.character(variable))] # 关联补全结果 new_df <- dt_match[df[, .(class)], on = "class"][, new_col := fcoalesce(new_col, "")][]
注意事项
如果单行存在多个TRUE值,以上方案默认返回第一个匹配的列名;若需要返回所有匹配列名,可将对应逻辑调整为多值拼接即可。
内容的提问来源于stack exchange,提问作者Vendetta
相关产品推荐
相关产品推荐

