Remover linhas duplicadas


152

Eu li um CSVarquivo em um R data.frame. Algumas das linhas têm o mesmo elemento em uma das colunas. Gostaria de remover linhas duplicadas nessa coluna. Por exemplo:

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

Gostaria apenas de uma dessas linhas, pois as outras têm os mesmos dados na primeira coluna.


3
qual deles você quer? apenas o primeiro? em outras palavras: você quer manter googleou localhostou hughsie?
Anthony Damico

Não importa para esta parte da minha análise estatística. Estou apenas tentando relacionar o título do projeto (primeira coluna), o número de bugs (segunda coluna) e o número de organizações no projeto (terceira coluna).
user1897691

3
legal. Jogue fora colunas desnecessárias e use? unique #
Anthony Damico

Respostas:


186

basta isolar seu quadro de dados nas colunas necessárias e, em seguida, use a função exclusiva: 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
Parece que vai funcionar perfeitamente. Você pode me explicar o que está acontecendo com a [,1:3]parte desse código? Eu sou novo no R e é por isso que estou perguntando o que só posso assumir como uma pergunta óbvia.
user1897691

6
@ user1897691 marca-lo como correto, então;) assistir a este e se você assim, verificar twotorials.com
Anthony Damico

3
Observe que isso removerá todas as colunas, exceto as três primeiras.
GuillaumeL

186

Para as pessoas que vieram aqui procurar uma resposta geral para remoção de linha duplicada, use !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

Resposta de: Removendo linhas duplicadas do quadro de dados R


Eu quero criar uma nova varibale que sinalize se houver uma duplicata em uma determinada variável quase como df $ duplicates <- ifelse (esse valor de linhas na coluna a == valor da linha anterior na coluna a, 1, 0)
jacob


2
Isso mantém o primeiro valor exibido e remove o restante das duplicatas, certo? Ou remove valores aleatoriamente?
News_is_Selection_Bias

@alphabetagamma sim, mantém o primeiro valor exibido
Mehdi Nellen

2
Se você está interessado apenas em duplicatas em determinadas colunas, dizem cols 1 e 2, podemos usardf[!duplicated(df[, 1:2])]
QWR

82

A função distinct()no dplyrpacote executa a remoção duplicada arbitrária, de colunas / variáveis ​​específicas (como nesta pergunta) ou considerando todas as colunas / variáveis. dplyrfaz parte do tidyverse.

Dados e pacote

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

Remova as linhas duplicadas em uma coluna específica (por exemplo, coluna a)

Observe que .keep_all = TRUEmantém todas as colunas; caso contrário, apenas a coluna aseria mantida.

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

Remova as linhas que são duplicatas completas de outras linhas:

distinct(dat)

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

Grande resposta, a propósito, .keep_allé para se manter todas as colunas, para não ser misturado com keepno pandas.
Jason Goal

28

O data.tablepacote também tem uniquee duplicatedmétodos de seu próprio com alguns recursos adicionais.

Tanto o método unique.data.tablequanto o duplicated.data.tablemétodo possuem um byargumento adicional que permite passar um characterou integervetor de nomes de colunas ou seus locais, respectivamente

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

Outra característica importante desses métodos é um enorme ganho de desempenho para conjuntos de dados maiores

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

Você também pode usar dplyra distinct()função! Tende a ser mais eficiente que as opções alternativas, especialmente se você tiver muitas observações.

distinct_data <- dplyr::distinct(yourdata)

1
Esta é a mesma resposta que a resposta de Sam Firke, mas com menos detalhes.
QWR

6

a resposta geral pode ser por exemplo:

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

resultado:

      X1 X2 X3
    1  2  9  6
    2  4  6  7

1
Seja cauteloso ao usar -which, isso levará a erros se não houver duplicatas, o uso df[!(duplicated(df)), ]pode ser mais seguro.
Jason Goal

5

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

Solução:

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

Resultado:

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

Isso tem a sobrecarga de configurar um banco de dados SQL inteiro. cran.r-project.org/web/packages/sqldf/index.html
QWR

O que você quer dizer com configurar um banco de dados SQL inteiro? Essa é uma das principais vantagens: 'com o sqldf, o usuário fica livre de fazer o seguinte, todos os quais são feitos automaticamente: configuração do banco de dados, escrevendo a instrução create table que define cada tabela, importando e exportando para e do banco de dados ' Não é uma solução ideal, mas útil para aqueles familiarizados com o SQL.
Mpalanco

3

Ou você pode aninhar os dados nas colunas 4 e 5 em uma única linha com 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]>

As duplicatas da coluna 2 e 3 agora são removidas para análise estatística, mas você manteve os dados da coluna 4 e 5 em uma tabela e pode voltar ao quadro de dados original a qualquer momento unnest().


1

Remover linhas duplicadas de um quadro de dados

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

Neste conjunto de dados, não há uma única linha duplicada; portanto, ele retornou o mesmo número de linhas que em meus dados.



Remova linhas duplicadas com base em uma variável

library(dplyr)
mydata <- mtcars

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

A função .keep_all é usada para reter todas as outras variáveis ​​no quadro de dados de saída.



Remova linhas duplicadas com base em várias variáveis

library(dplyr)
mydata <- mtcars

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

A função .keep_all é usada para reter todas as outras variáveis ​​no quadro de dados de saída.

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


0

Esse problema também pode ser resolvido selecionando a primeira linha de cada grupo em que o grupo são as colunas com base nas quais queremos selecionar valores únicos (no exemplo compartilhado, é apenas a 1ª coluna).

Usando a base R:

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

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

No dplyr

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

Ou usando data.table

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

Se precisarmos descobrir linhas exclusivas com base em várias colunas, adicione esses nomes de coluna na parte de agrupamento para cada uma das respostas acima.

dados

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

Aqui está um rápido muito simples, dplyr/ tidysolução:

Remova as linhas totalmente iguais:

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

Remova as linhas iguais apenas em determinadas colunas:

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.