Combinaisons de graphes avec igraph

Ayant eu récemment à me pencher sur la question délicate des jointures entre réseaux ayant des liens en communs, j’en profite pour faire un point rapide sur les fonctions du package igraph permettant ces combinaisons. Si vous ne connaissez pas ce package, voyez les billets taggés R sur ce blog. Le script utilisé est téléchargeable sur github ici-même. et, pour les personnes qui n’ont pas envie et/ou besoin de s’inscrire sur ce git, il est reproduit à la fin de ce billet.

Soit les deux graphes suivants :

g1g2

g1 et g2 sont deux graphes non orientés et ont trois sommets (ACD) et deux liens en commun (pléonasme…). Toutes les fonctions commentées ici prennent des graphes de même type en entrée (orientés ou non), certaines autorisent les combinaisons de graphes différents (un orienté et un non orienté).

La première étape du script consiste à créer des attributs pour g1 et g2 : attributs du réseau, des sommets et des liens. L’objectif est de contrôler la perte éventuelle d’attributs lors des opérations effectuées. Pour mémoire, pour un graphe nommé g, la syntaxe de igraph est la suivante :

g$densite <- graph.density(g) #attribut du graphe
V(g)$degre <- degree(g) #attribut des sommets (V comme vertex)
E(g)$betw <- edge.betweenness(g) #attributs des liens (E comme edges)

La fonction graph.complementer prend un graphe en attribut et crée son complémentaire : les liens absents dans le graphe de départ sont créés, les liens présents dans le graphe de départ sont supprimés. Un paramètre booléen loops permet de décider si on souhaite ou non générer des boucles (par défaut, loops = FALSE). Les attributs du réseau et des sommets sont conservés, les attributs des liens sont perdus (ce qui semble cohérent, ces liens étant supprimés).

La fonction graph.difference prend deux graphes en entrée : seuls les liens présents dans le premier réseau et non dans le deuxième sont conservés, tous les attributs du premier réseau sont gardés. On peut également utiliser l’opérateur %m% (comme minus) : écrire graph.difference(g1,g2) ou g1%m%g2 est donc équivalent. La figure ci-dessous permet de comparer les résultats obtenus : le lien AD présent dans g1 et g2 donc les opérations g1-g2 et g2-g1 entraînent sa disparition.

graph_difference

La fonction (non utilisée dans le script) graph.disjoint.union permet de joindre deux graphes dont les sommets sont distincts.

La fonction graph.intersection (ou %s%) prend deux graphes en entrée et un paramètre keep.all.vertices (TRUE par défaut) permet de choisir entre garder l’ensemble des sommets et les seuls sommets connectés dans le graphe produit. Les attributs sont tous conservés. Enfin, la fonction graph.union prend deux graphes en entrée : tout lien présent dans un moins un graphe
sera dans le graphe produit – sans création de liens multiples – et tous les attributs seront conservés.

Script complet

library(igraph)

#création des deux graphes
d1 <- rbind(c(« A », »B »),c(« A », »C »), c(« B », »C »), c(« A », »D »), c(« D », »E »))
d2 <- rbind(c(« A », »F »), c(« A », »D »), c(« A », »C »), c(« C », »I »))

g1 <- graph.data.frame(d1, directed = FALSE)
g2 <- graph.data.frame(d2, directed = FALSE)

#visualisation
par(mfrow = c(1,2))
plot(g1, main = « g1 »)
plot(g2, main = « g2 »)
dev.off()

#3 points communs (ACD) et deux liens communs (AD et AC)

#ajout d’attributs : degré des sommets
V(g1)$degree <-  degree(g1)
V(g2)$degree <- degree(g2)

#ajout d’attributs aux liens (intermédiarité)
E(g1)$between <- edge.betweenness(g1)
E(g2)$between <- edge.betweenness(g2)

#ajout d’attributs au réseau : densité
g1$densite <- graph.density(g1)
g2$densite <- graph.density(g2)

#fonction graph.complementer
#crée un graphe avec les liens absents du graphe de départ
#les liens présents au départ sont eux supprimés
compg1 <- graph.complementer(g1, loops = FALSE)
plot(compg1)
#les attributs des sommets et du graphe sont conservés
#attributs des liens sont perdus
V(compg1)$degree
compg1

#fonction graph.difference premier réseau – deuxième réseau (opérateur %m%)
#seuls les liens présents dans le premier réseau et non dans le deuxième sont conservés
#tous les attributs du premier réseau sont gardés
diffg1 <- graph.difference(g1, g2)
diffg1

diffg2 <- graph.difference(g2, g1)

#coordonnées (quasi) identiques pour faciliter la comparaison
lay <- layout.fruchterman.reingold(g1)

#lien A-D présent dans g1 et g2 donc g1-g2 et g2-g1 entrainent sa disparition
par(mfrow = c(2,2))
plot(g1, main = « g1 », layout = lay, vertex.color = « red », vertex.size = 20, vertex.label.dist =3)
plot(g2, main = « g2 », layout = lay, vertex.color = « red », vertex.size = 20, vertex.label.dist =3)
plot(diffg1, main = « graph.difference(g1, g2) », layout = lay, vertex.color = « red », vertex.size = 20, vertex.label.dist =3)
plot(diffg2, main = « graph.difference(g2, g1) », layout = lay, vertex.color = « red », vertex.size = 20, vertex.label.dist =3)
dev.off()

#calculer degré actualisé
V(diffg1)$degree2 <- degree(diffg1)
V(diffg1)$degree
V(diffg1)$degree2

#graph.disjoint.union pour joindre des graphes dont les sommets différents (opérateur %du%)

#liens communs à deux graphes : conserve les attributs
#tous les sommets sont conservés (opérateur %s%)
interg1 <- graph.intersection(g1,g2, keep.all.vertices = TRUE)

#seuls sommets adjacents aux liens communs sont gardés (ici ACD)
interg2 <- graph.intersection(g1,g2, keep.all.vertices = FALSE)

par(mfrow = c(1,2))
plot(interg1, sub = « graph.intersection(g1,g2,\nkeep.all.vertices = TRUE) »)
plot(interg2, sub = « graph.intersection(g1,g2,\nkeep.all.vertices = FALSE) »)
dev.off()

#union de graphes : tout lien présent dans un moins un graphe
#est dans le graphe produit – tous les attributs sont conservés
#ne crée pas de liens multiples

uniong <- graph.union(g1,g2) #opérateur %u%

Analyse (et visualisation) de réseaux avec NetworkX – 1

NetworkX est un module python dédié à l’analyse de réseaux. Déconseillé comme outil d’apprentissage, il pourrait s’avérer utile pour des personnes plus expertes, notamment pour l’analyse des réseaux bipartis où le choix reste limité (y compris dans R, le package bipartite n’intégrant guère de mesures récentes). Avant de découvrir NetworkX, il est indispensable de savoir utiliser Python (écriture et exécution d’un script .py). Il exige des centaines de ressources en ligne sur le sujet et je n’ai pas les compétences permettant d’en recommander une en particulier. Mais j’insiste : soit vous cherchez des mesures non existantes ailleurs (ex. plus courts chemins dans des graphes bipartis), vous avez des notions en programmation et l’investissement peut être rentable ; soit vous vous en sortez très bien avec vos logiciels préférés et, à moins d’animer un blog sur l’analyse de réseaux, l’investissement n’est peut-être pas tout à fait nécessaire… Je précise pour finir que je suis encore très loin de maîtriser l’outil (je n’arrive par exemple pas encore à importer des attributs pour les sommets) et que ce billet est très perfectible. Les phrases suivies d’un * sont à considérer comme de possibles erreurs de ma part…

