Сопоставление/группировка повторяющихся строк (индексов)

Как я могу эффективно сопоставлять/группировать индексы дублированных строк?

Скажем, у меня есть этот набор данных:

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

Я могу найти все индексы дубликатов (включая первый дубликат), используя

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

Но я хочу иметь возможность сопоставлять эти индексы, как показано ниже:

list(
    c(2, 13),
    c(1, 4, 5, 6, 9),
    c(3, 7, 8, 10, 11)
)

Как я могу сделать это эффективно?

Ответы

Ответ 1

Здесь возможно использование "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

Основная идея состоит в том, чтобы создать столбец, который "группирует" другие столбцы (используя .GRP), а также столбец, в котором подсчитывается количество повторяющихся строк (используя .N), а затем фильтровать все, что имеет больше чем один дубликат, и положить столбец "GRP" в list.

Ответ 2

Мы можем использовать dplyr. Используя аналогичную методологию, такую ​​как @AnandaMahto post, мы создаем имя столбца индекса строки (add_rownames(), группу по всем столбцам, мы filter набор данных с количеством строк в каждой группе больше 1, summarise rowname 'до list и извлеките этот столбец 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"