unir - sumar valores de filas repetidas
Coincidir/agrupar filas duplicadas(índices) (2)
¿Cómo puedo unir / agrupar eficientemente los índices de filas duplicadas?
Digamos que tengo este conjunto de datos:
set.seed(14)
dat <- data.frame(mtcars[sample(1:5, 14, TRUE), ])[sample.int(14), ]
rownames(dat) <- NULL
dat
## mpg cyl disp hp drat wt qsec vs am gear carb
## 1 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## 3 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## 4 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## 5 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## 6 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## 7 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## 8 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## 9 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## 10 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## 11 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## 12 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## 13 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## 14 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Puedo encontrar todos los índices de duplicados (incluido el primer duplicado) usando
which_duplicated <- function(dat){
which(duplicated(dat) | duplicated(dat[nrow(dat):1, ])[nrow(dat):1])
}
which_duplicated(dat)
## [1] 1 2 3 4 5 6 7 8 9 10 11 13
Pero quiero poder hacer coincidir esos índices como se ve a continuación:
list(
c(2, 13),
c(1, 4, 5, 6, 9),
c(3, 7, 8, 10, 11)
)
¿Cómo puedo hacer esto de manera eficiente?
Aquí hay una posibilidad usando "data.table":
library(data.table)
as.data.table(dat)[, c("GRP", "N") := .(.GRP, .N), by = names(dat)][
N > 1, list(list(.I)), by = GRP]
## GRP V1
## 1: 1 1,4,5,6,9
## 2: 2 2,13
## 3: 3 3, 7, 8,10,11
La idea básica es crear una columna que "agrupe" las otras columnas (usando .GRP
), así como una columna que cuente cuántas filas duplicadas hay (usando .N
), luego filtre todo lo que tenga más de un duplicado, y poniendo la columna "GRP" en una list
.
Podemos utilizar dplyr
. Usando una metodología similar a la publicación de @ AnandaMahto, creamos un nombre de columna de índice de fila ( add_rownames(
), add_rownames(
por todas las columnas, filter
el conjunto de datos con el número de filas en cada grupo mayor que 1, summarise
el ''rowname'' en una list
y extraer esa columna de la list
.
library(dplyr)
add_rownames(dat) %>%
group_by_(.dots= names(dat)) %>%
filter(n()>1) %>%
summarise(rn= list(rowname))%>%
.$rn
#[[1]]
#[1] "3" "7" "8" "10" "11"
#[[2]]
#[1] "2" "13"
#[[3]]
#[1] "1" "4" "5" "6" "9"