Comment ça marche ?

Le principe est simple : écrire un script python utilisant les commandes du module NetworkX et l’exécuter. Le graphe analysé peut être créé à l’intérieur même du script ou généré à partir d’une liste de liens, et l’importation de fichiers d’autres formats sont également possibles (GEXF, GraphML, Pajek, JSON etc. voir la liste complète ici). Les résultats et les sorties graphiques peuvent être exportés pour être utilisés dans un environnement logiciel autre (format image ou vectoriel).

Comme souvent, il est possible de générer directement son réseau (sommets, liens et attributs éventuels pour les deux) dans NetworkX. Et comme presque toujours, cette option (longuement développé dans tous les tutoriels disponibles) n’a à peu près aucun intérêt dans la mesure où nos données sont déjà existantes dans un format quelconque… Je vais prendre ici le cas le plus simple – ou en tout cas, l’un des plus répandus – dans la mesure où les données sont sous la forme d’une liste de liens possédant un attribut (intensité). Représenter un sommet isolé oblige à créer une boucle.  NetworkX permet également de lire des fichiers structurés sous la forme :

a b c

b d e  etc. où le premier sommet est l’origine du lien et les sommets suivants ses voisins (fonction networkx.read_adjlist).

J’ai utilisé un format .txt et des espaces comme séparateurs pour créer un fichier liens.txt. Les attributs doivent être indiqués entre accolades. S’il n’y a pas d’attribut pour les liens, n’importe quel séparateur semble utilisable (j’ai testé avec des virgules et des points-virgules) ; par contre, s’il y a un attribut, l’espace semble être le séparateur à utiliser*. Le nom des attributs est entre apostrophes, suivi de :, puis de la valeur. S’il y a plusieurs attributs, les séparer par une virgule comme dans l’exemple ci-dessous.

a b {'weight':2, 'color':'green'}
a c {'weight':3, 'color':'green'}

Par défaut, NetworkX considère que le graphe est non orienté. Le script suivant permet d’importer le fichier, de le visualiser, d’effectuer des mesures standards, de le rendre non-orienté puis d’effectuer une nouvelle série de mesures. Le script et le fichier des liens sont téléchargeables sur github à l’adresse https://github.com/beauguitte/NetworkX_1. Je le reproduis in extenso pour les personnes ne souhaitant pas s’inscrire sur le git en question…

Exemple type

# coding: utf8
import networkx as nx
import matplotlib.pyplot as plt #pour la visualisation

#lecture d'une liste de liens
G=nx.read_edgelist("liens.txt", create_using=nx.DiGraph())

#visualisation
pos=nx.spring_layout(G)               #choix de l'algorithme
nx.draw(G, pos, with_labels=True)
plt.show()
#plt.savefig("edge_colormap.png")     #export dans un format donné

Ce qui donne à peu près ça.

plot_ networkx

#analyse
print "number of nodes : %s" % G.number_of_nodes()
print "number of edges : %s" % G.number_of_edges()
print G.in_degree()
print G.out_degree()

#passage en graphe non orienté
G=G.to_undirected()

print "degree of node a : %s" % G.degree("a") #sommet spécifique
print "degree (undirected) %s" % G.degree()   #ensemble des sommets
print "betweenness centrality %s" % nx.betweenness_centrality(G)
print "degree (normalized) %s" % nx.degree_centrality(G)

#transformer les mesures en attributs
deg = G.degree()
nx.set_node_attributes(G, 'degree', deg)

#visualisation
pos=nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()

#recherche des cliques
cl = list(nx.find_cliques(G))
print "cliques %s" % cl

#plus courts chemins
pathlengths=[]

print("source vertex {target:length, }")
for v in G.nodes():
   spl=nx.single_source_shortest_path_length(G,v)
    print('%s %s' % (v,spl))
    for p in spl.values():
        pathlengths.append(p)
print('')
print("moyenne des plus court chemins %s" % (sum(pathlengths)/len(pathlengths)))

#distribution des plus courts chemins
dist={}
for p in pathlengths:
    if p in dist:
        dist[p]+=1
    else:
        dist[p]=1

print('')
print("length #paths")

print("densité : %s" % nx.density(G))
print("diamètre: %d" % nx.diameter(G))
print("eccentricity: %s" % nx.eccentricity(G))
print("centre : %s" % nx.center(G))
print("péripherie : %s" % nx.periphery(G))

En attendant la suite…

Sur le papier, NetworkX est plutôt séduisant pour l’analyse des graphes bipartites et/ou valués. En pratique, le coût d’entrée pour un programmateur peu avancé est assez élevé. Je compte m’acharner dessus dans les semaines à venir et proposer un billet un peu moins approximatif que celui-ci aussi vite que mes capacités d’apprentissage le permettront.

Et pour aller plus loin

Site : https://networkx.github.ioe/

La documentation disponible en ligne est exclusivement en anglais : voir par exemple la très bonne présentation de Derek Greene à cette adresse : http://mlg.ucd.ie/files/summer/tutorial.pdf

R et igraph – revue de détail

Suite du billet consacré à statnet il y a peu ici même.

L’objectif du billet est le même que pour celui signalé une ligne au dessus : importer et effectuer une série de mesures sur le graphe suivant. Téléchargement des fichiers de données et du script commenté ici (encodage en utf-8).
td1plot

Importer ses données

L’importation des données avec igraph est plus simple dans la mesure où les liens et les attributs des sommets peuvent être importés simultanément à l’aide de la commande graph.data.frame – et la gestion des sommets isolés ne pose donc aucun problème particulier. En ce qui concerne les liens, igraph considère que les deux premières colonnes correspondent aux origines et aux destinations, toutes les éventuelles colonnes suivantes seront considérées comme des attributs des liens.

Après transformation, taper le nom de l’objet créé permet d’obtenir à peu près les mêmes informations qu’avec statnet mais sous une forme un peu moins lisible.

library(igraph)

liens <- read.table("liens2.txt", header=TRUE, sep=";")
attributs <- read.table("attributs.txt", header=TRUE, sep=";")

g <- graph.data.frame(liens, vertices = attributs)
g
IGRAPH DN-- 7 8 -- 
+ attr: name (v/c), ANC (v/n), TEAM (v/c), I (e/n)

g est donc un objet igraph de type directed network (DN), comprenant 7 sommets et 8 liens. Il existe 3 attributs pour les sommets (attr v), deux de type character (name et TEAM), un de type numeric (ANC (v/n)) ; un attribut numérique I pour le lien.

Filtrer les données

Sélectionner une partie du graphe en fonction d’un attribut (des sommets et/ou des liens) est d’une grande simplicité une fois comprise la logique de la syntaxe.

Si je souhaite supprimer les liens d’une intensité inférieure à 2

g2 <- delete.edges(g,E(g)[I<2])

