R语言:获取与fixed_date匹配的列名失败,求高效实现方案
问题:为大尺寸Date类型data.frame新增匹配列名的列
我有一个约66k行、150列的data.frame,所有列均为Date类型。示例数据如下:
structure(list(fixed_date = structure(c(19267, 19239, 19120, 18035, 19253, 19211, 19120, 19778, 19120, 19211, 18224, 18224, 19624, 19211, 19211, 19211, 18409, 18409, 18558, 19876, 19267 ), class = "Date"), BEGIN1 = structure(c(19240, 19212, 19086, 18008, 19240, 19177, 19086, 19751, 19086, 19177, 18197, 18197, 19597, 19177, 19177, 18197, 18197, 18197, 18477, 18477, 19240 ), class = "Date"), END1 = structure(c(19267, 19239, 19120, 18035, 19253, 19211, 19120, 19778, 19120, 19211, 18224, 18224, 19624, 19211, 19211, 18224, 18224, 18224, 18488, 18488, 19267), class = "Date"), BEGIN2 = structure(c(NA, NA, 18043, NA, NA, NA, NA, NA, 18232, NA, NA, NA, NA, NA, 18232, 18232, 18232, 18232, 18512, 19849, 18484), class = "Date"), END2 = structure(c(NA, NA, 18070, NA, NA, NA, NA, NA, 18280, NA, NA, NA, NA, NA, 18280, 18280, 18280, 18280, 18523, 19876, 18495), class = "Date"), BEGIN3 = structure(c(NA, NA, 18897, NA, NA, NA, NA, NA, 18323, NA, NA, NA, NA, NA, 18354, 18354, 18396, 18396, 18547, 19793, 18519), class = "Date"), END3 = structure(c(NA, NA, 18924, NA, NA, NA, NA, NA, 18350, NA, NA, NA, NA, NA, 18381, 18381, 18409, 18409, 18558, 19827, 18530), class = "Date"), BEGIN4 = structure(c(NA, NA, 18113, NA, NA, NA, NA, NA, 18687, NA, NA, NA, NA, NA, 18722, 18372, NA, NA, NA, NA, 18554), class = "Date"), END4 = structure(c(NA, NA, 18140, NA, NA, NA, NA, NA, 18700, NA, NA, NA, NA, NA, 18749, 18399, NA, NA, NA, NA, 18565), class = "Date"), BEGIN5 = structure(c(NA, NA, 18148, NA, NA, NA, NA, NA, 18407, NA, NA, NA, NA, NA, 18407, 18407, NA, NA, NA, NA, NA), class = "Date"), END5 = structure(c(NA, NA, 18175, NA, NA, NA, NA, NA, 18434, NA, NA, NA, NA, NA, 18434, 18434, NA, NA, NA, NA, NA), class = "Date")), row.names = c(NA, -21L), class = c("tbl_df", "tbl", "data.frame"))
需求是新增一列,记录第2至11列中与第1列(fixed_date)值相等的列名。尝试以下代码无报错,但未生成目标列:
sample$match_date_<- apply(sample[,c(2:11)], 1, function(x) names(which(x == sample[,1])))
想知道代码未生效的原因,同时需要更高效的实现方案。
解答
原代码问题分析
- 匹配逻辑错误:
apply逐行处理时,x是单行数据,而sample[,1]是整个fixed_date列向量,x == sample[,1]会将单行与整列做比较,无法得到逐行匹配的结果,最终which返回空值,导致赋值无效。 - 效率低下:
apply是逐行循环处理,对66k行的大数据集来说速度较慢;且Date类型会被自动转为数值,虽然不影响比较,但增加了隐式转换的开销。
高效实现方案
方案1:向量化操作(最优性能)
# 提取目标列的数值矩阵(Date转数值不影响比较逻辑) target_cols <- as.matrix(sample[, -1]) # 生成逐行匹配的布尔矩阵 match_matrix <- target_cols == sample$fixed_date # 提取每行匹配的列名并以逗号连接 sample$match_date_ <- apply(match_matrix, 1, function(x) { matched_names <- colnames(target_cols)[x] paste(matched_names, collapse = ", ") })
- 优势:先通过向量化比较生成匹配矩阵,再逐行提取列名,比原始
apply逐行处理快数倍,适合大尺寸数据集。
方案2:tidyverse风格(简洁易读)
library(dplyr) library(purrr) sample <- sample %>% mutate(match_date_ = pmap_chr(select(., -fixed_date), ~ paste(names(c(...))[c(...) == fixed_date], collapse = ", ")))
- 优势:代码符合tidyverse语法,可读性强,处理66k行数据的效率优于原始
apply。
方案3:data.table(超大数据集首选)
如果数据量持续增长,data.table的内存效率和速度会更突出:
library(data.table) setDT(sample) sample[, match_date_ := { dt_subset <- .SD[, -"fixed_date"] apply(dt_subset == fixed_date, 1, function(x) paste(names(dt_subset)[x], collapse = ", ")) }]
- 优势:
data.table的内存优化机制适合处理百万级以上的数据集,操作速度更快。
内容的提问来源于stack exchange,提问作者Alejandro Carrera
相关产品推荐
相关产品推荐

