2015-02-08 16 views
5

Ich habe Daten wie folgt aus:Kantenliste Erstellen von in R

ID=c(rep("ID1",3), rep("ID2",2), "ID3", rep("ID4",2)) 
item=c("a","b","c","a","c","a","b","a") 

data.frame(ID,item) 

ID1 a 
ID1 b 
ID1 c 
ID2 a 
ID2 c 
ID3 a 
ID4 b 
ID4 a 

und ich würde es als eine Liste von Kanten wie diese benötigen:

a;b 
b;c 
a;c 
a;c 
b;a 

die ersten drei Kanten von ID1 kommen, vierten von ID2 hat ID3 keine Kanten, also nichts davon und fünfter von ID4. Irgendwelche Ideen, wie man das erreicht? schmelzen/gießen?

Antwort

3

res <- do.call(rbind,with(df, tapply(item, ID, 
     FUN=function(x) if(length(x)>=2) t(combn(x,2))))) 
    paste(res[,1], res[,2], sep=";") 
#[1] "a;b" "a;c" "b;c" "a;c" "b;a" 
+0

Vielen Dank! Ich benutze Ihre vorherige Version: lst <- lapply (Split (Element, DG), Funktion (x) if (Länge (x)> = 2) t (combn (x, 2)) sonst NULL) nodes = as .data.frame (do.call (rbind, lst [! sapply (lst, is.null)])), aber könntest du mir bitte raten, wie "mitnehmen" ID und einige andere Variablen (Alter, Geschlecht etc.) ableiten das Original df und haben sie als Spalten in "Knoten"? – ElinaJ

+0

@ElinaJ Könnten Sie bitte Ihren Beitrag mit dem neuen Datensatz und erwarteten Ergebnis aktualisieren – akrun

+0

Um klar zu sein und die Antworten übereinstimmen, habe ich ein neues Thema: http://stackoverflow.com/questions/28449118/creating-edge-list-with -additional-variables-in-r – ElinaJ

5

Versuchen Ich denke, es würde sollte eine einfache igrpah Lösung dafür sein, aber hier ist eine einfache Lösung mit data.table Paket

library(data.table) 
setDT(df)[, if(.N > 1) combn(as.character(item), 2, paste, collapse = ";"), ID] 

#  ID V1 
# 1: ID1 a;b 
# 2: ID1 a;c 
# 3: ID1 b;c 
# 4: ID2 a;c 
# 5: ID4 b;a 
+0

Schöne Antwort. :) Ich erinnere mich an deinen Kommentar zu 'if (...) else (...)' diese Woche oder letzte Woche. Sie haben sich gefragt, warum 'else()' nicht in einer data.table-Lösung enthalten war. Ich kann mich nicht erinnern, welche Frage das war. Hast du den Grund gefunden, warum man keinen else() -Teil braucht? Wenn Sie Informationen haben, würde ich es gerne wissen. – jazzurro

+0

@jazzurro Ich habe über 'if' nachgedacht, wenn du eine Operation wie' dplyr :: mutate' machen willst und du musst auch Werte für 'else' bekommen, sonst hast du keine" genug "Werte. In dieser Situation mache ich etwas, das "dplyr :: summarise" ähnlich ist, also brauche ich keine "else" -Werte (ich möchte sie wirklich loswerden, also das 'if'). Die Lösung für die damals geäußerte Frage (ich vermute) ist, dass das OP 'NA's in der' else' Anweisung wollte und wenn 'if' in der' data.table' Umgebung läuft und durch ': =' operator definiert ist , erzeugt es 'NA's standardmäßig (wenn' else' nicht angegeben wird). –

+1

Vielen Dank für die klare Erklärung. Die Standardgeneration von NA ist etwas Gutes zu wissen. Nochmals vielen Dank, dass du dir Zeit genommen hast. – jazzurro

2

Hier ist eine skalierbare Lösung, die die verwendet gleiche Kernlogik wie die anderen Lösungen:

library(plyr) 
library(dplyr) 

ID=c(rep("ID1",3), rep("ID2",2), "ID3", rep("ID4",2)) 
item=c("a","b","c","a","c","a","b","a") 

dfPaths = data.frame(ID, item) 
dfPaths2 = dfPaths %>% 
    group_by(ID) %>% 
    mutate(numitems = n(), item = as.character(item)) %>% 
    filter(numitems > 1) 


ddply(dfPaths2, .(ID), function(x) t(combn(x$item, 2))) 
+1

Sie könnten dies in 'dplyr' mit' do' 'dfPaths%>% group_by (ID)%>% filter (n()> 1)%>% do (data.frame (V1 = combn (as.character (. $ item), 2, FUN = einfügen, collapse = ";"))) ' – akrun

+0

@akrun Danke - wusste das nicht. – tchakravarty