soit, si l’on décompose, la fonction delete.edges (nom du graphe, E comme edge (nom du graphe) [ attribut et condition]). Si l’on veut supprimer des sommets, on remplace par delete.vertices et E devient V comme ici où je supprime les sommets de degré inférieur à 2.

g22 <- delete.vertices(g, V(g)[degree(g) < 2])

Si l’on supprime des sommets, les liens adjacents disparaissent également. Si l’on supprime des liens, par défaut, tous les sommets du graphe restent présents.

Mesurer

La recherche de la densité (graph.density) donne – et c’est heureux – le même résultat que statnet, soit 0.19 (8/42).

La recherche des composantes connexes (clusters) renvoie une liste de 3 objets, l’appartenance des sommets (les sommets abcd sont dans la composante connexe numérotée 1), la taille des composantes connexes et leur nombre.

$membership
[1] 1 1 1 1 2 2 3
$csize
[1] 4 2 1
$no
[1] 3

Contrairement à statnet, igraph considère par défaut que la connexité faible est recherchée. Pour la connexité forte, il faudra utiliser l’option mode = « strong ».

La recherche des cliques (fonction cliques) est ici efficace mais, par défaut, igraph fournit toutes les cliques de taille 1, 2 etc. Il est donc conseillé d’indiquer un min. La direction des liens n’est pas et ne peut pas être prise en compte. Les commandes dyad.census et triad.census donnent exactement les mêmes résultats que statnet mais la présentation est moins claire ici pour cette dernière fonction car les codes MAN ne sont pas rappelés. Le résultat reproduit ci-dessous n’est pas très simple à interpréter.

 triad.census(g) 
 [1] 11 12  8  0  1  0  1  0  1  0  0  0  1  0  0  0

La commande degree fournit par défaut est la somme des degrés entrants et sortants. La normalisation (normalized = TRUE) se fait ici par le degré maximal possible. Si je calcule les degrés entrants normalisés, j’obtiens le résultat suivant :

 degree(g, mode="in", normalized = TRUE) 
    a         b      c     d      e       f         g 
0.1666667 0.3333333 0.50 0.000 0.1666667 0.1666667 0.00

Le degré entrant de c est 3, il y a 7 sommets donc le maximum possible est de 6 (pas de boucle) : c a donc un degré entrant normalisé de 0.5. La fonction degree.distribution donne la proportion de sommets ayant un degré zéro, un, deux etc. Mais si on visualise avec la fonction plot(degree.distribution(g)), l’axe des abscisses est faux (il commence à un au lieu de zéro). Et si vous faites partie des adeptes du scale-free, le fameux plot log log s’obtient aisément (voir le script) mais il n’a évidemment aucun intérêt pour un réseau aussi modeste.

La fonction closeness appliquée à un graphe non connexe donne les résultats aberrants suivants :

      a          b          c          d          e          f          g 
0.03333333 0.03333333 0.02380952 0.04000000 0.02777778 0.02777778 0.02380952

Il n’est par définition pas possible de calculer une centralité de proximité pour un sommet isolé, igraph y parvient… La solution permettant d’obtenir un résultat cohérent est de décomposer le graphe puis de la mesurer sur chacune des composantes considérée individuellement. L’option mode= »all » permet d’ignorer la direction des liens.

g2 <- decompose.graph(g)
plot(g2[[1]])
sapply(g2, closeness, mode="all")
[[1]]
        a         b         c         d 
0.2500000 0.3333333 0.3333333 0.2500000 
[[2]]
e f 
1 1 
[[3]]
  g 
NaN

Le résultat est plus crédible (NaN soit Not a Number pour g effectivement). 1 pour e et f, c’est logique. Mais pourquoi 0.25 pour a et d, 0.33 pour b et c. Petit rappel : pour mesurer la closeness, on divise 1 par la somme des plus courts chemins entre un sommet et tous les autres. Pour a et d, on a donc 1/(1+1+2) ; pour b et c, 1/(1+1+1). À retenir en résumé : faire attention avec la fonction closeness qui peut facilement donner des résultats absurdes…

La fonction betweenness donne les mêmes résultats que statnet mais igraph propose également de mesurer l’intermédiarité des liens, c’est-à-dire le nombre de plus courts chemins empruntant un lien donné. Par définition, cette intermédiarité des liens sera toujours supérieure ou égale à 1 (le lien entre a et b est placé sur le plus court chemin entre ces deux points). Les résultats sont présentés dans l’ordre des liens du fichier de départ. Soit le résultat suivant (les codes des liens ont été rajoutés manuellement a posteriori) :

edge.betweenness(g, directed=TRUE) 
   ef fe  ab  ba  ac db dc bc
[1] 1  1   1  2   1  2   1   1
edge.betweenness(g, directed=FALSE)
    ef  fe  ab        ba         ac      db        dc         bc
[1] 0.5 0.5 0.8333333 0.8333333 1.3333333 1.6666667 1.3333333 1.0

Si on prend en compte l’orientation des liens, tous ont un minimum de 1 et le lien ba atteint 2 : il se situe en effet sur les plus courts chemins ba et dba.  Si on ne la prend pas en compte, les résultats sont difficiles à comprendre. Pourquoi des résultats différents pour les liens db, dc, ab et ba ? Tout simplement parce qu’il y a trop de liens pour l’opération demandée : si je ne tiens pas compte de la direction, mon graphe ne comprend que 6 liens.  Donner des résultats pour 7 oblige à des pondérations étranges… La solution la plus pertinente est de transformer d’abord le réseau en réseau non orienté (as.undirected) puis de mesurer l’intermédiarité des liens. On obtient alors un résultat cohérent :

[1] 1.5 1.5 1.0 1.5 1.5 1.0

1 correspond ici aux liens ef et bc et les quatre autres liens obtiennent un score identique. Chacun est placé sur le plus court chemin entre ses sommets terminaux et est l’un des deux plus courts chemins entre a et d : tous ont donc 1.5.

La fonction transitivity (nombre de triangles fermés parmi les voisins d’un sommet) ne permet pas de prendre en compte l’orientation des liens : il est donc nécessaire pour obtenir des résultats corrects de prendre le graphe non orienté. On obtient alors les résultats suivants

transitivity(g3, "local")
[1] 1.0000000 0.6666667 0.6666667 1.0000000       NaN       NaN       NaN

a et d sont situés à la pointe dans des triangles fermés donc la transitivité est de 1 ; efg ne font pas partie de triades donc le résultat n’est pas un nombre (NaN = Not a Numer). b et c sont voisins et tous deux liés à a et à d ; comme il manque 1 lien entre a et d, ils obtiennent un score de 2/3 (2 triangles fermés sont présents sur 3 possibles). La recherche des plus chemins, par défaut, ne tient pas compte non plus de l’orientation des liens. La fonction centralization donne des résultats corrects pour les graphes k-réguliers (score de 0) et non valides pour les graphes en étoile (voir le script où un graphe étoilé de 10 sommets obtient un score de centralisation par le degré de 0.8 seulement). En ce qui concerne les graphes bipartis, même remarque que pour statnet : igraph permet d’en définir, d’en représenter mais ne permet pas de les analyser – lorsqu’une mesure est lancée, il est considéré comme un one-mode.

