Сложное слияние между строками при совместном использовании значений с другими группами в R

#r #dplyr

#r #dplyr

Вопрос:

Привет всем, у меня есть фрейм данных, такой как ::

   Families Species   Event      Groups
1  A,B,C,D     SP1 4,5,6,1 G1,G2,G3,G4
2    A,A,C     SP2   4,4,2       G1,G4
3        B     SP2       5          G1
4        A     SP3       2          G8
5        C     SP3       1          G9
 

и идея заключается в том, что я хотел бы объединить строки, Species когда :

  • по крайней мере , один элемент Families Event и Groups является общим для другого Species .

Так, например, мы видим, что для SP2 row2 этого :

  • в Families A также присутствует в Families of SP1 (A, B, C, D)
  • в Event 4 также присутствует в Event SP1 (4,5,6,1)
  • в группах G1 и G4 также присутствуют в Groups оф SP1 (G1, G2,G3, G4)

И

для SP2 row3 этого :

  • в Families B также присутствует в Families of SP1 (A, B, C, D)
  • in Event 5 также присутствует в Event of SP1 (4,5,6,1)
  • в группах G1 также присутствует в Groups оф SP1 (G1, G2, G3, G4)

затем я могу объединить rows and row3 , поскольку они оба имеют общие значения с row1 of SP1 .

итак, вот ожидаемый результат:

   Families Species   Event      Groups
1  A,B,C,D     SP1 4,5,6,1 G1,G2,G3,G4
2  A,A,C,B SP2,SP2 4,4,2,5    G1,G4,G1
3        A     SP3       2          G8
4        C     SP3       1          G9
 

Если у кого-то есть идея, это было бы потрясающе, большое вам спасибо за вашу помощь и время.

Вот эти данные :

     structure(list(Families = structure(c(3L, 2L, 4L, 1L, 5L), .Label = c("A", 
    "A,A,C", "A,B,C,D", "B", "C"), class = "factor"), Species = structure(c(1L, 
    2L, 2L, 3L, 3L), .Label = c("SP1", "SP2", "SP3"), class = "factor"), 
        Event = structure(c(4L, 3L, 5L, 2L, 1L), .Label = c("1", 
        "2", "4,4,2", "4,5,6,1", "5"), class = "factor"), Groups = structure(c(2L, 
        3L, 1L, 4L, 5L), .Label = c("G1", "G1,G2,G3,G4", "G1,G4", 
        "G8", "G9"), class = "factor")), class = "data.frame", row.names = c(NA, 
    -5L))
 

Ответ №1:

вот попытка, используя data.table (но если вы посмотрите, это довольно легко сделать без data.table, просто data.table теперь мой родной язык) :

 dt <-  structure(list(Families = structure(c(3L, 2L, 4L, 1L, 5L), .Label = c("A", 
                                                                             "A,A,C", "A,B,C,D", "B", "C"), class = "factor"), Species = structure(c(1L, 
                                                                                                                                                     2L, 2L, 3L, 3L), .Label = c("SP1", "SP2", "SP3"), class = "factor"), 
                      Event = structure(c(4L, 3L, 5L, 2L, 1L), .Label = c("1", 
                                                                          "2", "4,4,2", "4,5,6,1", "5"), class = "factor"), Groups = structure(c(2L, 
                                                                                                                                                 3L, 1L, 4L, 5L), .Label = c("G1", "G1,G2,G3,G4", "G1,G4", 
                                                                                                                                                                             "G8", "G9"), class = "factor")), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                  -5L))
library(data.table)                                                                                                                                                                                                                                           
setDT(dt)
library(stringr)

dt[, Families := as.character(Families)]
dt[, Event := as.character(Event)]
dt[, Groups := as.character(Groups)]
dt[, n := row.names(.SD) ]

dt2 <- merge(dt, 
      dt, 
      by = "Species")[n.x >= n.y]

dt2[, testFamilies := length(intersect(unlist(strsplit(Families.x, ",")), unlist(strsplit(Families.y, ",")))) > 0, by = 1:nrow(dt2)]
dt2[, testEvents := length(intersect(unlist(strsplit(Event.x, ",")), unlist(strsplit(Event.y, ",")))) > 0, by = 1:nrow(dt2)]
dt2[, testGroups := length(intersect(unlist(strsplit(Groups.x, ",")), unlist(strsplit(Groups.y, ",")))) > 0, by = 1:nrow(dt2)]

dt2[, Families := paste0(unique(unlist(strsplit(paste(Families.x, Families.y, sep = ","), ","))), collapse = ","), by = 1:nrow(dt2)]
dt2[, Event := paste0(unique(unlist(strsplit(paste(Event.x, Event.y, sep = ","), ","))), collapse = ","), by = 1:nrow(dt2)]
dt2[, Groups := paste0(unique(unlist(strsplit(paste(Groups.x, Groups.y, sep = ","), ","))), collapse = ","), by = 1:nrow(dt2)]

dt2[(testFamilies == TRUE | testGroups == TRUE | testEvents == TRUE)
    amp; !n.x %in% dt2[(testFamilies == TRUE | testGroups == TRUE | testEvents == TRUE) amp; n.x != n.y, n.y]
    amp; !n.y %in% dt2[(testFamilies == TRUE | testGroups == TRUE | testEvents == TRUE) amp; n.x != n.y, n.x], 
                     .(Species, Families, Event, Groups)]



 

Комментарии:

1. Здравствуйте, спасибо, но я попробовал ваш код и не получил ожидаемого результата, dt2 не имеет объединенной строки между строками 2 и 3…

2. Я не понимаю .. В ваших семействах примеров для строк 2 и 3 есть «A, A, C» и «B» .. сын, я думаю, они не должны сливаться .. О .. хорошо, я пропустил «хотя бы один из ..» Я отредактирую свой ответ, чтобы он соответствовал вашей цели..

3. В SP2 row2 также Familly A находится в SP2 row1 amp; В SP2 row3 Familly B SP2 row1 , поэтому я объединяю два SP2 row2 и row3 в одну строку. Смотрите в примере, я объяснил это лучше с более подробной информацией. Хорошо, я видел, что вы только что увидели этот момент, спасибо.

4. И где-то в моем коде есть небольшая ошибка .. Я смотрю на это ..

5. Спасибо, но опять же, это не похоже на ожидаемый результат… Строка 1 была удалена, и слияние между строками 2 и строкой 3 не происходит, как ожидалось… Вы можете увидеть, каков точный ожидаемый результат в сообщении, если вы хотите сослаться на него