在R中对数据框行内值重排序并将重复值替换为NA
处理R数据框行内年份值的高效方案
需求
- 按行将年份值降序排列,
year_1为最大值,后续列依次递减,NA置于行末 - 行内重复年份替换为NA,保留所有列,NA仍放在行末
原始数据
data <- data.frame(sample = c("A", "B", "C", "D", "E", "F"), year_1 = c(2015, 2014, NA, 1985, 2011, 2010), year_2 = c(NA, 1986, 1999, 1986, 2009, 2009), year_3 = c(2015, 2014, 2014, 1956, NA, 2010), year_4 = c(NA, 2014, 2014, 1985, 2010, 2010))
已完成的排序步骤
你已经实现了行内降序排序,代码如下:
cols <- c("year_1", "year_2", "year_3", "year_4") data[cols] <- t(apply(data[cols], MARGIN = 1, FUN = function(x) sort(x, decreasing = TRUE, na.last = TRUE)))
高效去重并替换重复值为NA的方案
针对数十万行的大数据量,优先推荐向量化处理方案,比逐行apply效率更高:
方案1:使用data.table(高效处理大数据)
library(data.table) # 转换为data.table格式 setDT(data) # 1. 转长格式,过滤NA值 long_dt <- melt(data, id.vars = "sample", value.name = "year", na.rm = TRUE) # 2. 按样本分组,去重后降序排序 long_dt <- long_dt[, .(year = unique(year)), by = sample][order(sample, -year)] # 3. 给每个样本的唯一年份分配行号,用于转宽 long_dt[, row_id := 1:.N, by = sample] # 4. 转宽格式,自动补全NA到原列数 result <- dcast(long_dt, sample ~ paste0("year_", row_id), value.var = "year") # 5. 补全缺失的year列(确保保留4列结构) for (col in paste0("year_", 1:4)) { if (!col %in% names(result)) { result[, (col) := NA] } } # 6. 恢复原列顺序 setcolorder(result, c("sample", "year_1", "year_2", "year_3", "year_4"))
方案2:基于原有apply逻辑优化(无需额外包)
如果不想引入新包,可直接修改原apply的处理函数,在排序后完成去重和补NA:
cols <- c("year_1", "year_2", "year_3", "year_4") data[cols] <- t(apply(data[cols], MARGIN = 1, FUN = function(x) { # 降序排序 sorted_x <- sort(x, decreasing = TRUE, na.last = TRUE) # 提取唯一非NA值 unique_vals <- unique(na.omit(sorted_x)) # 补NA到原列长度 c(unique_vals, rep(NA, length(x) - length(unique_vals))) }))
目标结果
> result sample year_1 year_2 year_3 year_4 1: A 2015 NA NA NA 2: B 2014 1986 NA NA 3: C 2014 1999 NA NA 4: D 1986 1985 1956 NA 5: E 2011 2010 2009 NA 6: F 2010 2009 NA NA
内容的提问来源于stack exchange,提问作者apple
相关产品推荐
相关产品推荐

