web-dev-qa-db-fra.com

Supprimer les lignes dupliquées à l'aide de dplyr

J'ai un data.frame comme ça - 

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

Je voudrais supprimer les lignes en double en fonction des deux premières colonnes. Production attendue - 

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

Je recherche spécifiquement une solution utilisant le package dplyr.

100
Nishanth

Remarque : dplyr contient maintenant la fonction distinct à cette fin.

Réponse originale ci-dessous:


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
)

Une approche consisterait à grouper et à ne conserver que la première ligne:

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

(Dans dplyr 0.2, vous n’aurez plus besoin de la variable factice z et vous serez simplementable pour écrire row_number() == 1)

J'ai également pensé à ajouter une fonction slice() qui fonctionnerait comme suit:

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

Ou peut-être une variante de unique() qui vous permettrait de sélectionner les variables À utiliser:

df %>% unique(x, y)
113
hadley

Voici une solution utilisant dplyr 0.3.

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)
    x y z
  1 0 1 1
  2 1 0 2
  3 1 1 4

Mis à jour pour dplyr 0.5

le comportement par défaut de distinct() de dplyr version 0.5 ne renvoie que les colonnes spécifiées dans l'argument ...

Pour obtenir le résultat initial, vous devez maintenant utiliser:

df %>% distinct(x, y, .keep_all = TRUE)
164
davechilders

Par souci d’exhaustivité, ce qui suit fonctionne également:

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

Cependant, je préfère la solution utilisant distinct, et je suppose que c'est aussi plus rapide.

24
Konrad Rudolph

Lorsque vous sélectionnez des colonnes dans R pour un jeu de données réduit, vous pouvez souvent vous retrouver avec des doublons.

Ces deux lignes donnent le même résultat. Chacune génère un ensemble de données unique avec deux colonnes sélectionnées uniquement:

distinct(mtcars, cyl, hp);

summarise(group_by(mtcars, cyl, hp));
2
Anton Andreev

Si vous voulez trouver les lignes dupliquées, vous pouvez utiliser find_duplicates à partir de hablar:

library(dplyr)
library(hablar)

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

df %>% find_duplicates()
0
davsjob

La plupart du temps, la meilleure solution consiste à utiliser distinct() de dplyr, comme cela a déjà été suggéré.

Cependant, voici une autre approche qui utilise la fonction slice() de dplyr.

# 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)

Différence d'utilisation de la fonction distinct()

L'avantage de cette solution est qu'elle rend explicites quelles lignes sont conservées dans le cadre de données d'origine et peut très bien s'associer à la fonction arrange().

Supposons que vous disposiez de données sur les ventes client et que vous souhaitiez conserver un enregistrement par client et que vous souhaitiez que cet enregistrement soit celui de leur dernier achat. Ensuite, vous pourriez écrire:

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