如何在R中高效识别重复值并正确重排数字序列?
优化R语言重复值识别与重排的循环逻辑
需求背景
需要编写R语言循环代码,识别数字序列中不允许存在的重复值,并反复将数字重排为正确序列。当前代码可正常运行,但ckDupes中的重复值识别与重排逻辑较为繁琐,需优化为更清晰高效的实现方式以适配后续迭代循环。
原始代码
library(dplyr) dat <- data.frame(Element= c("X","X","X","X","R"), Code = c(1.1,2.1,2.2,2.2,3)) uniqCodes <- dat %>% select(Code) %>% distinct() ckDupes <- dat %>% mutate(cntDupes1 = sapply(1:n(), function(x) sum(Element[1:x]==Element[x] & Code[1:x] == Code[x]))-1) %>% mutate(reCode1 = ifelse(cntDupes1 > 0,uniqCodes[match(Code,uniqCodes$Code)+cntDupes1,],Code)) %>% mutate(cntDupes2 = sapply(1:n(), function(x) sum(Element[1:x]==Element[x] & reCode1[1:x] == reCode1[x]))-1)
优化后的代码
library(dplyr) dat <- data.frame(Element= c("X","X","X","X","R"), Code = c(1.1,2.1,2.2,2.2,3)) # 将唯一Code转为向量,提升索引效率 uniqCodes_vec <- dat %>% distinct(Code) %>% pull(Code) ckDupes <- dat %>% # 按Element和Code分组,计算每组内的累计重复次数(当前行之前的重复数) group_by(Element, Code) %>% mutate(cntDupes1 = row_number() - 1) %>% ungroup() %>% # 为重复项分配下一个连续的Code值 mutate(reCode1 = ifelse(cntDupes1 > 0, uniqCodes_vec[match(Code, uniqCodes_vec) + cntDupes1], Code)) %>% # 再次检查重排后的Code在同一Element内的重复情况 group_by(Element, reCode1) %>% mutate(cntDupes2 = row_number() - 1) %>% ungroup()
优化说明
- 替换低效循环:用
dplyr的分组窗口函数row_number()替代sapply循环计算累计重复数,实现向量化操作,大幅提升处理速度(尤其针对大数据集)。 - 简化索引操作:将
uniqCodes从数据框转为向量,直接通过索引访问元素,代码更简洁且效率更高。 - 逻辑保持一致:优化后的代码完全保留原始逻辑,但结构更清晰、可读性更强,更适合后续嵌入迭代循环中使用。
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

