2015-04-20 2 views
4

Я хочу удалить дубликаты на основе столбца «Пользователь», но только первый экземпляр, где он появляется.Удаление первой повторяющейся строки и сохранение остальных?

DF:

User No 
A  1 
B  1 
A  2 
A  3 
A  4 
C  1 
B  2 
D  1 

Результат: (A1 и B1 удалены)

User No 
A  2 
A  3 
A  4 
C  1 
B  2 
D  1 

Я был неудачным с помощью дублированного функции.

Любая помощь будет оценена! Благодаря!

+2

Что вы подразумеваете под «Я не увенчался успехом с использованием дублированной функции»? Что вы пробовали до сих пор? Пожалуйста, поделитесь некоторым кодом, или этот вопрос обязательно будет закрыт. –

ответ

14

Если я правильно понимаю, это должно работать

library(dplyr) 
dd %>% group_by(User) %>% filter(duplicated(User) | n()==1) 
+0

Принял меня, чтобы понять, что вы там делали. Спасибо! – ant

11

Здесь можно использовать data.table. Мы преобразуем «data.frame» в «data.table» (setDT(DF)). Сгруппированный по столбцу «Пользователь», мы выбираем все строки, кроме первого (tail(.SD, -1)), где .SD - Subset of Data.table. Но это также удалит строку, если для группы «Пользователь» есть только одна строка. Мы можем избежать этого, используя условие if/else, заявив, что if число строк больше 1 (.N>1), мы удаляем первую строку или else возвращаем строку (.SD).

library(data.table) 
setDT(DF)[, if(.N>1) tail(.SD,-1) else .SD , by = User] 
# User No 
#1: A 2 
#2: A 3 
#3: A 4 
#4: B 2 
#5: C 1 
#6: D 1 

Или подобный вариант, как в @ MrFlick-х dplyr код будет использовать логическое условие с duplicated и .N (количество строк). Мы создаем столбец «N», проверяя группы «Пользователь», которые имеют одно наблюдение (.N==1), на следующем шаге мы подмножаем строки, которые имеют значение TRUE для N или duplicated для «Пользователь». duplicated возвращает TRUE значения для duplicate строк, оставляя первое значение как FALSE.

setDT(DF)[DF[, N:=.N==1, by = User][, N|duplicated(User)]][,N:=NULL][] 

Или base R вариант будет использовать ave, чтобы получить логический индекс («indx2»), проверяя, если length для каждой группы «User» является 1 или нет. Мы можем использовать это вместе с duplicated, как описано выше, для подмножества набора данных.

indx2 <- with(DF, ave(seq_along(User), User, FUN=length)==1) 
DF[duplicated(DF$User)|indx2,] 
# User No 
#3 A 2 
#4 A 3 
#5 A 4 
#6 C 1 
#7 B 2 
#8 D 1 
3

Это не так легко понять, как MrFlick и подходы akrun, но это одна линия решение A база ¨R

#data 
DF=data.frame(User=c("A","B","A","A","A","C","B","D"),No=c(1,1,2,3,4,1,2,1)) 
#solution 
subset(DF,duplicated(User)|!duplicated(User,fromLast=TRUE)) 

Дает

# User No 
#3 A 2 
#4 A 3 
#5 A 4 
#6 C 1 
#7 B 2 
#8 D 1 

Объяснения:

subset(DF,logicalA|logicalB) 
  • logicalA ... выбирает все дублирующиеся записи и, следовательно, не включает всех пользователей ровно одну записи
  • logicalB ...выбирает всем пользователям ровно одна запись и выбирает последнюю запись (см fromLast=TRUE) пользователей с более чем одной строки (последний выбираются logicalA в любом случае)

Я надеюсь, что я получил это право. :)

Смежные вопросы