2017-01-23 2 views
0

у меня есть очень похожие проблемы с: Identify and replace duplicates elements from a vectorЗаменить повторяющиеся значения в векторе с использованием критериев из других столбцов в кадре данных

Мне нужно заменить повторяющиеся значения в столбце, происходящем в последовательности, но на основе критериев, из других столбцов в кадре данных.

У меня есть кадр данных, как это (плюс ряд дополнительных столбцов):

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 

Что мне нужно, чтобы заменить повторяющиеся результаты в пределах каждого 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 

Все строки сохранены. Те же самые оценки могут встречаться в разных идентификаторах/годах/последовательностях, но только в каждой уникальной комбинации этих трех столбцов я могу заменить дубликат.

Пример с одним вектором и решения от другого связанного вопроса:

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 

Я уверен в том, как адаптировать код выше в вопросе выше с несколькими критериями. Является ли это возможным? Прежде всего, самое главное - заменить баллы, но если у кого-то есть решение заменить как оценки, так и последовательность, я был бы очень доволен.

ответ

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 

Это также более безопасно в долгосрочной перспективе в случае смещения позиций из-за слияния или других манипуляций. Это может быть легче читать и интерпретировать при просмотре кода через шесть месяцев.

+0

Спасибо, это было просто и отлично! – Lisarv

0

Мы можем использовать data.table. Преобразуйте 'data.frame' в 'data.table' (setDT(examp)), сгруппированные по 'ID', 'year', мы получаем индекс строки (.I), где column 'sequence', является duplicated, а затем set эти значения в последовательность столбцов набора данных »,« оценка »до 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 

Или другой op Тион является replace с lapply

examp[3:4] <- lapply(examp[3:4], function(x) replace(x, duplicated(examp[1:3]), NA))