2015-07-01 8 views
6

Chciałbym utworzyć ostatnią kolumnę ("desired_result") z 3 wcześniejszych kolumn ("grupa", "zwierzę" i "pełna"). Poniżej znajduje się kod dla odtwarzalnego przykładu.Usuń pozycje specyficzne dla wiersza z listy

library(data.table) 
data = data.table(group = c(1,1,1,2,2,2), animal = c('cat', 'dog', 'pig', 'giraffe', 'lion', 'tiger'), desired_result = c('dog, pig', 'cat, pig', 'cat, dog', 'lion, tiger', 'giraffe, tiger', 'giraffe, lion')) 
data[, full := list(list(animal)), by = 'group'] 
data = data[, .(group, animal, full, desired_result)] 

data 
    group animal    full desired_result 
1:  1  cat   cat,dog,pig  dog, pig 
2:  1  dog   cat,dog,pig  cat, pig 
3:  1  pig   cat,dog,pig  cat, dog 
4:  2 giraffe giraffe,lion,tiger lion, tiger 
5:  2 lion giraffe,lion,tiger giraffe, tiger 
6:  2 tiger giraffe,lion,tiger giraffe, lion 

Zasadniczo chciałbym zmodyfikować "pełny", aby nie zawierał odpowiedniego "zwierzęcia". Próbowałem różnych lapply poleceń przy użyciu zarówno listy i wersje znaków tych kolumn, ale nie były w stanie rozwiązać ten problem.

Odpowiedz

3

Oto możliwym rozwiązaniem

data[, desired_result := { 
     temp <- unique(unlist(full)) 
     toString(temp[-match(animal, temp)]) 
     }, by = .(group, animal)] 
data 
# group animal    full desired_result 
# 1:  1  cat  cat,dog,pig  dog, pig 
# 2:  1  dog  cat,dog,pig  cat, pig 
# 3:  1  pig  cat,dog,pig  cat, dog 
# 4:  2 giraffe giraffe,lion,tiger lion, tiger 
# 5:  2 lion giraffe,lion,tiger giraffe, tiger 
# 6:  2 tiger giraffe,lion,tiger giraffe, lion 
3

Inna opcja:

data[, desired := .(Map(setdiff, list(animal), as.list(animal))), by = group] 

#or if starting from full 
data[, desired := .(Map(setdiff, full, animal))] 

(recykling magia sprawia, że ​​pierwsze prace wersja)

+0

Ten sam pomysł w 'dplyr':' library (dplyr); data%>% mutate (pożądana = mapa (setdiff, pełna, zwierzę)) ' –

+0

To da listę z powrotem zamiast wektora znaków (zgodnie z oczekiwanymi wynikami). –

+1

Czytam OP, ponieważ nie obchodzi ich, czy dostaną listę lub ciąg znaków, a konwersja jest banalna. – eddi

1

znalazłem sposób, jak dobrze!

Zmieniając "zwierzę" w listę, mogę użyć mapply.

data$animal = strsplit(data$animal, ' ') 
data$check = mapply(function(x, y) {list(x[x != y]) }, data$full, data$animal) 

data 
group animal    full desired_result   check 
1:  1  cat  cat,dog,pig  dog, pig  dog,pig 
2:  1  dog  cat,dog,pig  cat, pig  cat,pig 
3:  1  pig  cat,dog,pig  cat, dog  cat,dog 
4:  2 giraffe giraffe,lion,tiger lion, tiger lion,tiger 
5:  2 lion giraffe,lion,tiger giraffe, tiger giraffe,tiger 
6:  2 tiger giraffe,lion,tiger giraffe, lion giraffe,lion 
+0

Twoje podejście zwróci listę z powrotem zamiast wektora znaków (zgodnie z pożądanym wyjściem). –

+0

Ach, dobrze, że trzeba by było przekonwertować i wyczyścić, jeśli to konieczne. – DataBandit