eliminación de duplicados por pares del marco de datos [duplicado]
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!
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
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 !duplicated
para eliminarlos.
Las otras respuestas usan un for
bucle 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