Rimuovi le righe duplicate


152

Ho letto un CSVfile in un R data.frame. Alcune delle righe hanno lo stesso elemento in una delle colonne. Vorrei rimuovere le righe duplicate in quella colonna. Per esempio:

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

Vorrei solo una di queste righe poiché le altre hanno gli stessi dati nella prima colonna.


3
quale vuoi? solo il primo? in altre parole: vuoi mantenere googleo localhosto hughsie?
Anthony Damico,

Non importa per questa parte della mia analisi statistica. Sto solo cercando di mettere in relazione il titolo del progetto (prima colonna), il numero di bug (seconda colonna) e il numero di organizzazioni nel progetto (terza colonna).
user1897691

3
freddo. buttare fuori colonne inutili e usare? unico
Anthony Damico il

Risposte:


186

basta isolare il frame di dati nelle colonne necessarie, quindi utilizzare la funzione unica: 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.

1
Sembra che funzionerà perfettamente. Potete per favore spiegarmi cosa sta succedendo con la [,1:3]parte di quel codice? Sono nuovo di R ed è per questo che sto chiedendo che cosa posso solo supporre sia una domanda ovvia.
user1897691

6
@ user1897691 contrassegnalo come corretto allora;) guarda questo e se ti piace, controlla twotorials.com
Anthony Damico il

3
Nota che questo rimuoverà tutte le colonne tranne le prime tre.
GuillaumeL

186

Per le persone che sono venute qui per cercare una risposta generale per la rimozione di righe duplicate, utilizzare !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

Risposta da: rimozione di righe duplicate dal frame di dati R.


Voglio creare una nuova varibale che segnala se esiste un duplicato su una determinata variabile quasi come df $ duplicates <- ifelse (questo valore di righe nella colonna a == valore di riga precedente nella colonna a, 1, 0)
jacob,

@jacob vedere questa domanda stackoverflow.com/questions/12495345/...
dpel

2
Ciò mantiene il primo valore apparso e rimuove il resto dei duplicati, giusto? O rimuove i valori in modo casuale?
News_is_Selection_Bias il

@alphabetagamma sì, mantiene il primo valore apparso
Mehdi Nellen

2
Se sei interessato solo ai duplicati in determinate colonne, ad esempio le colonne 1 e 2, possiamo usaredf[!duplicated(df[, 1:2])]
qwr

82

La funzione distinct()nel dplyrpacchetto esegue la rimozione arbitraria di duplicati, sia da colonne / variabili specifiche (come in questa domanda) sia considerando tutte le colonne / variabili. dplyrfa parte del tidyverse.

Dati e pacchetto

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

Rimuovi le righe duplicate in una colonna specifica (ad es. Colonna a)

Nota che .keep_all = TRUEconserva tutte le colonne, altrimenti averrebbe mantenuta solo la colonna .

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

Rimuovi le righe che sono duplicati completi di altre righe:

distinct(dat)

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

A proposito, un'ottima risposta .keep_allè se mantenere tutte le colonne, non mescolarle con keepin pandas.
Jason Goal,

28

Il data.tablepacchetto ha anche uniquee duplicatedmetodi propri con alcune funzionalità aggiuntive.

Sia il unique.data.tableed i duplicated.data.tablemetodi hanno un ulteriore byargomento che permette di passare una charactero integervettore di nomi di colonna o le loro posizioni, rispettivamente,

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

Un'altra caratteristica importante di questi metodi è un enorme aumento delle prestazioni per set di dati più grandi

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 

7

Puoi anche usare dplyrla distinct()funzione! Tende ad essere più efficiente delle opzioni alternative, soprattutto se hai un sacco di osservazioni.

distinct_data <- dplyr::distinct(yourdata)

1
Questa è la stessa risposta di Sam Firke, ma con meno dettagli.
qwr

6

la risposta generale può essere ad esempio:

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)), ]

produzione:

      X1 X2 X3
    1  2  9  6
    2  4  6  7

1
Prestare attenzione quando si utilizza -which, questo porterà ad errori se non ci sono duplicati, l'uso df[!(duplicated(df)), ]potrebbe essere più sicuro.
Jason Goal,

5

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

Soluzione:

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

Produzione:

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

Questo ha il sovraccarico di impostare un intero database SQL. cran.r-project.org/web/packages/sqldf/index.html
qwr

Cosa intendi con l'impostazione di un intero database SQL? Questo è uno dei principali vantaggi: 'con sqldf l'utente è libero di dover eseguire le seguenti operazioni, tutte eseguite automaticamente: configurazione del database, scrittura dell'istruzione create table che definisce ciascuna tabella, importazione ed esportazione da e verso il database '. Non è una soluzione ottimale, ma utile per chi ha familiarità con SQL.
mpalanco,

3

Oppure potresti annidare i dati nelle colonne 4 e 5 in una singola riga con 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]>

I duplicati di col 2 e 3 vengono ora rimossi per l'analisi statistica, ma i dati di col 4 e 5 sono stati conservati in una tabella e si può tornare al frame di dati originale in qualsiasi momento con unnest().


1

Rimuovere le righe duplicate di un frame di dati

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

In questo set di dati, non esiste una singola riga duplicata, quindi ha restituito lo stesso numero di righe di mydata.



Rimuovi le righe duplicate in base a una variabile

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using carb variable
distinct(mydata,carb, .keep_all= TRUE)

La funzione .keep_all viene utilizzata per conservare tutte le altre variabili nel frame dei dati di output.



Rimuovi righe duplicate in base a più variabili

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using cyl and vs variables
distinct(mydata, cyl,vs, .keep_all= TRUE)

La funzione .keep_all viene utilizzata per conservare tutte le altre variabili nel frame dei dati di output.

(da: http://www.datasciencemadesimple.com/remove-duplicate-rows-r-using-dplyr-distinct-function/ )


0

Questo problema può anche essere risolto selezionando la prima riga da ciascun gruppo in cui il gruppo sono le colonne in base alle quali vogliamo selezionare valori univoci (nell'esempio condiviso è solo la prima colonna).

Utilizzando la base R:

subset(df, ave(V2, V1, FUN = seq_along) == 1)

#                      V1  V2 V3     V4 V5
#1 platform_external_dbus 202 16 google  1

Nel dplyr

library(dplyr)
df %>% group_by(V1) %>% slice(1L)

O usando data.table

library(data.table)
setDT(df)[, .SD[1L], by = V1]

Se dobbiamo scoprire righe univoche basate su più colonne, aggiungi semplicemente i nomi di queste colonne nella parte di raggruppamento per ciascuna delle risposte sopra.

dati

df <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), 
.Label = "platform_external_dbus", class = "factor"), 
V2 = c(202L, 202L, 202L, 202L, 202L), V3 = c(16L, 16L, 16L, 
16L, 16L), V4 = structure(c(1L, 4L, 3L, 5L, 2L), .Label = c("google", 
"hughsie", "localhost", "space-ghost.verbum", "users.sourceforge"
), class = "factor"), V5 = c(1L, 1L, 1L, 8L, 1L)), class = "data.frame", 
row.names = c(NA, -5L))

0

Ecco una soluzione molto semplice, veloce dplyr/ tidy:

Rimuovi le righe completamente uguali:

library(dplyr)
iris %>% 
  distinct(.keep_all = TRUE)

Rimuovi le righe uguali solo in alcune colonne:

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.