eliminación de duplicados por pares del marco de datos [duplicado]

Resuelto user3141121 asked hace 54 años • 4 respuestas

Esto parece un problema simple pero parece que no puedo resolverlo. Me gustaría eliminar duplicados de un marco de datos (df) si dos columnas tienen los mismos valores, incluso si esos valores están en orden inverso . Lo que quiero decir es que digamos que tiene el siguiente marco de datos:

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

  a b
1 A A
2 A B
3 A B
4 B C
5 B A
6 B A
7 C B
8 C B

Si ahora elimino duplicados, obtengo el siguiente marco de datos:

df[duplicated(df),]

  a b
3 A B
6 B A
8 C B

Sin embargo, también me gustaría eliminar la fila 6 en este marco de datos, ya que "A", "B" es lo mismo que "B", "A". ¿Cómo puedo hacer esto automáticamente?

Lo ideal sería especificar qué dos columnas comparar, ya que los marcos de datos pueden tener diferentes columnas y pueden ser bastante grandes.

¡Gracias!

user3141121 avatar Jan 01 '70 08:01 user3141121
Aceptado

Ampliando la respuesta de Ari, para especificar columnas y verificar si también hay otras columnas:

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

df$c = sample(1:10,8)
df$d = sample(LETTERS,8)
df
  a b  c d
1 A A 10 B
2 A B  8 S
3 A B  7 J
4 B C  3 Q
5 B A  2 I
6 B A  6 U
7 C B  4 L
8 C B  5 V

cols = c(1,2)
newdf = df[,cols]
for (i in 1:nrow(df)){
    newdf[i, ] = sort(df[i,cols])
}

df[!duplicated(newdf),]
  a b c d
1 A A 8 X
2 A B 7 L
4 B C 2 P
rnso avatar Aug 14 '2014 01:08 rnso

Una solución es ordenar primero cada fila de df:

for (i in 1:nrow(df))
{
    df[i, ] = sort(df[i, ])
}
df

a b
1 A A
2 A B
3 A B
4 B C
5 A B
6 A B
7 B C
8 B C

En ese punto sólo es cuestión de eliminar los elementos duplicados:

df = df[!duplicated(df),]
df
  a b 
1 A A
2 A B
4 B C

Como thelatemail mencionó en los comentarios, su código en realidad mantiene los duplicados. Necesitas usar !duplicatedpara eliminarlos.

Ari avatar Aug 14 '2014 00:08 Ari

Las otras respuestas usan un forbucle para asignar un valor a todas y cada una de las filas. Si bien esto no es un problema si tiene 100 filas, o incluso mil, tendrá que esperar un tiempo si tiene datos grandes del orden de 1 millón de filas.

Robando de la otra respuesta vinculada usando data.table, puedes intentar algo como:

df[!duplicated(data.frame(list(do.call(pmin,df),do.call(pmax,df)))),]

Un punto de referencia de comparación con un conjunto de datos más grande ( df2):

df2 <- df[sample(1:nrow(df),50000,replace=TRUE),]

system.time(
  df2[!duplicated(data.frame(list(do.call(pmin,df2),do.call(pmax,df2)))),]
)
# user  system elapsed 
# 0.07    0.00    0.06 

system.time({
  for (i in 1:nrow(df2))
  {
      df2[i, ] = sort(df2[i, ])
  }
  df2[!duplicated(df2),]
}
)
#   user  system elapsed 
#  42.07    0.02   42.09 
thelatemail avatar Aug 14 '2014 01:08 thelatemail