2012-12-20 15 views
82

Przeczytałem plik CSV w pliku R data.frame. Niektóre wiersze mają ten sam element w jednej z kolumn. Chciałbym usunąć wiersze będące duplikatami w tej kolumnie. Na przykład:Usuwanie zduplikowanych wierszy

platform_external_dbus   202   16      google  1 
platform_external_dbus   202   16   space-ghost.verbum  1 
platform_external_dbus   202   16     localhost  1 
platform_external_dbus   202   16   users.sourceforge  8 
platform_external_dbus   202   16     hughsie  1 

Chciałbym tylko jeden z tych wierszy, ponieważ inne mają te same dane w pierwszej kolumnie.

+2

których jeden chcesz? tylko pierwszy? innymi słowy: czy chcesz zachować 'google' lub' localhost' lub 'hughsie'? –

+0

Nie ma znaczenia dla tej części mojej analizy statystycznej. Próbuję tylko powiązać tytuł projektu (pierwsza kolumna), liczbę błędów (druga kolumna) i liczbę organizacji w projekcie (trzecia kolumna). – user1897691

+3

fajne. wyrzuć niepotrzebne kolumny i używaj? unikatowe –

Odpowiedz

114

prostu izolować ramki danych do kolumn trzeba, a następnie użyć unikalną funkcję: D

# in the above example, you only need the first three columns 
deduped.data <- unique(yourdata[ , 1:3 ]) 
# the fourth column no longer 'distinguishes' them, 
# so they're duplicates and thrown out. 
+0

Wygląda na to, że będzie idealnie działać. Czy możesz mi wyjaśnić, co dzieje się z częścią kodu "[, 1: 3]"? Jestem nowy w R, dlatego pytam, co mogę tylko założyć, to oczywiste pytanie. – user1897691

+6

@ user1897691 zaznacz to jako poprawne;) [obejrzyj to] (http://www.screenr.com/fCs8) i jeśli ci się to podoba, sprawdź [twotorials.com] (http://twotorials.com) –

110

dla ludzi, którzy przybyli tu w poszukiwaniu ogólnej odpowiedzi na duplikat usuwania wierszy, użyj !duplicated():

a <- c(rep("A", 3), rep("B", 3), rep("C",2)) 
b <- c(1,1,2,4,1,1,2,2) 
df <-data.frame(a,b) 

duplicated(df) 
[1] FALSE TRUE FALSE FALSE FALSE TRUE FALSE TRUE 

> df[duplicated(df), ] 
    a b 
2 A 1 
6 B 1 
8 C 2 

> df[!duplicated(df), ] 
    a b 
1 A 1 
3 A 2 
4 B 4 
5 B 1 
7 C 2 

Odpowiedź: Removing duplicated rows from R data frame

+0

I chcesz utworzyć nowy varibale, który oznacza flagę, jeśli istnieje duplikat * w pewnej zmiennej * prawie taki sam jak df $ duplikaty <- ifelse (ta wartość wierszy w kolumnie a == poprzednia wartość wiersza w kolumnie a, 1, 0) – jacob

+0

@ jacob zobacz to pytanie http://stackoverflow.com/questions/12495345/find-indices-of-duplicated-rows –

+1

To zachowuje pierwszą wartość i usuwa pozostałe duplikaty, prawda? Lub usuwa wartości losowo? – alphabetagamma

37

funkcją distinct() w dplyr packa ge wykonuje arbitralne usuwanie duplikatów, pozwalając na specyfikację zduplikowanych zmiennych (jak w tym pytaniu) lub biorąc pod uwagę wszystkie zmienne.

danych:

dat <- data.frame(a = rep(c(1,2),4), b = rep(LETTERS[1:4],2)) 

Usuń wiersze gdzie określone kolumny są duplikowane:

library(dplyr) 
dat %>% distinct(a, .keep_all = TRUE) 

    a b 
1 1 A 
2 2 B 

Usuń wiersze, które są kompletne duplikatami innych wierszy:

dat %>% distinct 

    a b 
1 1 A 
2 2 B 
3 1 C 
4 2 D 
5

Z sqldf:

# Example by Mehdi Nellen 
a <- c(rep("A", 3), rep("B", 3), rep("C",2)) 
b <- c(1,1,2,4,1,1,2,2) 
df <-data.frame(a,b) 

Rozwiązanie:

library(sqldf) 
    sqldf('SELECT DISTINCT * FROM df') 

wyjściowa:

a b 
1 A 1 
2 A 2 
3 B 4 
4 B 1 
5 C 2 
21

Pakiet data.table ma również unique i duplicated metod na jego własny z dodatkowymi funkcjami.

Zarówno unique.data.table i metody duplicated.data.table mieć dodatkowy by argument, który pozwala przekazać character lub integer wektor nazw kolumn lub ich miejscach odpowiednio

library(data.table) 
DT <- data.table(id = c(1,1,1,2,2,2), 
       val = c(10,20,30,10,20,30)) 

unique(DT, by = "id") 
# id val 
# 1: 1 10 
# 2: 2 10 

duplicated(DT, by = "id") 
# [1] FALSE TRUE TRUE FALSE TRUE TRUE 

Inną ważną cechą tych metod jest ogromna wydajność wzmocnienie dla większych zestawów danych

library(microbenchmark) 
library(data.table) 
set.seed(123) 
DF <- as.data.frame(matrix(sample(1e8, 1e5, replace = TRUE), ncol = 10)) 
DT <- copy(DF) 
setDT(DT) 

microbenchmark(unique(DF), unique(DT)) 
# Unit: microseconds 
#  expr  min   lq  mean median  uq  max neval cld 
# unique(DF) 44708.230 48981.8445 53062.536 51573.276 52844.591 107032.18 100 b 
# unique(DT) 746.855 776.6145 2201.657 864.932 919.489 55986.88 100 a 


microbenchmark(duplicated(DF), duplicated(DT)) 
# Unit: microseconds 
#   expr  min   lq  mean  median  uq  max neval cld 
# duplicated(DF) 43786.662 44418.8005 46684.0602 44925.0230 46802.398 109550.170 100 b 
# duplicated(DT) 551.982 558.2215 851.0246 639.9795 663.658 5805.243 100 a 
2

Albo możesz zagnieździć dane w Cols 4 i 5 w jednym wierszu z tidyr:

library(tidyr) 
df %>% nest(V4:V5) 

# A tibble: 1 × 4 
#      V1 V2 V3    data 
#     <fctr> <int> <int>   <list> 
#1 platform_external_dbus 202 16 <tibble [5 × 2]> 

Col 2 i 3 kopie zostały teraz do analizy statystycznej, ale zachowałem Col 4 i 5 dane w tibble i może wrócić do oryginalnej ramki danych w dowolnym momencie z unnest().

0

ogólna odpowiedź może być na przykład:

df <- data.frame(rbind(c(2,9,6),c(4,6,7),c(4,6,7),c(4,6,7),c(2,9,6)))) 



new_df <- df[-which(duplicated(df)), ] 

wyjściowa:

 X1 X2 X3 
    1 2 9 6 
    2 4 6 7