объединить несколько группирующих индексов в один - PullRequest
3 голосов
/ 30 апреля 2020

Я столкнулся с проблемой, когда я должен объединить различные групповые индексы в один. Вот пример:

df <- data.frame(idx1 = c("1_1","1_1","1_2","1_3","1_4","1_4","1_5","1_6","1_6"),
                 idx2 = c("2_1","2_2","2_2","2_3","2_4","2_5","2_6","2_7","2_8"),
                 idx3 = c("3_1","3_1","3_2","3_3","3_3","3_5","3_6","3_7","3_8"))


  idx1 idx2 idx3
1  1_1  2_1  3_1
2  1_1  2_2  3_1
3  1_2  2_2  3_2
4  1_3  2_3  3_3
5  1_4  2_4  3_3
6  1_4  2_5  3_5
7  1_5  2_6  3_6
8  1_6  2_7  3_7
9  1_6  2_8  3_8

Каждый индекс указывает на повторяющиеся строки, обнаруженные разными методами. Я хочу создать индекс, который объединяет три. Например, строки 1 и 2 обозначены как одинаковые idx1, а строки 2 и 3 - idx2, поэтому строки 1, 2 и 3 одинаковы и должны иметь одинаковый индекс группировки.

Строки 4 и 5 имеют одинаковый idx3 индекс группировки, а строки 5 и 6 - одинаковые idx1, поэтому они должны иметь одинаковый индекс группировки, отличающийся от строк 1, 2 и 3.

Мне удалось написать al oop для создания составного индекса:

df$I <- seq(df$idx1)
df$doublon_idx <- as.numeric(NA)
idx_cnt <- 1
for(i in 1:dim(df)[1]){
  if(is.na(df[i,"doublon_idx"])){
    df[i,"doublon_idx" ] <- idx_cnt
    idx_cnt <- idx_cnt + 1
  }
  df[df$I != i & df$idx1 == df[i,]$idx1,"doublon_idx"] <- df[i,"doublon_idx"]
  df[df$I != i & df$idx2 == df[i,]$idx2,"doublon_idx"] <- df[i,"doublon_idx"]
  df[df$I != i & df$idx3 == df[i,]$idx3,"doublon_idx"] <- df[i,"doublon_idx"]
}

(Ожидаемый) вывод:

  idx1 idx2 idx3 I doublon_idx
1  1_1  2_1  3_1 1           1
2  1_1  2_2  3_1 2           1
3  1_2  2_2  3_2 3           1
4  1_3  2_3  3_3 4           2
5  1_4  2_4  3_3 5           2
6  1_4  2_5  3_5 6           2
7  1_5  2_6  3_6 7           3
8  1_6  2_7  3_7 8           4
9  1_6  2_8  3_8 9           4

Но я не доволен этим : оно не обобщено, оно использует al oop, поэтому медленно, когда таблица становится большой. Я уверен, что есть способ слияния или умный способ сделать так, чтобы я не нашел. Что твое ? Можно ли его обобщить на любое число индекса группировки?

dplyr и data.table приветствуются (хотя я предпочитаю data.table, если вы можете сделать оба)

1 Ответ

1 голос
/ 01 мая 2020

Не уверен, насколько быстро это будет на вашем фактическом наборе данных. Вот подход, объединяющий выходные данные igraph и data.table:

library(data.table)
setDT(df)[, rn := .I]

#create edges and idx* are your vertices
DT <- rbindlist(list(
  df[, .(s=idx1, e=idx2, rn)],
  df[, .(s=idx1, e=idx3, rn)],
  df[, .(s=idx2, e=idx3, rn)]))

#find linked clusters
library(igraph)
g <- graph_from_data_frame(DT, directed=FALSE)
cl <- clusters(g)$membership))

#look up cluster for each vertex
DT[, g := cl[s]]

#look up grouping for each vertex
df[unique(DT, by="rn"), on=.(rn), doublon_idx := g]

, например, для вывода 1:

   idx1 idx2 idx3 rn doublon_idx
1:  1_1  2_1  3_1  1           1
2:  1_1  2_2  3_1  2           1
3:  1_2  2_2  3_2  3           1
4:  1_3  2_3  3_3  4           2
5:  1_4  2_4  3_3  5           2
6:  1_4  2_5  3_5  6           2
7:  1_5  2_6  3_6  7           3
8:  1_6  2_7  3_7  8           4
9:  1_6  2_8  3_8  9           4

, например, для 2:

   idx1 idx2 idx3 rn doublon_idx
1:  1_1  2_1  3_1  1           1
2:  1_1  2_2  3_1  2           1
3:  1_2  2_2  3_2  3           1
4:  1_3  2_3  3_3  4           2
5:  1_4  2_4  3_3  5           2
6:  1_4  2_5  3_5  6           2
7:  1_5  2_6  3_6  7           3
8:  1_6  2_7  3_7  8           4
9:  1_6  2_8  3_8  9           4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...