eliminación duplicada por pares del dataframe

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

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) ab 1 AA 2 AB 3 AB 4 BC 5 BA 6 BA 7 CB 8 CB 

Si elimino duplicados, obtengo el siguiente dataframe:

 df[duplicated(df),] ab 3 AB 6 BA 8 CB 

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

Idealmente, podría especificar qué dos columnas comparar, ya que los marcos de datos podrían tener columnas variables y pueden ser bastante grandes.

¡Gracias!

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

 for (i in 1:nrow(df)) { df[i, ] = sort(df[i, ]) } df ab 1 AA 2 AB 3 AB 4 BC 5 AB 6 AB 7 BC 8 BC 

En ese punto, solo se trata de eliminar los elementos duplicados:

 df = df[!duplicated(df),] df ab 1 AA 2 AB 4 BC 

Como el correo de enlace mencionado en los comentarios, su código mantiene los duplicados. Necesita !duplicated para eliminarlos.

Extendiendo la respuesta de Ari, para especificar columnas para verificar si otras columnas también están allí:

 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 abcd 1 AA 10 B 2 AB 8 S 3 AB 7 J 4 BC 3 Q 5 BA 2 I 6 BA 6 U 7 CB 4 L 8 CB 5 V cols = c(1,2) newdf = df[,cols] for (i in 1:nrow(df)){ newdf[i, ] = sort(df[i,cols]) } df[!duplicated(newdf),] abcd 1 AA 8 X 2 AB 7 L 4 BC 2 P 

Las otras respuestas usan un ciclo for para asignar un valor para cada fila. Si bien esto no es un problema si tiene 100 filas, o incluso mil, esperará un tiempo si tiene datos grandes del orden de las filas de 1M.

Robando de la otra respuesta vinculada usando data.table , podrías 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 

Usar apply será una mejor opción que los bucles.

 newDf <- data.frame(t(apply(df,1,sort))) 

Todo lo que necesitas hacer ahora es eliminar duplicados.

 newDf <- newDf[!duplicated(newDf),] 
Intereting Posts