identificar grupos de episodios vinculados que encadenan

Toma este dataframe simple de identificadores vinculados:

test  test id1 id2 1 10 1 2 10 36 3 1 24 4 1 45 5 24 300 6 8 11 

Ahora quiero agrupar todos los identificadores que enlazan. Por ‘enlace’, me refiero a seguir a través de la cadena de enlaces para que todos los identificadores de un grupo estén etiquetados juntos. Una especie de estructura de ramificación. es decir:

 Group 1 10 --> 1, 1 --> (24,45) 24 --> 300 300 --> NULL 45 --> NULL 10 --> 36, 36 --> NULL, Final group members: 10,1,24,36,45,300 Group 2 8 --> 11 11 --> NULL Final group members: 8,11 

Ahora sé más o menos la lógica que quisiera, pero no sé cómo la implementaría elegantemente. Estoy pensando en un uso recursivo de match o %in% para ir por cada twig, pero estoy realmente perplejo esta vez.

El resultado final que estaría persiguiendo es:

 result  result group id 1 1 10 2 1 1 3 1 24 4 1 36 5 1 45 6 1 300 7 2 8 8 2 11 

El paquete Bioconductor RBGL (una interfaz R para la biblioteca de gráficos BOOST) contiene una función, connectedComp() , que identifica los componentes conectados en un gráfico, justo lo que usted desea.

(Para usar la función, primero deberá instalar el gráfico y los paquetes RBGL , disponibles aquí y aquí ).

 library(RBGL) test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11)) ## Convert your 'from-to' data to a 'node and edge-list' representation ## used by the 'graph' & 'RBGL' packages g <- ftM2graphNEL(as.matrix(test)) ## Extract the connected components cc <- connectedComp(g) ## Massage results into the format you're after ld <- lapply(seq_along(cc), function(i) data.frame(group = names(cc)[i], id = cc[[i]])) do.call(rbind, ld) # group id # 1 1 10 # 2 1 1 # 3 1 24 # 4 1 36 # 5 1 45 # 6 1 300 # 7 2 8 # 8 2 11 

Aquí hay una respuesta alternativa que descubrí después de que Josh dio un paso en la dirección correcta. Esta respuesta usa el paquete igraph . Para aquellos que están buscando y encuentran esta respuesta, mi conjunto de datos de test se conoce como una “lista de bordes” o “lista de adyacencia” en la teoría de grafos ( http://en.wikipedia.org/wiki/Graph_theory )

 library(igraph) test <- data.frame(id1=c(10,10,1,1,24,8 ),id2=c(1,36,24,45,300,11)) gr.test <- graph.data.frame(test) links <- data.frame(id=unique(unlist(test)),group=clusters(gr.test)$membership) links[order(links$group),] # id group #1 10 1 #2 1 1 #3 24 1 #5 36 1 #6 45 1 #7 300 1 #4 8 2 #8 11 2 

Sin usar paquetes:

 # 2 sets of test data mytest <- data.frame(id1=c(10,10,3,1,1,24,8,11,32,11,45),id2=c(1,36,50,24,45,300,11,8,32,12,49)) test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11)) grouppairs <- function(df){ # from wide to long format; assumes df is 2 columns of related id's test <- data.frame(group = 1:nrow(df),val = unlist(df)) # keep moving to next pair until all same values have same group i <- 0 while(any(duplicated(unique(test)$val))){ i <- i+1 # get group of matching values matches <- test[test$val == test$val[i],'group'] # change all groups with matching values to same group test[test$group %in% matches,'group'] <- test$group[i] } # renumber starting from 1 and show only unique values in group order test$group <- match(test$group, sort(unique(test$group))) unique(test)[order(unique(test)$group), ] } # test grouppairs(test) grouppairs(mytest) 
    Intereting Posts