¿Qué filas/columnas son duplicadas de qué otras en las matrices R?
Tengo una matriz con muchas filas y columnas, de la siguiente manera:
x <- matrix(c(1, 1, 3, 3, 55, 55, 1, 3, 3, 1,
1, 1, 3, 3, 55, 55, 1, 3, 9, 1), ncol = 2)
Mi problema:
Dentro de cada grupo de filas duplicadas (es decir, cada conjunto de filas idénticas), quiero identificar el índice de la primera fila y asignarlo a todas las ocurrencias dentro de ese grupo. Por ejemplo, hay varias filas duplicadas con ‘1’ en ambas columnas (en las filas 1, 2, 7, 10). En cada una de estas filas quiero el índice de la primera fila, es decir, 1.
x
[,1] [,2]
[1,] 1 1 # primera fila de 1-1. Asignar su índice de fila, 1, a todas las filas 1-1
[2,] 1 1
[3,] 3 3 # primera fila de 3-3. Asignar su índice de fila, 3, a todas las filas 3-3
[4,] 3 3
[5,] 55 55 # primera fila de 55-55. Asignar su índice de fila, 5, a todas las filas 55-55
[6,] 55 55
[7,] 1 1
[8,] 3 3
[9,] 3 9 # primera (y única) fila de 3-9; índice de fila 9
[10,] 1 1
Resultado deseado:
1 1 3 3 5 5 1 3 9 1
Mi intento:
Lo mejor que se me ocurrió es un enfoque complicado basado en duplicados y bucles for
, que no es eficiente ni elegante. También conozco posibles soluciones para data.frames
; aquellas que implican concatenar filas en cadenas también consumen muchos recursos.
Identificar duplicados
duplicate <- duplicated(x, MARGIN = 1)
Identificar primera ocurrencia de cada duplicado
firstDup <- duplicated(x, MARGIN = 1, fromLast = TRUE) & !duplicate
indices <- which(firstDup)
Inicializar índice para filas únicas
index <- seq_len(dim(x)[1])
cf <- duplicate
for (i in indices) {
# Los duplicados deben ocurrir después de la primera aparición
cf[seq_len(i)] <- FALSE
dups <- apply(x[cf, , drop = FALSE], 1L, identical, x[i, ])
index[which(cf)[dups]] <- i
}
index
¿Existe una solución elegante utilizando R base?
davy.ai
Sí, hay una solución más elegante utilizando funciones base de R. Puedes usar
match()
para obtener el primer índice de cada fila única, y luego usarreplace()
para reemplazar todas las ocurrencias de cada fila duplicada con ese índice. Aquí está el código:Este código primero usa
match(unique(x), x)
para obtener el índice de la primera ocurrencia de cada fila única. El argumentonomatch = 0
asegura que las filas que no tienen coincidencia (es decir, aquellas que solo ocurren una vez) devuelvan 0.A continuación, se utiliza
match(x, unique(x))
para obtener el índice de la fila única que cada fila enx
coincide. Nuevamente, se utilizanomatch = 0
para asegurarse de que las filas no duplicadas devuelvan 0.Finalmente, se utiliza
replace()
para reemplazar cada fila duplicada con el primer índice de esa fila. Esto se hace indexando enfirstIndex[match(x[duplicated(x), ], unique(x))]
, lo cual devuelve el índice de la primera ocurrencia de cada fila duplicada. La funciónmatch()
se utiliza para encontrar el índice de cada fila duplicada enunique(x)
, yduplicated(x)
se utiliza para seleccionar solo las filas duplicadas. El vector resultante de índices luego se utiliza para reemplazar las filas duplicadas en el vector original.¡Espero que esto ayude!