2015-02-08 15 views
5

Ho dati in questo modo:Creazione di un elenco vantaggio 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 

e mi avrebbe bisogno come un elenco di bordi in questo modo:

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

i primi tre bordi provenienti da ID1, quarta da ID2, ID3 non ha spigoli, quindi niente da questo e quinto da ID4. Qualche idea su come realizzare questo? fondere/cast?

risposta

3

Prova

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

Grazie! Sto usando la tua versione precedente: lst <- lapply (split (item, DG), function (x) if (length (x)> = 2) t (combn (x, 2)) else NULL) nodes = as .data.frame (do.call (rbind, lst [! sapply (lst, is.null)])), ma potresti consigliarmi su come ID "take along" e alcune altre variabili (età, sesso ecc.) da il file originale df e averli come colonne in "nodi"? – ElinaJ

+0

@ElinaJ Potresti aggiornare il tuo post con il nuovo set di dati e il risultato previsto – akrun

+0

Per essere chiari e corrispondere alle risposte, ho creato un nuovo argomento: http://stackoverflow.com/questions/28449118/creating-edge-list-with -additional-variables-in-r – ElinaJ

5

direi ci dovrebbe essere una soluzione semplice igrpah per questo, ma qui è una soluzione semplice utilizzando data.table pacchetto

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

Risposta piacevole. :) Ricordo il tuo commento relativo a "if (...) else (...)" questa settimana o la scorsa settimana. Ti stavi chiedendo perché 'else()' non fosse in una soluzione data.table. Non riesco a ricordare quale domanda fosse. Hai trovato il motivo per cui non hai bisogno della parte else()? Se hai informazioni, mi piacerebbe saperlo. – jazzurro

+0

@jazzurro Mi stavo chiedendo di "se" quando si vuole eseguire un'operazione come "dplyr :: mutate" e si devono ottenere valori anche per "else", altrimenti non si avranno valori "sufficienti". In questa situazione sto facendo qualcosa di simile a 'dplyr :: sumarise', quindi non ho bisogno dei valori di' else' (in realtà voglio liberarmene, quindi il 'if'). La soluzione alla domanda allora (suppongo) è che l'OP voleva 'NA's nell'istruzione' else', e quando 'if' è in esecuzione nell'ambiente' data.table' e viene definito da ': =' operatore , genera 'NA' di default (se' else' non viene fornito). –

+1

Grazie mille per la chiara spiegazione. La generazione predefinita di NA è qualcosa di buono da sapere. Ancora una volta, grazie per aver dedicato tempo. – jazzurro

2

Ecco una soluzione più scalabile che utilizza il stessa logica di base delle altre soluzioni:

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

Si può fare ciò all'interno di 'dplyr' usando' do' 'dfPaths%>% group_by (ID)%>% filter (n()> 1)%>% do (data.frame (V1 = combn (as.character (. $ item), 2, FUN = paste, collapse = ";"))) ' – akrun

+0

@akrun Grazie - non lo sapevo. – tchakravarty

Problemi correlati