Pour résumer : il est beaucoup plus facile d’importer ses données et de les filtrer avec igraph, il est aussi beaucoup plus facile d’obtenir des résultats aberrants si l’on n’est pas attentif… À venir très prochainement, un billet détaillé consacré au package bipartite.

R et statnet – revue de détail

Suite aux cours et aux TD donnés à l’ENSAI, j’ai découvert de nouveaux (et agaçants) problèmes liés à l’analyse de réseau avec R. De plus, la nécessité de commenter les résultats m’est clairement apparue. Ce billet vise donc à détailler au maximum les étapes et les résultats produits par le package statnet – un billet consacré à igraph est en cours de préparation. Le script et les fichiers de données sont téléchargeables ici.

Rappel : statnet (et igraph) permettent d’analyser des graphes non valués et one-mode. Si statnet permet de mener des modèles type ERGM, igraph est plus simple d’utilisation. Pour l’analyse de réseau biparti avec R, oubliez statnet et igraph (qui proposent pourtant des options bipartite=TRUE) et voyez plutôt du côté du package bipartite qui est, à ma connaissance, le seul à donner des résultats corrects pour ce type de réseau (voir la démonstration dans le script).

1. Liens, attributs et isolés : sur le format et l’importation des données

Le graphe fictif qui va servir d’exemple tout au long de ce billet représente les interactions autour d’une machine à café dans une petite entreprise : la population est constituée de 7 individus répartis en 2 équipes et de niveaux d’ancienneté différents. Un lien signale qu’une personne a payé un café à une autre. Le graphe est simple : pas de boucle (on ne prend pas en compte les cafés que s’offre une personne) ; pas de liens de nature différente. Il est orienté (une personne offre à une autre) et valué (combien de cafés ont été offerts par une personne à une autre dans la semaine ?).td1plot

Les sommets sont définis par deux attributs : un attribut quantitatif relatif à l’ancienneté (ANC – taille du sommet), un attribut qualitatif relatif à l’équipe (TEAM – couleur du sommet). Les liens sont définis par une direction et une intensité (INT). La valeur des attributs est donnée dans le tableau ci-dessous.

td11

Un rappel important : statnet (comme igraph) ne prend pas en compte de l’intensité des liens pour les calculs. Elle peut juste être utilisée pour la représentation graphique.

Premier problème : statnet génère un graphe à partir d’une liste de liens. Or, le sommet g est isolé. Une solution est de créer dans son fichier de départ un lien fictif g-g puis de préciser lors de l’importation qu’il n’y a pas de boucle.

L’importation des données se fait en deux temps (liens, attributs des sommets). La transformation en objet network, manipulable par statnet, nécessite de ne prendre en compte que les deux premières colonnes (origine – destination). Taper ensuite le nom du graphe permet d’en connaître les caractéristiques. De façon étrange, alors qu’il n’y a pas de boucle, statnet indique malgré tout 9 liens et non 8. Pourtant, le calcul de la densité (cf infra) donne un résultat correct – seuls les 8 liens réellement présents sont donc pris en compte dans les calculs.

library(statnet)
#import fichier
 liens <- read.table("liens.txt", header=TRUE, sep=";")
 attributs <- read.table("attributs.txt", header=TRUE, sep=";")
g <- as.network(as.matrix(liens[,-3]), loops = FALSE)
g
 Network attributes:
 vertices = 7
 directed = TRUE
 hyper = FALSE
 loops = FALSE
 multiple = FALSE
 bipartite = FALSE
 total edges= 9
 missing edges= 0
 non-missing edges= 9
Vertex attribute names:
 vertex.names
No edge attributes

Pour l’instant, les sommets ont un attribut (leur nom) et les liens n’en ont aucun. Les lignes suivantes permettent de transférer les données des data.frame vers l’objet network.

g %v% "ANC" <- attributs$ANC
g %v% "TEAM" <- as.numeric(attributs$TEAM)
g %e% "INT" <- liens$I

Si l’on tape à nouveau g, on observe que les attributs sont désormais plus nombreux.

 Vertex attribute names:
 ANC TEAM vertex.names
Edge attribute names:
 INT

Il est sans aucun doute possible de filtrer le graphe selon les attributs des liens et des sommets (par exemple, extraire le graphe des relations entre membres de l’équipe A) mais si l’opération est facile avec igraph, elle ne l’est pas avec statnet (i.e. je n’ai pas trouvé comment faire, si ce n’est en filtrant les données en amont, avant la transformation en graphe…).

Pour obtenir la figure ci-dessus, deux options sont possibles : appeler les données des data.frame, appeler les attributs de l’objet network. Le résultat est heureusement le même.

#à partir des fichiers de départ
gplot(g, gmode="digraph", displaylabels=TRUE, vertex.col=nodeColors, 
      vertex.cex= log(attributs$ANC), edge.lwd = liens$I*2)

#à partir des attributs de l'objet network
gplot(g, gmode="digraph", displaylabels=TRUE, vertex.col=nodeColor, 
      vertex.cex= log(g %v% "ANC"), edge.lwd = g %e% "INT")

2. Quelques mesures et quelques précisions

Le calcul de la densité (fonction gden) donne comme résultat 0.1904762, ce qui correspond bien à 8 (nombre de liens présents) divisé par 7*6 (nombre de liens possibles) – pour mémoire, dans un graphe simple orienté de n sommets, le nombre maximum de liens est égal à n*(n-1).

Le nombre de composantes connexes s’obtient avec la fonction components et donne ici comme résultat 5. Pourquoi 5 ? Par défaut, statnet considère que, dans un graphe orienté, la connexité recherchée est la forte : il doit exister un chemin (une suite de liens orientés) entre toute paire de sommets au sein d’une composante connexe. La composition des 5 composantes connexes est obtenue avec la commande component.dist. Si l’on souhaite les composantes faiblement connexes (au nombre de 3), il suffit de modifier l’option.

components(g)  #   5 composantes fortement connexes
cs <- component.dist(g) 
cs$membership #  et leur composition

components(g, connected="weak") #  3 composantes faiblement connexes
cw <- component.dist(g,connected="weak")
cw$membership #composition
cw$csize      #et taille

La liste des plus chemins – retour de la commande geodist – comprend deux matrices : $counts donne le nombre de plus courts chemins entre paires de sommets (il peut très bien y avoir plusieurs plus courts chemins entre deux sommets) ; $gdist donne la longueur en liens des plus courts chemins. La commande dyad.census donne un résultat facilement interprétable (nombre de liens mutuels, asymétriques et nuls). La commande triad.census donne en sortie le code MAN (mutuel, asymétrique, nul) des triades et le nombre de triades respectives. Dans le graphe fictif étudié, il n’y a aucune triade complète, et donc 0 sous le code 300.

Il est déconseillé d’utiliser la commande clique.census : même avec un graphe aussi petit, et sur un ordinateur récent et plutôt puissant, RStudio plante…

