我有一个非常类似的问题: Identify and replace duplicates elements from a vector
我需要根据数据框中其他列的条件替换序列BUT中出现的列中的重复值。
我有一个这样的数据框(加上一些额外的列):
ID<- c("1V","1V","1V","1V","2V","2V","4V","4V","4V","4V","4V")
year<- c(1,1,1,2,1,1,2,2,3,3,3)
sequence<- c(1,2,2,1, 1,2,1,2,1,1,1)
score <- c(5,5,5,5,10,10,10,10,11,11,11)
examp <- data.frame(ID,year, sequence, score)
> examp
ID year sequence score
1 1V 1 1 5
2 1V 1 2 5
3 1V 1 2 5
4 1V 2 1 5
5 2V 1 1 10
6 2V 1 2 10
7 4V 2 1 10
8 4V 2 2 10
9 4V 3 1 11
10 4V 3 1 11
11 4V 3 1 11
我需要的是用NA替换每个ID,年份和序列中的重复分数。与分数结合的序列也应该用NA替换。因此,不会删除任何行,只删除特定条目。
> examp
ID year sequence score
1 1V 1 1 5
2 1V 1 2 5
3 1V 1 NA NA
4 1V 2 2 5
5 2V 1 1 10
6 2V 1 2 10
7 4V 2 1 10
8 4V 2 2 10
9 4V 3 1 11
10 4V 3 NA NA
11 4V 3 NA NA
保留所有行。不同的ID /年/序列可能会出现相同的分数,但只有在这三个列的每个唯一组合中,才能替换重复的分数。
来自其他链接问题的单个向量和解决方案的示例:
a <- 1 1 1 2 3 2 2 2 2 1 0 0 0 0 2 3 4 4 1 1
ifelse(a == c(a[1]-1,a[(1:length(a)-1)]) , 0 , a)
[1] 1 0 0 2 3 2 0 0 0 1 0 0 0 0 2 3 4 0 1 0
我不确定如何使用多个标准调整上述问题中的上述代码。可能吗? 首先,最重要的是取代分数,但如果有人有解决方案来取代分数和顺序,我会非常高兴。
答案 0 :(得分:1)
在基数R中,您可以使用子集和is.na
。
is.na(examp[duplicated(examp[1:3]), c("sequence", "score")]) <- TRUE
examp
ID year sequence score
1 1V 1 1 5
2 1V 1 2 5
3 1V 1 NA NA
4 1V 2 1 5
5 2V 1 1 10
6 2V 1 2 10
7 4V 2 1 10
8 4V 2 2 10
9 4V 3 1 11
10 4V 3 NA NA
11 4V 3 NA NA
这里,ID year sequence
返回一个逻辑向量,即data.frame的长度,表示前三个变量的行是否与前一行重复。 c("sequence", "score")
确定要替换的列。然后在重复行的那些列中将is.na
设置为TRUE。
更长但更易读的版本是使用变量名而不是它们的位置。
is.na(examp[duplicated(examp[c("ID", "year", "sequence")]), c("sequence", "score")]) <- TRUE
从长远来看,如果由于合并或其他操作导致位置发生变化,这也更安全。从现在起六个月后审查代码时,阅读/解释也可能更容易。
答案 1 :(得分:0)
我们可以使用data.table
。将'data.frame'转换为'data.table'(setDT(examp)
),按'ID','年'分组,我们得到行索引(.I
),其中列'序列',是duplicated
然后set
数据集列'sequence'中的值,'得分'到NA。这应该是非常有效的,因为我们正在设置
library(data.table)
i1 <- setDT(examp)[, .I[duplicated(sequence)], .(ID, year)]$V1
for(j in 3:4){
set(examp, i = i1, j=j, value = NA)
}
examp
# ID year sequence score
# 1: 1V 1 1 5
# 2: 1V 1 2 5
# 3: 1V 1 NA NA
# 4: 1V 2 1 5
# 5: 2V 1 1 10
# 6: 2V 1 2 10
# 7: 4V 2 1 10
# 8: 4V 2 2 10
# 9: 4V 3 1 11
#10: 4V 3 NA NA
#11: 4V 3 NA NA
或dplyr
library(dplyr)
examp %>%
group_by(ID, year) %>%
mutate_each(funs(replace(., duplicated(.), NA)))
使用base R
,我们可以做一个紧凑的选项
examp[duplicated(examp[1:3]), 3:4] <- NA
examp
# ID year sequence score
#1 1V 1 1 5
#2 1V 1 2 5
#3 1V 1 NA NA
#4 1V 2 1 5
#5 2V 1 1 10
#6 2V 1 2 10
#7 4V 2 1 10
#8 4V 2 2 10
#9 4V 3 1 11
#10 4V 3 NA NA
#11 4V 3 NA NA
或另一个选项replace
lapply
examp[3:4] <- lapply(examp[3:4], function(x) replace(x, duplicated(examp[1:3]), NA))