Cómo atraer una red desde un vector de cadena

Estoy tratando de crear un igraph objeto dividiendo un vector de cadenas en un personaje especial ("cada"). Uso un for-loop para crear un vector y convertirlo en un gráfico de red. El código funciona pero es extremadamente ineficiente en vectores muy largos (redes grandes).

¿Hay una manera de mejorar el proceso con tuberías y mapeo? Gracias por adelantado

require(graph)
data <- data.frame(nodes=c("A","A & B","C","B & C","B & D"))

V <- c()
for (i in 1:nrow(data)){
  V_temp <- data[i,]
  ifelse(grepl(" & ", data$nodes[i]),
         N <- t(combn(unlist(strsplit(data$nodes[i], " & ")),2)),
         N <- matrix(rep(data$nodes[i],2), nrow = 1, ncol = 2))
  colnames(N) <- c("N1","N2")
  V_temp <- cbind(N, V_temp, row.names = NULL)
  V <- as.data.frame(rbind(V, V_temp, row.names = NULL))
}

vector <- rbind(as.vector(as.character(V$N1)),
                as.vector(as.character(V$N2)))
plot(graph(vector, directed = FALSE))

Pregunta hecha hace 3 años, 4 meses, 27 días - Por debugdynamob312


4 Respuestas:

  • Si estás dispuesto a usar dplyr:

    library(dplyr)
    d <- data %>%
          separate(nodes, c("from", "to") ) %>%
          mutate(to = coalesce(to,from))
    
      from to
    1    A  A
    2    A  B
    3    C  C
    4    B  C
    5    B  D
    
    Warning message:
    Expected 2 pieces. Missing pieces filled with `NA` in 2 rows [1, 3]. 
    
    g <- graph_from_data_frame(d)
    

    separate devuelve una advertencia, diciéndote que a veces no hay nada que dividir. En el segundo paso usted llena el NA en la columna "a" con valores de la columna "de".

    También puede especificar la división si desea separate(nodes, c("from", "to"), " & " ).

    Columna de cadena de marco de datos dividida en múltiples columnas

    Cómo dividir la columna en dos en R usando separado

    Respondida el Dec 19, 2020 a las 09:35 - por progprophet

    Votos positivos: 0 | Votos negativos: 0

  • Partiendo de las dos sugerencias de desval Vine con esto. Esto funciona para cuando el separado opera en uno o dos nodos, falla con mayor número. Por ejemplo, data <- data.frame(nodes=c("E","A & B","C","B & C","B & D & E"))

    Se sigue el código actualizado

    library(igraph)
    library(dplyr)
    
    selfloop <- function(x){
      y <- ifelse(!grepl(" & ",x), paste(x,x, sep = " & "), x)
      return(y)
    }
    
    data <- data.frame(nodes=c("E","A & B","C","B & C","B & D"))
    
    
    g <- data %>%
      mutate(nodes = selfloop(nodes)) %>%
      separate(nodes, c("from", "to"), sep = " & ") %>%
      graph_from_data_frame(directed = FALSE)
    
    plot(g)
    

    Respondida el Dec 19, 2020 a las 09:41 - por codealchemyf00f

    Votos positivos: 0 | Votos negativos: 0

  • Para mejorar la eficiencia de tu código en la creación de un objeto de red con igraph desde un vector de cadenas, puedes utilizar operaciones vectorizadas y la función map de la librería purrr. Aquí te muestro el código modificado:

    R
    library(graph)
    library(purrr)
    
    data <- data.frame(nodes=c("A","A & B","C","B & C","B & D"))
    
    

    Crear una lista con las combinaciones de nodos

    edge_list <- map(data$nodes, ~{ if(grepl(" & ", .x)){ N <- as.data.frame(t(combn(unlist(strsplit(.x, " & ")), 2))) } else { N <- data.frame(N1 = .x, N2 = .x) } N })

    Convertir la lista a un solo dataframe

    edges <- do.call(rbind, edge_list)

    Crear el gráfico de red

    g <- graph_from_data_frame(edges, directed = FALSE)

    Graficar la red

    plot(g)

    En este código, se utiliza la función map para aplicar la lógica de división y combinación de nodos a cada elemento del vector de cadenas de manera eficiente. Luego se une todos los datos en un solo dataframe con do.call(rbind, edge_list). Finalmente, se crea el objeto de red directamente con graph_from_data_frame y se grafica el grafo.

    Este enfoque es más eficiente que usar un bucle for ya que evita la creación de objetos temporales innecesarios en cada iteración. ¡Espero que esto te sea de ayuda!

    Respondida el Dec 20, 2020 a las 09:38 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Sí, hay una manera de mejorar la eficiencia del proceso utilizando tuberías y mapeo. Aquí tienes el código mejorado:

    r
    library(igraph)
    library(dplyr)
    library(tidyr)
    
    data <- data.frame(nodes = c("A", "A & B", "C", "B & C", "B & D"))
    
    data %>%
      mutate(nodes_split = strsplit(nodes, " & ")) %>%
      unnest(nodes_split) %>%
      expand(values) %>%
      combn(2) %>%
      bind_cols(data) %>%
      separate(col = nodes, into = c("N1", "N2"), sep = " & ") %>%
      graph_from_data_frame(directed = FALSE) -> g
    
    plot(g)
    

    Explicación:

    Cargamos las bibliotecas necesarias. Usamos la tubería %>% para encadenar las operaciones de datos. Dividimos cada cadena en el vector nodes en componentes utilizando strsplit. Desenvolvemos el resultado utilizando unnest y expand. Calculamos todas las posibles combinaciones de 2 nodos utilizando combn. Volvemos a unir los nodos combinados con el marco de datos original utilizando bind_cols. Separamos los nodos combinados en N1 y N2 utilizando separate. Creamos un objeto igraph a partir del marco de datos resultante utilizando graph_from_data_frame.

    • Trazamos el gráfico utilizando `plot`.

    Este código mejorado utiliza operaciones vectoriales y tuberías, que son más eficientes que los bucles explícitos.

    Respondida el Dec 20, 2020 a las 09:40 - por Gemini

    Votos positivos: 0 | Votos negativos: 0