En ce qui concerne le degré, la commande degree fournit par défaut la somme des degrés entrants et sortants par sommet. Si l’on choisit de normaliser, la somme des degrés des sommets sera égale à 1 (le mode de normalisation est différent dans igraph). Le graphe étant non connexe, la commande closeness donne un résultat égal à zéro pour tous les sommets (igraph donne lui des résultats aberrants). La centralité d’intermédiarité (betweenness) donne ici 0 pour tous les sommets sauf pour b qui obtient 1 : il y a en effet un seul plus court chemin (dba) passant par b. Si l’on ne prend pas en compte la direction des liens, tous les autres sommets restent à zéro et b descend à 0.5. Pourquoi ? Il y a deux plus courts chemins entre d et a (dba et dca), et 1 sur 2 passe par b. Que c reste à zéro est par contre difficilement explicable… (si vous avez une idée, n’hésitez pas à la soumettre).

Enfin, et je termine ici pour l’examen détaillé de certaines fonctions de statnet, la mesure de la centralisation du graphe est correcte dans statnet – on obtient bien 0 avec un graphe type cercle et 1 avec un graphe étoilé – mais elle donne des résultats erronés dans igraph

Dernier point qui concerne les graphes bipartis : statnet permet (difficilement) de les importer puis de calculer des indicateurs mais ceux-ci sont faux. Dans l’exemple du script, nous avons 7 liens, 3 événements et 4 acteurs. Si les 4 acteurs participent aux 3 événements, le graphe est complet, la densité de 1 et le nombre de liens égal à 12. Or, la commande gden donne comme résultat 0.33, soit 7*2 / 7*6 – dans un graphe simple non orienté de n sommets, la densité est égale à 2n / n(n-1). Et si vous tentez l’expérience avec igraph, le résultat est le même. Le seul – et très relatif – intérêt est de pouvoir passer ensuite à des matrices acteurs-acteurs ou événements-événements. Cette dernière opération est possible sans ces packages en multipliant la matrice m par sa transposée pour obtenir la matrice acteurs-acteurs

m %*% t(m)

ou en faisant l’opération inverse (matrice événements-événements)

t(m) %*% m

Deux ateliers R : deux présentations

Deux ateliers méthodologiques sur R ont eu lieu à Toulouse en Mai dernier. La première séance était une séance d’initiation, de discussion et de présentation autour de R tandis que la seconde portait sur l’utilisation de R pour l’analyse de réseau.

Ci-dessous, nous mettons à disposition les supports qui ont alimenté la discussion lors de ces rencontres en petits comités. Un peu de temps a passé depuis ces ateliers mais le contenu est toujours d’actualité (sauf le lien pour télécharger les documents). Il est à noter que le nombre de packages CRAN a bien évolué depuis, passant de 5531 au 12 mai 2014 à 5894 au 17 septembre 2014!

Le premier support donne un aperçu d’ensemble de R: R comme langage interprété, comme système d’exploration interactif,  comme environnement de programmation.

Le second est une présentation sommaire des différents packages permettant de faire de l’analyse de réseau avec R.

Ces ateliers animés avec Sébastien Plutniak ont été soutenus par le Labex Structuration des Mondes Sociaux (SMS) et organisés par le groupe ResTo (Réseaux Sociaux à Toulouse). Merci à tous de m’avoir permis de diffuser ce contenu en ligne et merci à Pauline pour son regard acéré.

Ecole d’été Ferney-Voltaire, Les réseaux, août 2014 (suite)

