2015-06-24 2 views
2

У меня есть data.tableDT следующим образом.Разделите значения разделенных запятыми значений в `data.table`

DT <- structure(list(ID = c("Bats", "HL", "JL", "Spidey", "Supes", 
"X"), List1 = c("Morrison, Brubaker, Daniel, Loeb", "David, Bryne, Lee", 
"", "Loeb, Lee", "Moore, Siegel, Millar", "Bendis, Whendon"), 
    List2 = c("Rucka, Kane, Morrison", "Lee, Mantlo, Bryne", 
    "Meltzer, Sekowsky, Morrison", "Waid, Yost, Kirby, Lee", 
    "", "Claremont, Whendon, Morrison")), .Names = c("ID", "List1", 
"List2"), row.names = c(NA, -6L), class = c("data.table", "data.frame" 
), .internal.selfref = NULL, sorted = "ID") 

DT

 ID       List1      List2 
1: Bats Morrison, Brubaker, Daniel, Loeb  Rucka, Kane, Morrison 
2:  HL    David, Bryne, Lee   Lee, Mantlo, Bryne 
3:  JL         Meltzer, Sekowsky, Morrison 
4: Spidey      Loeb, Lee  Waid, Yost, Kirby, Lee 
5: Supes   Moore, Siegel, Millar        
6:  X     Bendis, Whendon Claremont, Whendon, Morrison 

Я хотел бы объединить два списка построчно в столбцах DT$List1 и DT$List2 вместе без дублей.

Я могу сделать это с помощью apply следующим образом.

DT$merged <- apply(DT,1,function(vec){ 
    paste(unique(strsplit(paste(vec[2],vec[3],sep=", "),", ")[[1]]),collapse=", ") 
}) 

    DT 
     ID       List1      List2 
1: Bats Morrison, Brubaker, Daniel, Loeb  Rucka, Kane, Morrison 
2:  HL    David, Bryne, Lee   Lee, Mantlo, Bryne 
3:  JL         Meltzer, Sekowsky, Morrison 
4: Spidey      Loeb, Lee  Waid, Yost, Kirby, Lee 
5: Supes   Moore, Siegel, Millar        
6:  X     Bendis, Whendon Claremont, Whendon, Morrison 
              merged 
1: Morrison, Brubaker, Daniel, Loeb, Rucka, Kane 
2:      David, Bryne, Lee, Mantlo 
3:     , Meltzer, Sekowsky, Morrison 
4:     Loeb, Lee, Waid, Yost, Kirby 
5:       Moore, Siegel, Millar 
6:   Bendis, Whendon, Claremont, Morrison 

Как эффективно получить тот же результат с data.table без «» в начале и в конце из-за пустые ячейки?

+1

Я уверен, что есть лучший способ сделать это с помощью пасты, но вы всегда можете обернуть это в если-то заявление, в котором, если обе колонки имеют значения вы используете эту функцию, но если только один столбец имеет значение, вы просто используете данные из этого столбца. –

ответ

4
DT[, merged := toString(unique(c(strsplit(List1, split = ", ")[[1]], 
           strsplit(List2, split = ", ")[[1]]))), by = ID][] 
#  ID       List1      List2 
#1: Bats Morrison, Brubaker, Daniel, Loeb  Rucka, Kane, Morrison 
#2:  HL    David, Bryne, Lee   Lee, Mantlo, Bryne 
#3:  JL         Meltzer, Sekowsky, Morrison 
#4: Spidey      Loeb, Lee  Waid, Yost, Kirby, Lee 
#5: Supes   Moore, Siegel, Millar        
#6:  X     Bendis, Whendon Claremont, Whendon, Morrison 
#           merged 
#1: Morrison, Brubaker, Daniel, Loeb, Rucka, Kane 
#2:      David, Bryne, Lee, Mantlo 
#3:     Meltzer, Sekowsky, Morrison 
#4:     Loeb, Lee, Waid, Yost, Kirby 
#5:       Moore, Siegel, Millar 
#6:   Bendis, Whendon, Claremont, Morrison 

Или замените «на» с 1:nrow(DT) если ваш ID столбец не является уникальным.

