2012-08-14 9 views
5

estoy trabajando en un algoritmo de señal-propagación en R, utilizando igraph (una biblioteca para grafos aleatorios) que implica trabajar con un 2- lista anidada de nivelañadiendo iterativamente y eficientemente elementos a un atributo de lista de vértices en R igraph

Igraph permite adjuntar atributos a vértices (nodos del gráfico), estos pueden ser vectores o listas, pero en mi aplicación necesito listas anidadas.

ver, probar:

library("igraph") 
g <- graph.full(10) # create a fully connected graph with 10 vertices 
V(g)$letters <- list(NULL) # adds a list called "letters" to every vertex 
V(g)$letters # results in a nested list 

me gustaría añadir, en diferentes etapas, algunos elementos predeterminados almacenados en un vector para un determinado subconjunto de las listas de segundo nivel, donde la lista subestablecida es del mismo tamaño que el vector.

El problema es encontrar una manera eficiente de agregar elementos a las listas de segundo nivel.

La forma más simple (y hasta ahora único) para ir es escribir un bucle:

set.seed(1234) 

# every iteration represents a "round" of element addition , 
# followed by other operations. 
# So the attribute "letters" should not be populated in one sitting. 
for (i in 1:10){ 

    # select randomly five 2nd-level lists (vertices) from the 1st-level list 
    # the selected vertices are generated randomly for exposition, 
    # but I need to be able to select them from a well-defined vector (sel.ver) 

    sel.vert <- sample(1:10, 5) 

    # generate elements to add to the lists in the 2nd-level list (vertices) 
    # again, i generate them randomly just to fill the vector, 
    #but the vector could be pre-determined 

    add.elem <- sample(letters, 5) 

    # now add add each element to its own list 
    # notice that the first ELEMENT of add.elem (add.elem[1]) is added 
    # to the attribute of the first SELECTED vertex (V(g)[sel.vert[1]]$letters, 
    # the second element of add.elem with the second SELECTED vertex, and so on.. 

    for (l in 1:5){ 
    V(g)[sel.vert[l]]$letters <- list(c(V(g)[sel.vert[l]]$letters, add.elem[l]))  
    } 
} 

(Me disculpo con el lector experimentado si esto era un espectáculo de horror de las prácticas de programación malas)

A medida que el tamaño de la red inicial crece y se eligen más vértices en cada iteración (un número aleatorio, en lugar de 5), los bucles se vuelven mucho más lentos. Esta debería ser una función de "caballo de batalla", así que me gustaría acelerarla.

leí la respuesta dada a "Efficiently adding or removing elements to a vector or list in R?", es decir, trabajar con vectores siempre que sea posible y preasignación su tamaño, pero creo que no se aplica a mi caso, debido a que:

  1. Creo que con igraph No tengo más remedio que usar listas (al menos en el primer nivel)
  2. en el segundo nivel, las listas tendrán diferentes longitudes finales, dependiendo de qué vértices se seleccionen aleatoriamente. Por lo tanto, es difícil preasignar un vector del tamaño correcto. Incluso si pongo vectores muy grandes en el segundo nivel, inicialmente lleno de NA (lo que resulta en una lista de vectores), no sabría en qué posición agregar elementos (porque la longitud de la lista en cualquier iteración es aleatoria), sin mencionar que necesitaría eliminar AN más tarde.

Esto debería ser un caso particular de agregar elementos (trabajando con) lista anidada. Como tal, yo creo que tal vez una implementación más rápida podría lograrse mediante la sustitución del bucle interno con ddply en plyr o do.call, pero no pude escribir la función de aplicar: get the elements of the (inner) list and add this new element (itself a subset of a vector)

Cualquier comentario o sugerencia es apreciado. Espero que la publicación sea clara.

+1

¿Es necesario realizar alguna operación '' igraph' en G' en cada iteración (es decir, hacer algo más que poblar 'V (g) $ letters'), o ¿es correcto para poblar toda la' V (g) $ letters' data first? – lockedoff

+0

Realizaría otras operaciones entre una ronda de adiciones y la otra, por lo que no puedo llenar las listas anidadas de una sola vez. El bucle es un poco ambiguo, pero necesitaba ilustrar que los atributos de los vértices se rellenan capa por capa.Perdón por la confusion. – MatteoS

Respuesta

2
# number of vertices to add elements to at a time 
nv <- 5 

# selected vertices and elements 
sel.ver <- sample(V(g), nv) 
add.elem <- sample(letters, nv) 

V(g)$letters[sel.ver] <- lapply(1:nv, function(x) { 
    c(add.elem[x], unlist(V(g)$letters[sel.ver[x]])) 
}) 
+0

Gracias, pero eso no es exactamente lo que estaba buscando. Lo siento si no estaba claro, pero estoy buscando una función que * agregue * elementos a la lista interna, en * además de los existentes *. Si ejecuto su función dos veces, el contenido de la segunda iteración * reemplaza * el de la primera. De todos modos, la declaración ddply es un buen punto de partida. ¿Crees que necesito aclarar la pregunta? – MatteoS

+0

Creo que sigo, vea mi edición, puede simplemente combinar en lugar de asignar dentro de la aplicación. – Andy

+0

sí, noté (y mencioné) que podía asignar vectores, en lugar de listas, a los atributos. Sin embargo, dado que el número final de letras será diferente para cada vértice (consulte mi código en la pregunta y los puntos relacionados), creo que una lista es el camino a seguir, pero puedo estar equivocado. – MatteoS

Cuestiones relacionadas