Ci-dessous, une présentation réalisée à l’occasion de l’Université d’été Ferney-Voltaire consacrée aux réseaux (voir le programme sur le site http://ferney2014.sciencesconf.org/). Cette présentation a servi de support pour l’atelier PAJEK.

Elle comprend une brève introduction à l’analyse de réseau, une présentation des objets réseaux, partitions et vecteurs tels qu’ils doivent être manipulés et mis en forme dans Pajek. On y trouve une description des différentes opérations de type « network+partition » à savoir: extraction d’un sous-graphe, réduction d’un graphe en graphe image, création d’une vue contextuelle.

Pour finir une manipulation est proposée sur un sous-graphe du réseau « world.trade » (lequel est téléchargeable depuis le lien suivant: http://vlado.fmf.uni-lj.si/pub/networks/data/esna/metalWT.htm). A l’issue de cette manipulation, une représentation du réseau européen de commerce est exportée en format vectoriel (svg), chargée et retravaillée dans le logiciel Inkscape afin d’enrichir le contenu et la valeur de la représentation. En particulier, pour en améliorer la lisibilité: on montre qu’il convient d’y ajouter un titre et une légende.

Atelier Pajek Ferney 2014

Ecole d’été Ferney-Voltaire, Les réseaux, août 2014

Ci-dessous, deux présentations faites à l’école d’été Ferney-Voltaire consacrée aux réseaux (voir le programme sur le site http://ferney2014.sciencesconf.org/). La première est un survol, nécessairement très schématique, bourré de raccourcis et sans aucun doute empreint d’une évidente subjectivité, de l’analyse de réseaux dans les différentes sciences (sociales ou non sociales) de Moreno à nos jours. La deuxième présentation est une initiation à R qui pourra utilement compléter les différents billets tagués R disponibles sur ce site. Et les autres riches présentations faites à cette école (qui dure jusqu’au jeudi 28 août) devraient normalement être prochainement disponibles en ligne sur le site signalé plus haut.

 

 

Les indices Kansky avec R : premières fonctions

K. Kansky est un géographe américain qui, dans sa thèse imprimée en 1963, proposa un certain nombre d’indicateurs permettant de caractériser des réseaux, indicateurs directement issus de la théorie des graphes. Si l’ouvrage est quasiment introuvable, le chapitre 2 Measures of network structure en 1989 paru dans la revue Flux est lui accessible sur Persée (http://www.persee.fr/web/revues/home/prescript/article/flux_1154-2721_1989_hos_5_1_913). Ces indices ont connu un succès foudroyant en géographie des transports et restent encore largement utilisés aujourd’hui. Bizarrement, aucun package R ne permet – à ma connaissance – de calculer ces indices. Le présent billet rappelle très brièvement la définition de ces indices, leur interprétation et fournit les fonctions R – basées sur le package igraph – permettant de les calculer.

Petite précision : il s’agit de ma toute première tentative d’écriture de fonction, merci  donc d’être indulgent-e, ma marge de progression dans ce domaine étant immense… Merci à Serge L’homme qui m’a donné la formule pour le diamètre kilométrique et corrigé mon indice de Shimbel, merci enfin à Timothée Giraud qui est toujours disponible pour répondre à mes nombreuses (et souvent naïves) questions. J’en profite pour signaler leurs sites respectifs : site pédagogique de Serge Lhomme (http://serge.lhomme.pagesperso-orange.fr/) ; blog R géomatique de Timothée Giraud (http://rgeomatic.hypotheses.org/).

Les indices de Kansky

Soit e le nombre de liens, v le nombre de sommets et p le nombre de composantes connexes d’un graphe g, Kansky propose notamment les indices suivants :

  • nombre cyclomatique mu = e – v + p. Plus il est élevé, plus le réseau est dense ;
  • alpha : ratio entre le nombre de circuits présents et le nombre de circuits possibles : il varie entre 0 (arbre) et 1 (graphe complet) ;
  • beta : e/v. Une valeur inférieure à 1 signale un arbre, beta ne peut dépasser 3 pour un graphe planaire ;
  • gamma : ratio entre le nombre de liens présents et le nombre de liens possibles. Une formule est proposée pour les graphes planaires et une autre pour les graphes non planaires. Le terme densité employé dans les autres disciplines est synonyme ;
  • degré de connectivité : v*(v-1) * 1/2(e). Ratio entre le nombre de sommets et le nombre de liens (son interprétation m’échappe – mais je suis loin d’être un spécialiste des graphes planaires et des infrastructures de transport…) ;
  • indice de Shimbel : somme des toutes les distances entre les sommets. Peut être mesuré de façon topologique (distance mesurée en nombre de liens) ou pondéré (par une distance, un flux, une intensité etc.)
  • eta : distance moyenne des liens, exprimé généralement en kilomètres ;
  • pi : flux total divisé par le long des plus courts chemins kilométriques ;
  • theta : flux total divisé par le nombre de liens (intensité moyenne)
  • iota : distance totale divisée par le flux total

Trois fonctions R

Les données doivent avoir la forme suivante : un data.frame (tableau de données) ayant au minimum 3 colonnes : origine, destination et distance. Des colonnes peuvent être ajoutées pour porter des poids divers (flux de marchandises, débit horaire etc.). Cette liste de liens doit être transformée en objet igraph : le package igraph doit donc être appelé avant leur exécution (library(igraph)).

La fonction kansky_un mesure les indicateurs ne prenant pas en compte les poids et les distances : diamètre (topologique), nombre cyclomatique, indice alpha (planaire et non planaire), beta, gamma (planaire et non planaire), le degré de connectivité et l’indice de Shimbel (topologique).

La fonction kansky_di mesure les indicateurs prenant en compte une distance entre les sommets : diamètre (kilométrique), eta, pi et indice de Shimbel (pondéré). Le tableau en entrée doit impérativement avoir trois colonnes (origine, destination, distance).

La fonction kansky_df mesure les indicateurs prenant en compte une distance et une intensité entre les sommets : indices theta et iota. Si le tableau de départ ne comprend pas 4 colonnes minimum, un message  d’erreur apparaît.

Exemple reprenant une des figures utilisées par Kansky pour détailler le nombre cyclomatique (mu)

library(igraph)
d <- rbind(c(1,2), c(2,3), c(2,5), c(2,7), c(3,4),
             c(4,5), c(5,6),  c(6,7)) 
g <- graph.data.frame(d, directed = FALSE)
kansky_un(g)

Fonctions téléchargeables ici.

tnet : package R pour l’analyse de réseaux valués

La plupart des packages disponibles dans R permettent l’analyse de réseaux booléens (1 s’il existe une relation entre deux sommets i et j, 0 sinon) mais, si l’on souhaite étudier des réseaux valués (l’intensité des liens est variable entre les sommets), le choix est plus restreint. tnet est un package R maintenu par Tore Opsahl permettant l’analyse de réseaux valués simples et celle de réseaux bipartis et longitudinaux non valués. Le package est bien documenté, le site de Tore Opsahl est riche (http://toreopsahl.com/tnet/), cela méritait donc un billet un peu détaillé. Précision liminaire : tnet permet l’analyse mais non la visualisation des graphes, en effet, les objets manipulés par tnet sont de simples data.frame.

Je suppose pour la suite que R et le package tnet sont installés sur vos machines (voir les billets consacrés à R sur ce blog ou la foultitude de documentation disponible en français et en ligne sur le sujet).

Format des données et importation

Plusieurs jeux de données, classiques (le fameux Davis’ Southern Women Club) ou plus récents, sont disponibles dans tnet (voir la description détaillée sur la page http://toreopsahl.com/datasets/). Qu’on souhaite s’entraîner avec ou pas, il est intéressant d’y jeter un œil pour comprendre la structure des données. Elle est on ne peut plus simple : 3 colonnes origine – destination – intensité. Les attributs des sommets seront importés dans un fichier séparé. Si le réseau one-mode est non orienté, les liens devront être entrés deux fois (i-j et j-i). Les codes des sommets doivent être numériques et commencer par 1. La fonction as.tnet(jeu-de-données) permet de contrôler que la structure des données est correcte. Enfin, pour éviter la prise en compte des sommets isolés, la fonction compress_ids les supprime avant calcul.

Les fonctions se terminant par _w permettent l’analyse des réseaux valués (weighted), celles se terminant par _tm l’analyse des graphes bipartis (two-mode) et celles terminées par _l l’étude des réseaux longitudinaux.

Analyse des graphes valués one-mode

Le principe des mesures disponibles est simple : on fait varier un paramètre entre 0 – pas de prise en compte de l’intensité des liens – et 1 – prise en compte complète de l’intensité des liens. Il n’y a pas de recette miracle pour choisir le bon seuil et tout dépend de l’étendue des intensités : plus celle-ci  est grande, plus le paramètre devra être proche de zéro. Le petit graphe ci-dessous servira d’exemple pour cette partie :

tnet1

Pour le créer directement dans R :

rm(list=ls())
 library(tnet)
g <- rbind(c(1,2,3), c(2,1,3),
           c(1,3,4), c(3,1,4),
           c(2,3,1), c(3,2,1),
           c(3,4,2), c(4,3,2),
           c(4,5,1), c(5,4,1))

En pratique, mieux vaut évidemment importer ses données…

Les principales fonctions disponibles sont les suivantes :

degree_w(g) fournit un tableau à 3 colonnes : identifiant du sommet, degré et sommes des intensités des liens adjacents. Si je contrôle sur la figure, je vois par exemple que le sommet 3 a trois liens adjacents (degré) et que la somme des valeurs de ces trois liens est bien égale à 7 (4 + 2 + 1).

node degree output
 [1,] 1    2    7
 [2,] 2    2    4
 [3,] 3    3    7
 [4,] 4    2    3
 [5,] 5    1    1

closeness_w fournit un tableau de 3 colonnes : identifiant du sommet, centralité de proximité et centralité de proximité normalisée. La centralité mesurée ne repose pas sur le nombre de liens comme c’est le cas habituellement en analyse de réseau mais sur la somme des valeurs des liens parcourus. En d’autres termes, chaque intensité est assimilée à un coût et l’objectif est de trouver les chemins entre sommets minimisant ces coûts.

clustering_local_w et clustering_w fournissent les clustering coefficients locaux et globaux. Plusieurs prises en compte des intensités sont possibles avec l’argument measure = » ». Les principales options sont « am » (moyenne arithmétique, valeur par défaut de l’argument), « gm » (moyenne géométrique), « mi » et « ma » (respectivement minimum et maximum) et enfin « bi » (binaire). Dans ce dernier cas, l’intensité des liens n’est pas  utilisée.

D’autres fonctions et mesures sont disponibles (rich club coefficient global et local) mais il est fortement conseillé de relire attentivement les billets et articles de Tore Opsahl pour les utiliser à bon escient.

Analyse des graphes bipartis…

La structure des données est la même : origine – destination – intensité et, là encore, les deux ensembles de sommets doivent être numérotés de 1 à n. Attention donc à ne pas s’emmêler les pinceaux lors de la mise en forme… L’option type de la fonction as.tnet as.tnet(jeu-de-données, type= »weighted two-mode tnet ») – permet de contrôler la structure des données.

Les principales mesures disponibles sont la mesure de la distance (distance_tm()), le clustering coefficient global (clustering_tm()) et le clustering coefficient local (clustering_local-tm()). Là encore, mieux vaut relire d’abord ses articles et billets : ces mesures sont des propositions a priori pertinentes, ce ne sont pas (pas encore ?) des mesures communément utilisées.

… et analyse des réseaux longitudinaux

 Le package propose en tout en pour tout deux fonctions dont l’une (growth_l) qui prétend identifier les mécanismes responsables de l’apparition de liens entre  les sommets. Ayant à ce jour une connaissance fort limitée de l’analyse des réseaux longitudinaux,  je préfère ne pas m’avancer plus avant…

Dernier point : je déconseille en temps normal l’utilisation de packages développés et maintenus par une seule personne, le risque est en effet grand qu’il cesse brusquement d’être mis à jour avant de disparaître… Si je fais une exception pour celui-ci, c’est en grande partie due à la très grande qualité du site de Tore Opshal. Mais ce jeune homme (cf sa photo ici) travaillant dans le secteur privé, ne vous attachez quand même pas trop à son package….

 

 

Analyse de graphe et QGIS 2.0

Vous l’aurez sans doute déjà noté, la version 2.0 de QGIS est sortie en septembre 2013. Cette nouvelle version a suscité une certaine effervescence dans la sphère du SIG Open Source. Pour les développeurs du dimanche, cette évolution induisait quelques soirées de programmation afin d’apporter les modifications nécessaires au fonctionnement d’extensions développées dans des versions antérieures. Ainsi, je me suis attelé à mettre à jour les extensions présentées dans ce blog (billet 1, billet 2, billet 3). Il était selon moi dommage de laisser tomber en désuétude des extensions conçues il y a seulement un an. J’avais de surcroît plein de projets d’amélioration pour ces extensions, mais je me suis finalement laissé distraire (création d’un plugin d’analyse spatiale et d’un plugin permettant de calculer des modèles de localisation-allocation). Comble du ridicule, je n’ai pas pris le temps de publier cette mise à jour. QGIS est aujourd’hui à la version 2.2.

Je ne vais pas détailler dans ce billet les changements induits par cette nouvelle version en matière de programmation (vous pouvez trouver certains détails ici). Quoi qu’il en soit, je mets à votre disposition une nouvelle extension compatible avec QGIS 2.x (cliquez ici pour la télécharger). Une seule nouveauté est à noter : cette extension regroupe les trois extensions développées précédemment. De plus, cette extension incorpore directement NetworkX (bibliothèque sur laquelle ce plugin repose en partie). L’installation de cette extension est donc très simple.

qgisv2

Ce nouveau plugin regroupe le plugin d’analyse de réseau, celui d’analyse de vulnérabilité et permet de définir des communautés.

Pour installer cette extension, il faut tout d’abord dézipper le dossier téléchargé. Ensuite, il faut copier le dossier « network_analysis » dans « C:\Program Files\QGIS xxxx\apps\qgis\python\plugins\ ». Lancez QGIS et le tour est joué !

Une seule chose est à vérifier (car on apprend des commentaires passés). Lorsque vous dézippez un dossier sous Windows, il vous est proposé de l’envoyer vers un dossier du même nom. Ainsi, votre dossier « network_analysis » est lui-même dans un dossier « network_analysis ». Il faut éviter cette redondance. Ainsi, après avoir copié le dossier, vérifiez bien que votre arborescence est la suivante «C:\Program Files\QGIS xxxx\apps\qgis\python\plugins\network_analysis» et pas «C:\Program Files\QGIS xxxx\apps\qgis\python\plugins\network_analysis\network_analysis».

Arborescence correcte.

Arborescence correcte.

Pour effectuer les calculs, il est nécessaire de disposer de deux couches d’information géographique : une première couche contenant les nœuds et une deuxième couche contenant les arcs. La couche des nœuds doit impérativement contenir les identifiants des nœuds. Il est conseillé de choisir comme identifiant des valeurs numériques allant de 1 à n (vous pouvez télécharger un exemple ici). De même, la couche des arcs doit posséder un champ « identifiant ». De surcroît, cette couche doit impérativement comporter deux champs qui renvoient aux identifiants des nœuds formant les extrémités des arcs (vous pouvez télécharger un exemple ici).

A bientôt pour de nouvelles extensions…

Serge Lhomme

Maitre de conférences à l'université Paris Est Créteil - Docteur en géographie de l'université Paris VII spécialité "dynamique des milieux et risques"

More Posts - Website

Visualiser autrement son temps de transport en métro. (parisien)

L’application développée par Jérôme Cuvier est de celles qui sortent (vraiment) de l’ordinaire, et mérite donc qu’on y stationne quelques minutes.

Pour rejoindre une station de métro depuis une autre, il faut normalement scruter une version du plan (papier, numérique), repérer les différentes lignes à prendre, les éventuelles correspondances. Sur le site de la Ratp, la chose est facilitée puisqu’une version interactive est proposée ici. La possibilité est aussi offerte de calculer son itinéraire, d’estimer son temps de parcours en fonction du moment de la journée, d’afficher sa feuille de route etc.

Estimer son temps de déplacement en métro parisien relève d’un art qui tient beaucoup, beaucoup de l’expérience. Une petite astuce, bien connue, consiste à compter environ 2 minutes par station, ajoutées à celles-là, les temps de correspondance, la présence d’escaliers roulants ou pas, de tapis roulants lentement ou rapidement. Bref.

Avec l’application de Jérôme Cuvier, tout cela n’est pas terminé mais l’exercice peut devenir ludique.

Il faut d’abord sélectionner sa station d’origine : ici Châtillon-Montrouge. L’outil déstructure ensuite la topologie classique du réseau de métro, en reprojettant l’ensemble des stations sur un fond de plan centré sur la station de départ. L’utilisation d’un diagramme circulaire permet de visualiser le temps de déplacement depuis la station de départ vers l’ensemble des autres stations de métro, par tranche de 5 minutes. Le temps de trajet moyen depuis Châtillon-Montrouge vers n’importe quelle autre station est estimé ici à 33 minutes et 19 secondes.

plan de metro vu de Chatillon-Montrouge

Ensuite, après un survol (pas un clic) de la station de destination (Château-de-Vincennes, par exemple), l’application propose le sous-réseau de ligne(s) de métro qu’il faut emprunter, ainsi que le temps de parcours global. Plutôt saisissante cette manière d’afficher un cheminement « subjectif » (!), on dirait un chevelu.

sous-réseau de métro entre chatillon et vincennes

47 minutes de  temps de déplacement estimé, soit une de moins qu’avec le site de la ratp (je précise avoir mentionné des horaires de semaine et en journée). Mais si j’utilise l’astuce des 2 minutes par station, j’estime mon temps de parcours à 54 minutes (27 stations et une correspondance).

temps de transport chatillon-vincennes estime par le site de la ratp

Quelques bémols tout de même. On regrette l’absence d’éléments de repérage : les noms et numéros des lignes auraient été bienvenus. Aussi de ne pas pouvoir imprimer le résultat.

PS : il est bien sûr possible de conserver la position habituelle des stations du métro parisien.

Pour en savoir plus : Plan du métro interactif (Jerôme Cukier) 

Françoise Bahoken

Géographe et cartographe, Chargée de recherches à l'IFSTTAR et membre-associée de l'UMR 8504 Géographie-Cités.

More Posts

MoMA: Inventing Abstraction > visualiser le réseau de la création artistique (1910-1925)

Le site du Museum of Modern Art de New-York (MoMA) propose une très belle rétrospective en ligne de l’exposition Inventing Abstraction (1910-1925) parue en 2013 .

Si le MoMA n’est pas à présenter, on souhaite noter la possibilité d’observer le réseau de relations de ces artistes du début du vingtième siècle. Plusieurs approches de l’exposition sont disponibles.

Tout d’abord, on peut aller faire un tour sur le MoMA Multimedia de l’exposition, en passant ici. Pour ma part, j’ai commencé par Behind the Scene: Inventing Abstraction.

Ensuite, on peut s’émerveiller devant l’ensemble du réseau des acteurs de la période moderne, qui correspond à la capture suivante :

 

On peut poursuivre l’exploration en sélectionnant un artiste d’intérêt, avec tout l’embarras qui va avec. La liste n’est pas courte – ni très longue d’ailleurs – et une soirée n’y suffirait pas : de A comme Josef Albers à W comme Max Weber ou encore Mary Wigman, en passant bien sûr par Piet Mondrian, Fernand Léger, Pablo Picasso, Man Ray et tant d’autres. Il y en a (presque) pour tous les gouts.

J’ai choisi d’observer ce que l’on nous propose pour Vaslav Nijinski (1889-1950), car c’est un grand chorégraphe, ancien danseur étoile (donc classique) des ballets russes  ; une partie de sa bio est disponible sur Wikipédia ici.

En traçant le réseau de relations de Vaslav Nijinski, on obtient sa position et les liens qu’il entretient avec les autres artistes proposés (ici).

L’application étant vraiment bien faite, outre son aspect ludique, agréable à manipuler et à regarder, une trop courte biographie de l’auteur est proposée. On a aussi accès à quelques reproductions. Dans le cas de Vaslav Nijinski, on peut admirer trois dessins, dont celui-ci :

 

Vaslav Nijinski : Untilted (Arc and segments : Lines), 1918-1919

On y apprend que ce dessin est réalisé à main levée, au crayon de couleur sur papier. On y voit une mise en scène de lignes courbes, qui traduisent un effet de convergence vers des points, comme le plan d’une chorégraphie de ballet… les trajectoires d’un réseau de danseurs ?. Y aurait-il là un lien avec le Sacre du Printemps, repris notamment par Maurice Béjart (voir ici) ? Le texte qui accompagne le dessin ne le dit pas. Mais on sait que Vaslav Nijinski a été surnommé « Le clown de Dieu », par Béjart lui-même. En tous les cas, on note que lorsqu’il réalise ce dessin, vers 1818-1919, l’auteur vit ses dernières belles années : il sera peu de temps après interné en hôpital psychiatrique, pour schizophrénie, pendant une bonne trentaine d’années. Il ne finira pas très bien … mais il est toujours possible de télécharger le graphe des relations généré en ligne.

L’onglet Conversations du même site permet aussi d’accéder à des interviews de ceux qui ont participé au making off de l’exposition, à la constitution des fichiers qui ont servi à générer le réseau de relations. On y trouve aussi un entretien sur les Networks and Creativity qui décrit ce réseau….

Au final, une très belle visite entre visualisation des réseaux et art moderne.

Pour en savoir plus :  http://www.moma.org

Françoise Bahoken

Géographe et cartographe, Chargée de recherches à l'IFSTTAR et membre-associée de l'UMR 8504 Géographie-Cités.

More Posts

Un tutoriel pour faire des cartes de flux avec Qgis

Notre collègue cartographe et géomaticien Laurent Jégou vient de mettre en ligne un tutoriel bien pratique pour réaliser des cartes de flux avec le logiciel SIG libre Qgis: http://portailsig.org/content/qgis-concevoir-une-jolie-carte-de-flux

Le secret c’est d’utiliser la fonction « Hub Lines » du plugin Mmqgis (http://michaelminn.com/linux/mmqgis/) à partir d’une couche (shp) de points origines et une couche de points destinations.

Laurent Jégou complète son explication par une astuce pour rendre les lignes courbes. Un exemple de résultat obtenu avec les données Géoscience (UMR LISST, Université de Toulouse 2), la carte des collaborations internationales de Toulouse en 2008:

toulouse_collab

 

 

 

Votre ego-network… vu par google

Alors que l’affaire « Prism » (programme de surveillance de la NSA) a mis en évidence la délicate question de la protection de la vie privée sur internet, une équipe du MIT, dans le cadre d’un programme de recherche baptisé « Immersion », a mis en ligne une application permettant de visualiser notre ego-network à partir des métadonnées issues des mails envoyés et reçus sur la plateforme gmail. D’après la page internet du projet, « Immersion » se veut un outil d’introspection, d’aide à l’exploration de sa vie privée, de stratégie (pour mieux planifier ses relations professionnelles), mais il se présente aussi comme une démarche artistique. On note surtout sur cette page une absence de lien vers une documentation scientifique du projet.

Nouvelle image

L’application trace le réseau social de l’internaute à partir des champs « De »,  « A », « Cc »… et de la date d’envoi du mail. La taille des nœuds est proportionnelle au volume de mails échangé entre l’internaute (ego) et les membres de son ego-network. La taille des liens est proportionnelle au nombre de coprésence dans un même mail des différents acteurs. A noter que l’ego-network présenté n’en est pas totalement un puisque le nœuds de l’ego et les liens les reliant aux autres acteurs ne sont pas représentés (sans doute pour des raisons de clarté de la visualisation). Enfin, la couleur des nœuds, bien qu’aucune légende ne renseigne sur sa nature, renvoie probablement aux classes de modularité.

Le graphe présenté est dynamique et interactif, on peut ainsi sélectionner une période de temps et voir évoluer la structure de son réseau. Il est aussi possible de sélectionner un nœud en particulier pour avoir d’avantage d’information sur l’acteur.

ego_net

Pour ceux qui n’ont pas gmail (ou qui n’ont pas envie de transmettre leur login/mot de passe), il est aussi possible de visualiser un réseau de démonstration (composé de données réelles anonymisées).

Pour le site, c’est ici : https://immersion.media.mit.edu

Pour la démonstration, c’est là : https://immersion.media.mit.edu/demo#

Matthieu Drevelle

Doctorant en Géographie-Aménagement à l'Université Paris 1, UMR Géographie-cités, équipe CRIA - Transamo

More Posts

L’analyse de réseaux avec R – un état des lieux (journée Semin-R du 24 mai 2013)

La courte présentation Beamer ci-dessous a été présentée à la journée Semin-R du 24 mai 2013 à Paris. Comme toujours, les commentaires – absents ici – permettent de nuancer ou de préciser le contenu des différentes diapositives. Il va de soi que cette présentation ne vise ni l’exhaustivité – je n’ai pas testé les 46 packages annoncés – ni l’objectivité. Elle  me semble pouvoir néanmoins servir d’introduction correcte au vaste champ de l’analyse de réseaux avec R.

Cliquer sur Crtl + L pour visualiser le diaporama (je n’ai pas encore trouvé l’astuce pour permettre l’affichage en plein écran…).