Entfernen Sie doppelte Zeilen mit dplyr


128

Ich habe einen data.frame wie diesen -

set.seed(123)
df = data.frame(x=sample(0:1,10,replace=T),y=sample(0:1,10,replace=T),z=1:10)
> df
   x y  z
1  0 1  1
2  1 0  2
3  0 1  3
4  1 1  4
5  1 0  5
6  0 1  6
7  1 0  7
8  1 0  8
9  1 0  9
10 0 1 10

Ich möchte doppelte Zeilen basierend auf den ersten beiden Spalten entfernen. Erwartete Ausgabe -

df[!duplicated(df[,1:2]),]
  x y z
1 0 1 1
2 1 0 2
4 1 1 4

Ich suche speziell nach einer Lösung mit dplyrPaket.

Antworten:


137

Hinweis : dplyrEnthält jetzt die distinctFunktion für diesen Zweck.

Ursprüngliche Antwort unten:


library(dplyr)
set.seed(123)
df <- data.frame(
  x = sample(0:1, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  z = 1:10
)

Ein Ansatz wäre, zu gruppieren und dann nur die erste Zeile beizubehalten:

df %>% group_by(x, y) %>% filter(row_number(z) == 1)

## Source: local data frame [3 x 3]
## Groups: x, y
## 
##   x y z
## 1 0 1 1
## 2 1 0 2
## 3 1 1 4

(In dplyr 0.2 benötigen Sie die Dummy- zVariable nicht und können nur schreiben. row_number() == 1)

Ich habe auch darüber nachgedacht, eine slice()Funktion hinzuzufügen , die wie folgt funktionieren würde:

df %>% group_by(x, y) %>% slice(from = 1, to = 1)

Oder mit einer Variation davon können unique()Sie auswählen, welche Variablen verwendet werden sollen:

df %>% unique(x, y)

4
@dotcomken Bis dahin konnte auch nur verwendet werdendf %>% group_by(x, y) %>% do(head(.,1))
Holger Brandl

16
@ MahbubulMajumder das wird funktionieren, ist aber ziemlich langsam. dplyr 0.3 wirddistinct()
hadley

3
@ Hadley Ich mag die Funktion unique () und unique (), aber alle entfernen das 2. Duplikat aus dem Datenrahmen. Was ist, wenn alle ersten Begegnungen mit dem doppelten Wert entfernt werden sollen? Wie könnte das gemacht werden? Vielen Dank für jede Hilfe!
FlyingDutch

2
@MvZB - würdest du nicht einfach (desc ()) arrangieren und dann eindeutig verwenden?
Woodstock

Ich bin mir sicher, dass es eine einfache Lösung gibt, aber was ist, wenn ich beide doppelten Zeilen entfernen möchte? Ich arbeite oft mit Metadaten, die mit biologischen Proben verknüpft sind, und wenn ich doppelte Proben-IDs habe, kann ich oft nicht sicher sein, welche Zeile die richtigen Daten enthält. Am sichersten ist es, beide zu sichern, um fehlerhafte Metadatenzuordnungen zu vermeiden. Gibt es eine einfache Lösung, außer eine Liste doppelter Beispiel-IDs zu erstellen und Zeilen mit diesen IDs herauszufiltern?
glongo_fishes

191

Hier ist eine Lösung mit dplyr >= 0.5.

library(dplyr)
set.seed(123)
df <- data.frame(
  x = sample(0:1, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  z = 1:10
)

> df %>% distinct(x, y, .keep_all = TRUE)
    x y z
  1 0 1 1
  2 1 0 2
  3 1 1 4

3
Diese Lösung scheint viel schneller zu sein (in meinem Fall zehnmal) als die von Hadley.
Calimo

101
Auch technisch ist dies eine Lösung von Hadley :-)
Tyler Rinker

27

Der Vollständigkeit halber funktioniert auch Folgendes:

df %>% group_by(x) %>% filter (! duplicated(y))

Ich bevorzuge jedoch die Verwendung der Lösung distinctund vermute, dass sie auch schneller ist.


7

Die beste Lösung ist distinct()meistens die Verwendung von dplyr, wie bereits vorgeschlagen wurde.

Hier ist jedoch ein anderer Ansatz, der die slice()Funktion von dplyr verwendet.

# Generate fake data for the example
  library(dplyr)
  set.seed(123)
  df <- data.frame(
    x = sample(0:1, 10, replace = T),
    y = sample(0:1, 10, replace = T),
    z = 1:10
  )

# In each group of rows formed by combinations of x and y
# retain only the first row

    df %>%
      group_by(x, y) %>%
      slice(1)

Unterschied zur Verwendung der distinct()Funktion

Der Vorteil dieser Lösung besteht darin, dass explizit angegeben wird, welche Zeilen vom ursprünglichen Datenrahmen beibehalten werden, und dass sie sich gut mit der arrange()Funktion koppeln lässt .

Angenommen, Sie hatten Kundenverkaufsdaten und wollten einen Datensatz pro Kunde behalten, und Sie möchten, dass dieser Datensatz der Datensatz aus dem letzten Kauf ist. Dann könnten Sie schreiben:

customer_purchase_data %>%
   arrange(desc(Purchase_Date)) %>%
   group_by(Customer_ID) %>%
   slice(1)

3

Wenn Sie Spalten in R für einen reduzierten Datensatz auswählen, kann es häufig zu Duplikaten kommen.

Diese beiden Zeilen ergeben das gleiche Ergebnis. Jeder gibt einen eindeutigen Datensatz mit nur zwei ausgewählten Spalten aus:

distinct(mtcars, cyl, hp);

summarise(group_by(mtcars, cyl, hp));

1

Wenn Sie möchten , um die Zeilen zu finden , die dupliziert werden Sie verwenden können , find_duplicatesaus hablar:

library(dplyr)
library(hablar)

df <- tibble(a = c(1, 2, 2, 4),
             b = c(5, 2, 2, 8))

df %>% find_duplicates()
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.