2 votes

Fusionner les arêtes par attribut/groupe dans iGraph (R)

Dans le graphe ci-dessous, je souhaite combiner certaines des arêtes par $name. Cependant, il est facile de simplifier un graphe en fusionnant les arêtes en fonction du sommet auquel elles sont connectées, mais pas en les regroupant par une certaine étiquette, dans ce cas $name.

g <- graph(c(1,2, 1,2, 1,2, 2,3, 3,4))
E(g)$weight <- 1:5
E(g)$name <- c("A", "A", "B", "C", "D")

Lors de l'exécution du simplify ou même as.directed\as.undirected les noms sont supprimés s'ils ne sont pas spécifiés dans le champ edge.attr.comb qui est tout à fait logique. Mais pour ce qui est de la spécification, je ne peux que choisir max ou min, ou le convertir en chaîne de caractères.

simplify(g, edge.attr.comb=list(weight = "sum")

Ce que je voudrais obtenir, c'est un graphique où les arêtes marquées par A sont fusionnées/sommées, mais où celles marquées par B sont conservées comme une arête parallèle. J'ai essayé plusieurs choses sans succès.

EDIT : Je sais que je peux convertir le graphique en cadre de données, grouper les données dans ce cadre et revenir au graphique. Ou simplement préparer le cadre de données avant de le mettre dans le graphique. Cependant, c'est trop de manipulations et il serait plus facile de le faire directement dans igraph.

1voto

gfgm Points 2159

Vous pouvez le faire en convertissant les données en dataframe, puis en graphique :

library(dplyr)
df <- igraph::as_data_frame(g)
df <- df %>% group_by(name) %>% mutate(weight = sum(weight)) %>% unique()
df
# A tibble: 4 x 4
# Groups:   name [4]
from    to weight name 
<dbl> <dbl>  <int> <chr>
1  1.00  2.00      3 A    
2  1.00  2.00      3 B    
3  2.00  3.00      4 C    
4  3.00  4.00      5 D    

g2 <- igraph::graph_from_data_frame(df)

Editar

Désolé, je viens juste d'y revenir. Oui, je ne pense pas que la fonction exacte existe et ce serait bien de l'avoir. Mais vous pouvez le faire en deux étapes en 1.) agrégeant les poids pour les nœuds avec des noms partagés et 2.) en supprimant les arêtes dupliquées.

library(dplyr)
library(microbenchmark)
library(igraph)
g <- graph(c(1,2, 1,2, 1,2, 2,3, 3,4))
E(g)$weight <- 1:5
E(g)$name <- c("A", "A", "B", "C", "D")

Il faut d'abord envelopper le fichier data.frame et l'intégrer dans une fonction :

to_df_and_back <- function(g) {
  df <- igraph::as_data_frame(g)
  df <- df %>% group_by(name) %>% mutate(weight = sum(weight)) %>% unique()
  g2 <- igraph::graph_from_data_frame(df)
  g2
}

Nous créons maintenant une fonction pour l'autre approche : nous recalculons d'abord les poids des arêtes en additionnant les doublons, puis nous subdivisons le graphe en ne conservant que les arêtes portant un nom unique :

add_then_subset <- function(g) {
  E(g)$weight <- ave(E(g)$weight, names(E(g)), FUN=sum)
  g2 <- subgraph.edges(g, eid = E(g)[unique(E(g)$name)])
  g2
}

g1 <- to_df_and_back(g)
g2 <- add_then_subset(g)

identical(E(g1)$weight, E(g2)$weight)
#> [1] TRUE

Les résultats obtenus ici en matière de vitesse impliquent la repondération et sous-ensemble est beaucoup plus rapide (la médiane est environ quatre fois plus rapide), mais vous devrez tester cette méthode sur vos données, car je ne sais pas comment elle s'adaptera.

microbenchmark(to_df_and_back(g), add_then_subset(g))
#> Unit: milliseconds
#>                expr      min       lq     mean   median       uq       max
#>   to_df_and_back(g) 4.588584 4.851213 6.901448 4.947683 5.130546 182.82945
#>  add_then_subset(g) 1.208795 1.314137 2.138570 1.382700 1.485809  70.16585
#>  neval cld
#>    100   b
#>    100  a

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X