2016-08-05 11 views
2

Ich versuche zu setze Operationen zwischen den Vektoren in einer Liste Spalte wie this gespeichert.setze Operation innerhalb einer Listenspalte

DT <- data.table(exp = c("exp1", "exp2", "exp2"), 
        sample = c(1L, 1L, 2L), 
        listdata = list(c(2L,5L), c(2L,3L,5L,7L), c(1L,2L,6L))) 

> DT 
    exp sample listdata 
1: exp1  1  2,5 
2: exp2  1 2,3,5,7 
3: exp2  2 1,2,6 

während sehr umständlich, kann ich

DT$inc = list(setdiff(unlist(DT$listdata[2]), unlist(DT$listdata[1]))) 

tun und eine neue Liste Spalte mit dem Wert c(3,7) erhalten. Aber wenn ich versuche, den Unterschied zwischen der aktuellen Zeile zu berechnen und der ersten Reihe mit

DT$inc = list(list(setdiff(unlist(DT$listdata, recursive = FALSE), unlist(DT$listdata[1])))) 

erwarten Sie eine neue Spalte „inc“

0 
c(3,7) 
c(1,6) 

ich c(3,7,1,6). Anscheinend unlist flachte die ganze Liste Spalte zusammen. Irgendeine Idee was ist los?

Ich lerne auch dplyr und data.table. Es würde also wirklich helfen, wenn Sie Lösungen mit einer von ihnen anbieten können.

Antwort

5

[...] Ich versuche, den Unterschied zwischen der aktuellen Zeile und der ersten Reihe

Gut zu berechnen, Sie ... tun können

DT[, inc := .(Map(setdiff, listdata, listdata[1L]))] 

#  exp sample listdata inc 
# 1: exp1  1  2,5  
# 2: exp2  1 2,3,5,7 3,7 
# 3: exp2  2 1,2,6 1,6 

Aber ich denke, es ist viel besser, einfach nicht mit Listenspalten zu arbeiten.


nicht mit der Liste Spalten arbeiten könnte wie folgt aussehen ...

DT[, r := .I] 
DT2 = DT[,c(.SD[rep(.I, lengths(listdata))], .(v = unlist(listdata))), .SDcols=!"listdata"] 

#  exp sample r v 
# 1: exp1  1 1 2 
# 2: exp1  1 1 5 
# 3: exp2  1 2 2 
# 4: exp2  1 2 3 
# 5: exp2  1 2 5 
# 6: exp2  1 2 7 
# 7: exp2  2 3 1 
# 8: exp2  2 3 2 
# 9: exp2  2 3 6 

Dann einfach arbeiten wir mit diesem Datensatz, und tun können

DT2[!DT2[r==1L], on="v"] 

#  exp sample r v 
# 1: exp2  1 2 3 
# 2: exp2  1 2 7 
# 3: exp2  2 3 1 
# 4: exp2  2 3 6 
+0

Die answe rs kommen schnell. Kannst du die Verwendung von 'listdata [1L]' erklären? Die 'dplyr' Version unten muss' [[''. Außerdem bin ich nicht sicher, ob es eine gute Idee ist, die Liste auf mehrere Zeilen zu verteilen, wenn die Listenlänge sehr lang ist. – Dong

+0

@Dong Yeah, ich habe diesen Unterschied auch bemerkt. 'listdata [[1]]' (in Psidoms Antwort) ist das erste Element der Wahrheit; während 'listdata [1]' ein * slice * der Liste ist, die nur das erste Element enthält. Also, wenn "Lst = list (11, 22)", dann ist "Lst [[1]]" '11', während' Lst [1] '' list (11) 'ist. Das 'L' in' 1L' verwendet nur eine ganzzahlige Version von 1. – Frank

+0

Der Grund, warum ich einen brauche und er den anderen braucht, liegt in Rs Konzept des "Recyclings" und den Unterschieden in den zwei Funktionen, die wir benutzt haben. Wenn Sie über das Recycling und die Dokumente '? Lapply' und'? Map' lesen, sollte es hoffentlich Sinn machen. Wenn nicht, probieren Sie vielleicht den Chat aus: http://chat.stackoverflow.com/rooms/25312/r-public – Frank

3

Hier eine entsprechende dplyr Lösung :

library(dplyr) 
DT %>% mutate(inc = lapply(listdata, setdiff, listdata[[1]])) 

# exp sample listdata inc 
#1 exp1  1  2, 5  
#2 exp2  1 2, 3, 5, 7 3, 7 
#3 exp2  2 1, 2, 6 1, 6 
Verwandte Themen