+4

Вместо 'unique (c (x, y))', 'union (x, y)', похоже, работает. Вот что, используя '.SD':' DT [, merged: = toString (Reduce (union, lapply (.SD, function (x) strsplit (x, split = ",") [[1]]))), by = ID] [] ' – Frank

3

Попробуйте

library(data.table)#v1.9.5+ 
DT[, merged := do.call(paste, c(.SD, sep=", ")), .SDcols= List1:List2 
][, merged:=unlist(lapply(strsplit(merged, ", "), 
      function(x) toString(unique(x))))] 
#  ID       List1      List2 
#1: Bats Morrison, Brubaker, Daniel, Loeb  Rucka, Kane, Morrison 
#2:  HL    David, Bryne, Lee   Lee, Mantlo, Bryne 
#3:  JL         Meltzer, Sekowsky, Morrison 
#4: Spidey      Loeb, Lee  Waid, Yost, Kirby, Lee 
#5: Supes   Moore, Siegel, Millar        
#6:  X     Bendis, Whendon Claremont, Whendon, Morrison 
#           merged 
#1: Morrison, Brubaker, Daniel, Loeb, Rucka, Kane 
#2:      David, Bryne, Lee, Mantlo 
#3:     , Meltzer, Sekowsky, Morrison 
#4:     Loeb, Lee, Waid, Yost, Kirby 
#5:       Moore, Siegel, Millar 
#6:   Bendis, Whendon, Claremont, Morrison 

Или мы могли бы использовать regex после do.call(paste для удаления повторяющихся элементов

DT[, merged := gsub('^,\\s*|(\\b\\S+\\b)(?=.*\\b\\1\\b.*),\\s*|,\\s*$', '', 
    do.call(paste, c(.SD, sep=", ")), perl=TRUE), .SDcols = List1:List2] 
# ID       List1      List2 
#1: Bats Morrison, Brubaker, Daniel, Loeb  Rucka, Kane, Morrison 
#2:  HL    David, Bryne, Lee   Lee, Mantlo, Bryne 
#3:  JL         Meltzer, Sekowsky, Morrison 
#4: Spidey      Loeb, Lee  Waid, Yost, Kirby, Lee 
#5: Supes   Moore, Siegel, Millar        
#6:  X     Bendis, Whendon Claremont, Whendon, Morrison 
#           merged 
#1: Brubaker, Daniel, Loeb, Rucka, Kane, Morrison 
#2:      David, Lee, Mantlo, Bryne 
#3:     Meltzer, Sekowsky, Morrison 
#4:     Loeb, Waid, Yost, Kirby, Lee 
#5:       Moore, Siegel, Millar 
#6:   Bendis, Claremont, Whendon, Morrison 
3

Это может быть другой способ

DT[, merged:= paste(union(unlist(strsplit(List1, ', ')), 
       unlist(strsplit(List2, ', '))), collapse = ', '), by = ID] 

#> DT 
#  ID       List1      List2 
#1: Bats Morrison, Brubaker, Daniel, Loeb  Rucka, Kane, Morrison 
#2:  HL    David, Bryne, Lee   Lee, Mantlo, Bryne 
#3:  JL         Meltzer, Sekowsky, Morrison 
#4: Spidey      Loeb, Lee  Waid, Yost, Kirby, Lee 
#5: Supes   Moore, Siegel, Millar        
#6:  X     Bendis, Whendon Claremont, Whendon, Morrison 
#           merged 
#1: Morrison, Brubaker, Daniel, Loeb, Rucka, Kane 
#2:      David, Bryne, Lee, Mantlo 
#3:     Meltzer, Sekowsky, Morrison 
#4:     Loeb, Lee, Waid, Yost, Kirby 
#5:       Moore, Siegel, Millar 
#6:   Bendis, Whendon, Claremont, Morrison 
0

Простой пример, чтобы показать другой подход. Функция trimComma просто отбрасывает запятые в начале и в конце. Он также урезает повторять запятые и могут быть легко использованы с paste

trimComma <-function(x) 
{ 
    gsub(",,",",",gsub("^,+|,+$|","",x)) 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^