2015-07-01 29 views
6

Ich möchte die letzte Spalte ('selled_result') aus den 3 vorherigen Spalten ('group', 'animal' und 'full') erstellen. Unten ist Code für ein reproduzierbares Beispiel.Zeilenspezifische Einträge aus der Liste entfernen

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 

Grundsätzlich möchte ich "voll" ändern, so dass es nicht das entsprechende "Tier" enthält. Ich habe verschiedene lapply-Befehle ausprobiert, die sowohl Listen- als auch Zeichenversionen dieser Spalten verwenden, aber dieses Problem nicht lösen konnten.

Antwort

3

Hier ist ein möglicher Ansatz

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

Eine weitere Option:

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

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

(Recycling Magie macht die erste Version der Arbeit)

+0

Gleiche Idee in 'dplyr':' Bibliothek (dplyr); Daten%>% mutieren (gewünscht = Map (setdiff, full, animal)) ' –

+0

Dies ergibt eine Liste zurück anstelle des Zeichenvektors (je nach OPs gewünschter Ausgabe). –

+1

Ich lese OP, da es ihnen egal ist, ob sie eine Liste oder einen String bekommen und die Konvertierung trivial ist. – eddi

1

ich auch einen Weg gefunden!

Indem ich 'tier' in eine Liste verwandle, kann ich mapply verwenden.

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

Ihr Ansatz wird eine Liste zurück anstelle eines Zeichenvektors (gemäß Ihrer gewünschten Ausgabe) –

+0

Ah ok guter Punkt, das müsste konvertiert und falls nötig gereinigt werden. – DataBandit

Verwandte Themen