Analyse de réseaux
Mesures et représentations avec le langage/logiciel R
Analyse de réseaux
Mesures et représentations avec le langage/logiciel R
Ce document est un cours d’introduction à l’analyse de réseaux avec R.
Il s’agit du support de cours utilisé pour l’atelier “mesures et représentations” réalisé dans le cadre de l’École d’été : Initiation à l’analyse de réseaux en SHS, organisé par le GDR « Analyse de réseaux en sciences humaines et sociales » à Nice du 1 au 6 Juillet 2019, au Centre de la Méditerranée Moderne et Contemporaine.— H. Pecout (CNRS, FR CIST), L. Beauguitte (CNRS, UMR Géographie-cités)
Introduction à R et Rstudio
Toutes les disciplines dans lesquelles l’analyse de données occupe une place importante ont connu ces dernières années une petite révolution. Depuis le début des années 2000, le logiciel/langage R gagne en importance et s’impose petit à petit comme une référence, au même titre que les trois grands logiciels (payants) d’analyse de données qui dominent le marché : SAS, SPSS et Stata.
Un logiciel pour tout f’R
- Libre et multiplateforme
- Extensible
- Polyvalent
- Reproductible
R est un langage de programmation et un logiciel libre dédié aux statistiques et au traitement/gestion de données et soutenu par la R Foundation for Statistical Computing. R fait partie de la liste des paquets GNU. Il est multiplate-forme et peut ainsi être utilisé sur Windows, Mac OS ou GNU/Linux.
R est composé d’un socle commun, le r-base (ensemble de fonctions statistiques et graphiques standards, appelées fonctions primitives ou basiques), sur lequel se greffe un ensemble d’extensions appelées packages. Un package est une bibliothèque de fonctions implémentée par un utilisateur.trice et mise à disposition de tou.te.s par l’intermédiaire de dépôts regroupés dans le cadre du Comprehensive R Archive Network (CRAN). Cette structure modulaire permet d’étendre les applications possibles : l’expansion du logiciel n’est limitée que par les contributions des utilisateurs.trices du monde entier à la communauté (le 02 mars 2020, 15389 packages étaient disponibles sur le CRAN).
La communauté grandissante d’utilisateurs.trices et de contributeurs.trices R se traduit par une polyvalence remarquable de l’outil. C’est pour cette raison qu’il concurrence, complète ou remplace toute une gamme de logiciels et de langages pré-existants y compris dans des domaines très spécifiques, par exemple : la statistique textuelle, l’analyse de graphes, la cartographie, la statistique spatiale, le traitement d’enquête, le webscraping, la production de document, les applications web….
R se substitue ainsi à tout un ensemble de logiciels. Il permet de réaliser une chaîne de traitement de données complète (de la collecte à la valorisation) et ainsi d’avoir l’ensemble de son flux de travail au sein d’un seul logiciel.
L’ensemble d’une chaîne de traitement peut ainsi être réalisé sous R, depuis l’import, la manipulation de données, leur analyse et représentation, jusqu’à leur diffusion. Ce flux de travail intégré permet de se soustraire des imports et exports fréquents (afin de passer d’un logiciel à un autre) et minimise les erreurs de manipulation.
Écrire la globalité de la chaîne de traitement réalisée dans un script R ré-exécutable assure l’archivage, la diffusion et la reproductibilité de l’intégralité de son travail et de sa méthodologie.
Ces différents atouts ont fait de R un outil adopté par de nombreuses disciplines scientifiques, aussi bien issues des SHS que des sciences dites dures. R dispose aujourd’hui de nombreux contributeurs.trices aux profils et intérêts variés, ce qui lui assure un développement fonctionnel et thématique à la fois large et spécialisé.
L’environnement RStudio
RStudio est un outil qui vient combler un manque dans la collection des outils associés à R : il s’agit d’un environnement de développement intégré (IDE en anglais) facilitant l’utilisation de R (saisie, exécution de code, visualisation des résultats, etc.)
Le logiciel R propose une interface minimaliste sur MAC et Windows et inexistante sous linux.
Figure : Interface du logiciel R, sous Windows
L’IDE Rstudio facilite considérablement l’apprentissage et l’utilisation du langage R. Parce que c’est pratique, complet et en rapide évolution, il est recommandé d’utiliser l’environnement RStudio.
Installation R et RStudio
Installer R
Vous pouvez télécharger le logiciel R depuis le Comprehensive R Archive Network (CRAN) :
Pour mettre à jour R, il suffit de télécharger et d’installer la dernière version du programme d’installation.
Attention, la nouvelle version sera installée à côté de l’ancienne version. Désinstallez l’ancienne version si vous souhaitez faire de la place sur votre disque dur.
Installer Rstudio
Une fois R correctement installé, rendez-vous sur le site web Rstudio pour télécharger la dernière version stable et gratuite de RStudio. Il s’agit de l’édition Open Source de RStudio Desktop.
Choisissez l’installateur correspondant à votre système d’exploitation et suivez les instructions du programme d’installation.
Lorsque plusieurs versions de R sont disponibles, RStudio choisit par défaut la plus récente. Il est vous est possible de spécifier à RStudio quelle version de R utiliser via le menu Tools > Global Options > General.
Il est inutile de lancer R lorsque l’on utilise l’interface RStudio. Celui-ci est automatiquement démarré lors de l’ouverture de l’IDE.
Présentation de RStudio
L’interface Rstudio
L’interface de RStudio se présente sous la forme d’une fenêtre découpée en quatre zones que l’on peut redimensionner, masquer ou maximiser selon ses préférences :
Cette zone permet l’édition de fichiers source R (avec coloration syntaxique et auto complétion).
La console avec la session R en cours d’exécution. La console affiche à la fois le code exécuté, ses résultats associés, ainsi que les avertissements (warnings) et messages d’erreur éventuels (errors).
Cette zone permet de lister, typer et visualiser les objets créés par l’exécution du code R.
Un explorateur de fichiers, une fenêtre graphique, une fenêtre de gestion des packages et de la documentation associée aux fonctions et packages.
RStudio propose des fonctionnalités d’assistance :
- Une interface clic-bouton
- L’auto complétion
- Des raccourcis clavier
Alt
+-
renvoie l’opérateur d’assignation accompagné d’un espace avant et un espace après (<-)
Ctrl
+Entrée
exécute le code écrit dans la fenêtre d’édition (script)Ctrl
+shift
+c
passe une ligne en commentaireshift
+alt
+k
pour accéder à l’ensemble des raccourcis.
Plusieurs actions comme la création et le chargement de programme, l’import de données, l’installation et le chargement de packages, l’accès à la documentation, la visualisation des objets, l’export de figures… sont exécutables en un simple clic.
RStudio présente aussi la capacité de compléter automatiquement les termes en cours d’écriture. L’auto complétion fonctionne avec la touche Tab du clavier. Cela aide l’utilisateur.trice dans la saisie des noms d’objet, de fonction, de variable et des arguments de fonction.
RStudio propose de nombreux raccourcis clavier intéressants, exemple :
Les projets RStudio
Cette fonctionnalité permet d’organiser son travail en différents projets. L’idée principale est de réunir tous les fichiers relatifs à un même projet (quel que soit leur format) dans un répertoire dédié. Le menu “Project” est accessible via une icône dédiée située tout en haut à droite :
Dans le menu Project, sélectionnez l’option New project :
Dans un nouveau répertoire, créez un projet vide. Indiquez le nom de votre projet, qui sera également le nom du répertoire créé pour stocker les données du projet. Puis, indiquez le répertoire parent, dans lequel votre projet sera créé :
Utiliser les projets Rstudio permet également d’améliorer le partage et la mobilité de son travail, car avec un projet Rstudio :
-> Le répertoire de travail est prédéfini, c’est celui du projet. Il n’est plus utile de paramétrer un répertoire courant.
-> A chaque ouverture du projet, on revient à l’état du projet tel qu’il était lors de la dernière utilisation. Les scripts ouverts lors d’une précédente séance de travail sont automatiquement chargés.
-> Vous pouvez utiliser facilement votre projet et vos scripts sur différentes machines et/ou systèmes d’exploitation sans perdre d’information.
-> Il est possible d’utiliser des systèmes de gestion de version comme svn ou git. Les systèmes de gestion de version permettent de gérer les différentes versions de scripts et facilitent le travail collaboratif.
Les premiers pas
Créer un objet R
R est un super calculateur. Si vous exécutez une opération, le résultat s’affiche dans la console :
## [1] 60
Mais le résultat n’est pas stocké. Pour cela, il est nécessaire d’assigner le résultat à un objet. Les objets, au cœur de la programmation en langage R, permettent de stocker et de structurer les données.
Un objet peut être créé avec l’opérateur « assigner » (<-
), une flèche composée du signe inférieur (<
) accolé à un tiret (-
).
Si l’objet existe déjà, sa valeur précédente est remplacée par la nouvelle :
## [1] "chaîne de caractères"
## [1] 24
Les principaux objets
Le vecteur
Le vecteur est la structure de données de base dans R. Le vecteur permet de regrouper des éléments d’une même classe, comme par exemple des éléments numeric (real ou decimal), integer, string, logical ou complex…
Pour créer un vecteur, il faut utiliser la fonction c()
. La longueur d’un vecteur correspond au nombre d’éléments qu’il contient.
# Regroupement d'éléments dans un vecteur :
# Exemple avec des nombres (integer) :
c(1,5,8,4,3,6,9,2,7)
## [1] 1 5 8 4 3 6 9 2 7
# Pour assigner mon vecteur dans un objet :
# Exemple avec un vecteur de caractères
mon_vecteur <- c("A","B","C","D","E")
mon_vecteur
## [1] "A" "B" "C" "D" "E"
# Il n'est pas possible de regrouper des éléments de classe différentes :
mon_vecteur <- c("nom", "prenom", 10, 20.78, TRUE)
# Ici, toutes les valeurs sont converties en chaîne de caratères :
mon_vecteur
## [1] "nom" "prenom" "10" "20.78" "TRUE"
# Ajouter un (ou plusieurs) élément(s) à un vecteur
mon_vecteur <- c(mon_vecteur, "Element+1", "Element+2")
mon_vecteur
## [1] "nom" "prenom" "10" "20.78" "TRUE" "Element+1"
## [7] "Element+2"
Le facteur
Un facteur (factor) est un vecteur contenant uniquement certaines valeurs prédéfinies. Les valeurs pré-définies sont appelées des levels. La manipulation de ce type d’objet peut être compliquée pour un.e débutant.e, mais il peut s’avérer très utile pour pratiquer l’analyse de réseau sur R.
my_factor <- factor(sample(x = c("North", "East", "South", "West"), size = 13, replace = TRUE))
my_factor
## [1] West East South West North West South West West West North South
## [13] East
## Levels: East North South West
## Factor w/ 4 levels "East","North",..: 4 1 3 4 2 4 3 4 4 4 ...
## [1] "East" "North" "South" "West"
## East North South West
## 2 2 3 6
## [1] West
## Levels: East North South West
Le data.frame
Un data.frame est utilisé pour stocker un tableau de données. Il s’agit en fait d’un ensemble de vecteurs de même longueur. Utilisez la fonction data.frame()
pour construire un data.frame.
# Construction de 3 vecteurs
personne <- c("John Doe","Peter Gynn","Jolie Hope","John snow")
salaire <- c(21000, 23400, 26800, 32700)
date <- c("2010-11-1","2008-3-25","2007-3-14", "1678-1-23")
# Construction d'un data.frame à partir de ces 3 vecteurs (de même longueur)
mon_tableau <- data.frame(personne, salaire, date)
mon_tableau
## personne salaire date
## 1 John Doe 21000 2010-11-1
## 2 Peter Gynn 23400 2008-3-25
## 3 Jolie Hope 26800 2007-3-14
## 4 John snow 32700 1678-1-23
Pour ajouter une colonne à un data.frame :
# Ajouter de colonne (variable) à mon tableau
# Une modalité unique
mon_tableau$Satut <- "employé"
mon_tableau
## personne salaire date Satut
## 1 John Doe 21000 2010-11-1 employé
## 2 Peter Gynn 23400 2008-3-25 employé
## 3 Jolie Hope 26800 2007-3-14 employé
## 4 John snow 32700 1678-1-23 employé
## personne salaire date Satut Sexe
## 1 John Doe 21000 2010-11-1 employé H
## 2 Peter Gynn 23400 2008-3-25 employé H
## 3 Jolie Hope 26800 2007-3-14 employé F
## 4 John snow 32700 1678-1-23 employé H
La matrice
Une matrice est un tableau de nombre à double entrée. Il est possible de créer une matrice avec la fonction matrix()
.
# Création d'une matrice de 4 lignes et 4 colonnes
# stockant des valeurs allant de 1 a 16
ma_matrice <- matrix(1:16, nrow=4, ncol=4)
ma_matrice
## [,1] [,2] [,3] [,4]
## [1,] 1 5 9 13
## [2,] 2 6 10 14
## [3,] 3 7 11 15
## [4,] 4 8 12 16
La liste
Une liste permet de regrouper différents types d’objets dans un seul. Il s’agit en quelque sorte d’un vecteur d’objets. Il est possible de créer une liste avec la fonction list()
.
# Création de 4 objets différents
objet_simple <- "Nom de ma liste"
vector_A <- c("John Doe","Peter Gynn","Jolie Hope","John snow")
vector_B <- c(21000, 23400, 26800, 32700)
mon_tableau <- data.frame(vector_A, vector_B)
# Regroupement de ces 4 objets au sein d'une liste
ma_liste <- list(objet_simple , vector_A, vector_B, mon_tableau)
ma_liste
## [[1]]
## [1] "Nom de ma liste"
##
## [[2]]
## [1] "John Doe" "Peter Gynn" "Jolie Hope" "John snow"
##
## [[3]]
## [1] 21000 23400 26800 32700
##
## [[4]]
## vector_A vector_B
## 1 John Doe 21000
## 2 Peter Gynn 23400
## 3 Jolie Hope 26800
## 4 John snow 32700
La fonction
Le logiciel R propose un ensemble de fonctions préprogrammées appelées fonctions primitives ou basiques et regroupées dans les packages de base (base
, graphics
…) qui sont automatiquement chargés à l’ouverture d’une nouvelle instance de R (ou RStudio).
# Pour connaître toutes les fonctions primitives :
library(help = "base")
## Quelques exemples de fonctions primitives :
# library() Charger une librarie
# class() Connaître la classe de données d'un élément
# mean() Calculer une moyenne
# read.csv() Lire un fichier csv pour créer un data.frame
Pour utiliser une fonction, il suffit d’écrire son nom, puis de spécifier des arguments entre parenthèses.
Dans la plupart des cas, les arguments d’une fonction sont prédéfinis. Il est donc important de se renseigner sur les différents arguments d’une fonction et ses valeurs paramétrées par défaut. Attention, certains arguments n’ont pas de valeur prédéfinie mais doivent obligatoirement être renseignés.
Exemple avec la fonction mean()
:
notes <- c(11,13,15,17,10,8,14,13,12,15,19,NA)
# Pour utiliser la fonction mean() sur le vecteur 'notes' :
mean(x = notes)
## [1] NA
La fonction mean()
retourne NA car la série statistique présente une valeur manquante.
Il faut alors utiliser l’argument na.rm (FALSE par défault) pour ne pas prendre en compte la valeur manquante :
# na.rm (= FALSE par défault) permet de prendre en compte ou non les valeurs NA
mean(x = notes, na.rm = TRUE)
## [1] 13.36364
Les fonctions que l’on utilise sous R sont des objets. Tout le monde peut donc en créer. Pour cela, il est nécessaire d’utiliser la fonction function()
.
Pour utiliser une fonction issue d’un package spécifique (et non du r-base), vous devez d’abord installer le package puis charger la librairie qui propose cette fonction :
# Pour installer un package stocké sur le CRAN
# Indiquer le nom du package entre guillemets
install.packages("foreign")
# Chargement de la librarie
library(foreign)
# Il est maintenant possible d'utiliser une des fonctions proposées par le package foreign
# La fonction read.dbf() permet de lire des fichier de base de données dBASE
read.dbf("D:/users/geographie/Documents/nom_fichier.dbf")
Aide et documentation
Il y a plusieurs façons d’obtenir de l’aide avec R studio. Vous pouvez utiliser l’onglet d’aide proposé par Rstudio et accéder à la documentation d’une fonction :
Il est possible d’accéder à cette documentation par ligne de commande, en utilisant le symbole ?
puis la fonction ciblée :
Ne négligez pas le service d’auto complétion proposé par RStudio. C’est un véritable assistant de programmation. Il permet par exemple de s’assurer de l’orthographe d’un objet, d’une fonction ou de connaître les différents arguments possibles d’une fonction. Pour cela il suffit d’utiliser la touche tab
lors de la saisie.
Enfin, internet est une ressource documentaire très riche pour R. Vous y trouverez toujours une réponse à vos questions, et presque toujours en français !
Importer ses données
On peut importer différents types de données sous R (tableau, image, couche géographique, sons…), mais nous nous intéressons ici uniquement aux tableaux de données. Il est possible d’importer des tableaux de données directement en clic-bouton depuis l’interface Rstudio :
Pour des questions de reproductibilité des traitements, il est préférable d’importer ses données en ligne de commande. Pour cela, toute une série de fonctions (primitives ou non) peut être utilisée. Quelques exemples :
## Fonctions primitives du r-base
read.table() # Importer une table (format multiple)
read.delim() # Importer une table (format multiple)
read.csv() # Importer une table format csv
Il existe également de nombreuses librairies pour importer des données stockées dans un format propriétaire. Par exemple la librairie xlsx
pour importer un fichier au format Excel.
Pour réaliser un import correct, il est souvent nécessaire de renseigner un certain nombre d’arguments.
# Exemple d'import de fichier csv
# not run
My_data <- read.table(file = "/data/user/documents/DataFile.csv",
header = TRUE,
sep = ",",
stringsAsFactors = FALSE,
encoding = "UTF-8")
header : valeur logique qui indique si la première ligne du fichier importé contient les noms des variables. (TRUE par défaut)
sep : indique le séparateur de champ du fichier (" " par défaut)
stringsAsFactor : les données de type caractère sont transformées (par défaut) en facteur
Encoding : indique l’encodage utilisé pour les chaînes de caractères.
Interroger un objet
Vous pouvez consulter un objet créé depuis l’interface Rstudio :
ou en ligne de commande :
## List of 4
## $ : chr "Nom de ma liste"
## $ : chr [1:4] "John Doe" "Peter Gynn" "Jolie Hope" "John snow"
## $ : num [1:4] 21000 23400 26800 32700
## $ :'data.frame': 4 obs. of 2 variables:
## ..$ vector_A: Factor w/ 4 levels "John Doe","John snow",..: 1 4 3 2
## ..$ vector_B: num [1:4] 21000 23400 26800 32700
En cliquant sur l’objet, vous pouvez le visualiser dans sa globalité. Pour cela, vous pouvez également utiliser la fonction View()
.
D’autres fonctions peuvent être utiles pour interroger un objet. Exemple :
## [1] 4 2
## V1 V2 V3 V4
## Min. :1.00 Min. :5.00 Min. : 9.00 Min. :13.00
## 1st Qu.:1.75 1st Qu.:5.75 1st Qu.: 9.75 1st Qu.:13.75
## Median :2.50 Median :6.50 Median :10.50 Median :14.50
## Mean :2.50 Mean :6.50 Mean :10.50 Mean :14.50
## 3rd Qu.:3.25 3rd Qu.:7.25 3rd Qu.:11.25 3rd Qu.:15.25
## Max. :4.00 Max. :8.00 Max. :12.00 Max. :16.00
Pour sélectionner/naviguer au sein d’un objet, utiliser les crochets []
## [1] "10"
# DATA.FRAME (OU MATRCE) - data.frame[ligne(s), colonne(s)]
# 2e et 3e ligne, 1er colonne
mon_tableau[c(2,3), 1]
## [1] Peter Gynn Jolie Hope
## Levels: John Doe John snow Jolie Hope Peter Gynn
## [1] Peter Gynn
## Levels: John Doe John snow Jolie Hope Peter Gynn
## [1] "John Doe" "Peter Gynn" "Jolie Hope" "John snow"
## [1] "John Doe"
Pour les tableaux (data.frame), vous pouvez également utiliser les noms des colonnes :
## [1] John Doe
## Levels: John Doe John snow Jolie Hope Peter Gynn
## [1] John Doe
## Levels: John Doe John snow Jolie Hope Peter Gynn
Exercice
0) Lancez RStudio et créez un projet
Un jeu de données est mis à votre disposition. Il porte sur les relations sexuelles entre les personnages de la série Grey’s Anatomy. Il comporte deux fichiers : le premier contient les sommets et leurs attributs (les personnages de la série), le second contient les liens (arêtes) qui symbolisent les relations sexuelles observées entre les personnages.
1) Télécharger les données en cliquant ici
Source : Gary Weissman, Grey’s Anatomy Network of Sexual Relations, https://gweissman.github.io , 2011.
2) Décompressez l’archive à la racine du répertoire de votre projet Rstudio.
3) Créer et sauvegarder un nouveau fichier r
3) Importer les deux fichiers téléchargés dans des objets R à l’aide de la fonction de base read.table()
, en écrivant le code nécessaire dans votre fichier r.
4) Contrôlez vos deux objets créés pour s’assurer que vous les avez correctement importés.
L’analyse de réseaux avec R
Plusieurs librairies permettent de faire de l’analyse de réseaux avec R (network
, tnet
, statnet
, sna
…) mais la librairie la plus accessible pour démarrer l’analyse de réseaux avec R s’appelle igraph
.
La librairie ‘igraph’
Le code source de cette librairie open source est écrit en langage C. Elle a été développée par Gábor Csárdi et Tamás Nepusz. La première version de cette librairie est mise à disposition en 2006 (dernière version stabilisée en 2014). Elle a été par la suite adaptée en librairie Python et R.
*Les deux solutions pour installer igraph avec RStudio. En clic- bouton** :
En ligne de commande :
Cette opération n’a pas besoin d’être reproduite à chaque nouvelle instance de R, sauf si vous souhaitez mettre à jour le package. L’installation d’un package peut prendre un peu de temps. Astuce : une icône stop est affichée en haut à droite de la console lorsque R est en train d’exécuter votre code :
Pour savoir si le package a correctement été installé, regardez les messages d’alerte affichés dans la console :
Les dernières lignes indiquent que le package a bien été installé (DONE).
Avant de pouvoir utiliser une des fonctions du package igraph
, il est nécessaire de charger la librairie, et cela à chaque nouvelle instance de R.
Pour accéder à la documentation, vous pouvez utiliser les deux lignes de commande suivantes :
# Ouverture de l'onglet d'aide pour le package igraph
?igraph
# Métadonnées + liste des fonctions
library(help="igraph")
Mais internet reste une ressource inégalée. Vous trouverez toujours une conversation de forum, un pdf, un billet de blog… qui apportera les réponses à vos questions. Voici deux ressources officielles pour la librairie igraph
:
L’objet ‘igraph’
Une fonction va nous permette de construire un objet (list) appelé communément objet ‘igraph’, à partir des données relationnelles (liste de liens + éventuellement d’un tableau d’attributs décrivant les sommets du réseau).
A partir d’une liste de liens (ici, relation sexuelle : Greys_anatomy_Sexual_relation.csv) :
et éventuellement d’un tableau d’attributs des sommets (ici, caractéristiques des personnages : Greys_anatomy_Attributes.csv) :
On construit un objet ‘igraph’ (list), à l’aide de la fonction graph_from_data_frame()
:
# CONSTRUCTION DE L'OBJET 'igraph'
library(igraph)
# Construction du réseau, seulement à partir de la liste de liens
Mon_reseau_ex <- graph_from_data_frame(sexual_rel, directed = FALSE)
# Classe de l'objet crée ?
class(Mon_reseau_ex)
## [1] "igraph"
## IGRAPH 018760a UN-- 44 46 --
## + attr: name (v/c)
## + edges from 018760a (vertex names):
## [1] bailey --ben altman --burton adele --chief
## [4] catherine--chief addison --derek chief --ellis grey
## [7] derek --grey finn --grey denny --izzie
## [10] hank --izzie addison --karev ava --karev
## [13] izzie --karev avery --kepner karev --kepner
## [16] avery --lexi karev --lexi bailey --lloyd
## [19] karev --lucy megan --mostow karev --mrs. seabury
## [22] karev --olivia grey --o'malley izzie --o'malley
## + ... omitted several edges
## IGRAPH 018760a UN-- 44 46 --
## + attr: name (v/c)
La description de votre objet igraph commence par 4 lettres :
D ou U, pour un graphe orienté (Directed) ou non (Undirected)
N si il s’agit d’un “Named graph” : les sommets possèdent alors un attribut ‘name’
W Si le graphe est pondéré : les liens possèdent alors un attribut ‘weight’
B Si le graphe est bipartite : les sommets possèdent alors un attribut booléen ‘type’ permettant de différencier les deux ensembles de sommets.
Les deux chiffres qui suivent (ici 44 et 46) indiquent le nombre de sommets et de liens du graphe. La description de l’objet se poursuit avec la liste des attributs des sommets et des liens. La première lettre entre parenthèse (qui suit le nom de l’attribut) indique à quel élément du graphe se rattache l’attribut et la seconde indique la classe des valeur stockées (chaîne de caractère, nombre..). Exemple :
(g/c) - Graph / Character attribute
(v/c) - Vertex / Character attribute
(e/n) - Edge / Numeric attribute
# Construction du réseau, en ajoutant des attributs pour les sommets
Mon_reseau <- graph_from_data_frame(sexual_rel,
vertices = attributes,
directed = FALSE)
# Affichage de l'objet créé :
Mon_reseau
## IGRAPH 5e85c0b UN-- 44 46 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c)
## + edges from 5e85c0b (vertex names):
## [1] bailey --ben altman --burton adele --chief
## [4] catherine--chief addison --derek chief --ellis grey
## [7] derek --grey finn --grey denny --izzie
## [10] hank --izzie addison --karev ava --karev
## [13] izzie --karev avery --kepner karev --kepner
## [16] avery --lexi karev --lexi bailey --lloyd
## [19] karev --lucy megan --mostow karev --mrs. seabury
## + ... omitted several edges
Pour accéder aux informations de manière plus ciblée, vous pouvez utiliser la fonction V()
(V pour vertex), et E()
(E pour edge).
## + 44/44 vertices, named, from 5e85c0b:
## [1] addison adele altman amelia arizona
## [6] ava avery bailey ben burton
## [11] catherine chief colin denny derek
## [16] ellis grey finn grey hahn hank
## [21] izzie karev kepner lexi lloyd
## [26] lucy megan mostow mrs. seabury nancy
## [31] olivia o'malley owen perkins pierce
## [36] preston reed sloan steve susan grey
## [41] thatch grey torres tucker yang
## + 46/46 edges from 5e85c0b (vertex names):
## [1] bailey --ben altman --burton adele --chief
## [4] catherine--chief addison --derek chief --ellis grey
## [7] derek --grey finn --grey denny --izzie
## [10] hank --izzie addison --karev ava --karev
## [13] izzie --karev avery --kepner karev --kepner
## [16] avery --lexi karev --lexi bailey --lloyd
## [19] karev --lucy megan --mostow karev --mrs. seabury
## [22] karev --olivia grey --o'malley izzie --o'malley
## [25] olivia --o'malley altman --owen altman --perkins
## [28] megan --pierce addison --sloan altman --sloan
## + ... omitted several edges
## [1] "addison" "adele" "altman" "amelia" "arizona"
## [6] "ava" "avery" "bailey" "ben" "burton"
## [11] "catherine" "chief" "colin" "denny" "derek"
## [16] "ellis grey" "finn" "grey" "hahn" "hank"
## [21] "izzie" "karev" "kepner" "lexi" "lloyd"
## [26] "lucy" "megan" "mostow" "mrs. seabury" "nancy"
## [31] "olivia" "o'malley" "owen" "perkins" "pierce"
## [36] "preston" "reed" "sloan" "steve" "susan grey"
## [41] "thatch grey" "torres" "tucker" "yang"
# Pour les valeurs de la variable 'weight'
# Mais il ne s'agit pas d'un graphe pondéré...
E(Mon_reseau)$weight
## NULL
# Pour assigner une pondération aux liens, la synthaxe est la suivante :
# Pour l'exemple, on assigne une vecteur de 44 valeurs aléatoire entre 0 et 100
E(Mon_reseau)$weight <- sample(c(0:100), 46, replace = TRUE)
# Lister tous les attributs (et valeurs) des sommets
vertex_attr(Mon_reseau)
## $name
## [1] "addison" "adele" "altman" "amelia" "arizona"
## [6] "ava" "avery" "bailey" "ben" "burton"
## [11] "catherine" "chief" "colin" "denny" "derek"
## [16] "ellis grey" "finn" "grey" "hahn" "hank"
## [21] "izzie" "karev" "kepner" "lexi" "lloyd"
## [26] "lucy" "megan" "mostow" "mrs. seabury" "nancy"
## [31] "olivia" "o'malley" "owen" "perkins" "pierce"
## [36] "preston" "reed" "sloan" "steve" "susan grey"
## [41] "thatch grey" "torres" "tucker" "yang"
##
## $sex
## [1] "F" "F" "F" "F" "F" "F" "M" "F" "M" "M" "F" "M" "M" "M" "M" "F" "M" "F" "F"
## [20] "M" "F" "M" "F" "F" "M" "F" "F" "M" "F" "F" "F" "M" "M" "M" "M" "M" "F" "M"
## [39] "M" "F" "M" "F" "M" "F"
##
## $race
## [1] "White" "Black" "White" "White" "White" "White" "Black" "Black" "Black"
## [10] "White" "Other" "Black" "White" "White" "White" "White" "White" "White"
## [19] "White" "White" "White" "White" "White" "White" "Black" "White" "White"
## [28] "White" "White" "White" "White" "White" "White" "White" "White" "Black"
## [37] "White" "White" "Other" "White" "White" "Other" "Black" "Other"
##
## $birthyear
## [1] 1967 1949 1969 1981 1976 1975 1981 1969 1972 1972 1950 1954 1944 1966 1966
## [16] 1957 1970 1969 1967 1975 1978 1970 1980 1982 1971 1984 1979 1985 1952 1965
## [31] 1982 1973 1973 1965 1986 1963 1981 1972 1984 1959 1955 1975 1970 1971
##
## $position
## [1] "Attending" "Non-Staff" "Attending" "Attending" "Attending" "Non-Staff"
## [7] "Resident" "Attending" "Other" "Non-Staff" "Attending" "Chief"
## [13] "Attending" "Non-Staff" "Attending" "Attending" "Non-Staff" "Resident"
## [19] "Attending" "Non-Staff" "Resident" "Resident" "Resident" "Resident"
## [25] "Nurse" "Attending" "Intern" "Intern" "Non-Staff" "Non-Staff"
## [31] "Nurse" "Resident" "Chief" "Other" "Intern" "Attending"
## [37] "Resident" "Attending" "Non-Staff" "Non-Staff" "Non-Staff" "Attending"
## [43] "Non-Staff" "Resident"
##
## $season
## [1] 1 2 6 7 5 3 6 1 6 7 8 1 3 2 1 1 2 1 2 1 1 1 6 3 7 7 4 4 3 3 1 1 5 7 4 1 6 2
## [39] 2 2 2 2 2 1
##
## $sign
## [1] "Libra" "Leo" "Pisces" "Libra" "Leo"
## [6] "Gemini" "Leo" "Virgo" "Aquarius" "Cancer"
## [11] "Capricorn" "Scorpio" "Taurus" "Taurus" "Capricorn"
## [16] "Virgo" "Cancer" "Scorpio" "Gemini" "Sagittarius"
## [21] "Sagittarius" "Cancer" "Libra" "Aries" "Capricorn"
## [26] "Cancer" NA "Gemini" "Leo" "Leo"
## [31] "Capricorn" "Aries" "Leo" "Leo" NA
## [36] "Leo" "Aquarius" "Scorpio" "Gemini" "Taurus"
## [41] "Leo" "Virgo" "Leo" "Cancer"
## $weight
## [1] 77 34 21 85 83 14 54 6 62 48 97 24 68 87 27 52 42 4 57 79 55 19 72 98 41
## [26] 42 93 77 88 26 13 75 86 5 63 54 92 71 73 27 74 52 33 8 73 31
Pour extraire la liste des liens ou des sommets de votre objet igraph :
# Liens en tableau :
lien_de_mon_reseau <- as_data_frame(Mon_reseau, what="edges")
# Sommets en tableau :
Sommet_de_mon_reseau <- as_data_frame(Mon_reseau, what="vertices")
# Matrice d'adjacence :
# Mon_reseau[]
Mat_mon_réseau <- Mon_reseau[attr="weight"]
Représentation graphique
Une fois vos données relationnelles transformées en objet igraph, il est possible de les représenter graphiquement avec la fonction de r-base plot()
Toute une série d’arguments permet d’ajuster la représentation à sa guise.
Pour paramétrer les sommets :
vertex.color : couleur (Ex : “red”)
vertex.frame.color : couleur des bordures (Ex : “white”)
vertex.shape : forme (“none”, “circle”, “square”, “rectangle”, “pie”, “raster”, “sphere”…) vertex.size : taille de la forme (15 par défaut)
vertex.size2 : seconde dimension (pour la forme rectangle par exemple)
vertex.label.color : couleur des labels
vertex.label : label (vecteur de chaîne de caractères)
vertex.label.family : famille de police des labels (ex : “Times”, “Helvetica”…)
vertex.label.font : police (1=plain, 2=bold, 3=italic, 4=bold italic…)
vertex.label.cex : taille des labels
vertex.label.dist : distance entre label et sommet
vertex.label.degree : position des labels par rapport aux sommets (0=right, pi=left, pi/2=below, -pi/2=above)
Pour paramétrer les liens :
edge.color : couleur (Ex : “red”)
edge.width : épaisseur
edge.arrow.size : taille de la flèche (si orienté, 1 par défaut)
edge.arrow.width : largeur de la flèche (si orienté, 1 par défaut)
edge.lty : type de ligne (0=blank, 1=solid, =dashed, 3=dotted, 4=dotdash, 5=longdash, 6 = twodash)
edge.label : label (vecteur de chaîne de caractères)
edge.label.family : famille de police des labels
edge.label.font : police (1=plain, 2=bold, 3=italic, 4=bold italic…)
edge.label.cex : taille des labels
edge.curved : courbure des liens (0=FALSE to 0.5=TRUE)
arrow.mode : préciser ou placer les flèches (0 = no arrow, 1 = back, 2 = forward, 3 = both)
Autres paramètres importants :
margin : marges autour du graphe (vecteur de quatre chiffres : c(bottom, left, top, right)). Ex : c(1,1,2,1))
frame : encadrer le graphe ? TRUE ou FALSE
main : titre du graphe
sub : sous-titre du graphe
layout : spatialisation du graphe. De nombreux choix possibles : layout_as_bipartite, layout_as_star, layout_as_tree, layout_in_circle, layout_nicely, layout_on_grid, layout_on_sphere…
Vous pouvez utiliser n’importe quelle couleur dans R en indiquant son code hexadécimal. Ex : “#4d4dbe”
Vous pouvez également utiliser des couleurs directement implémentées dans R, en les appelant par leur nom. Ex : “violet” Pour connaître la liste des couleurs implémentées dans R, vous pouvez consulter ce document
Exemple de mise en forme :
plot(Mon_reseau,
vertex.color = "darkolivegreen4",
vertex.frame.color = "white",
vertex.shape = "sphere",
vertex.size = 6,
vertex.label.color = "grey20",
vertex.label.font = 4,
vertex.label.cex = 0.5,
vertex.label.dist = 1.6,
vertex.label.degree = 0,
edge.color = "goldenrod3",
edge.width = 3,
edge.lty = 1,
margin = c(0,0,0.2,0),
main = "Relations sexuelles entre les personnages de Grey's Anatomy (8 saisons)",
sub = "Source : Gary Weissman, Greys Anatomy Network of Sexual Relations, https://gweissman.github.io, 2011",
layout = layout_nicely)
L’argument ‘layout’ permet d’utiliser des algorithmes de placement qui peuvent s’avérer utiles selon le type de réseau.
Voici quelques exemples de spatialisation disponibles avec l’argument ‘layout’ :
Il est possible de prendre en compte les valeurs de certains attributs dans la représentation du graphique.
On peut par exemple colorer ou modifier la forme des sommets en fonction des valeurs d’un attribut :
# Pour modifier la forme des sommets en fonction de l'attribut 'sex' :
# Il suffit d'assigner une forme à la variable 'shape' en fonction de la valeur de la variable 'sex'
# Si 'sex' = F alors 'shape' = "circle", sinon 'shape' = "square"
V(Mon_reseau)$shape <- ifelse(V(Mon_reseau)$sex %in% "F", "circle", "square")
# Pareil pour la couleur des sommets : 'color' en fonction des valeurs de la variable 'race'
V(Mon_reseau)$color <- ifelse(V(Mon_reseau)$position %in% "Chief", "red2",
ifelse(V(Mon_reseau)$position %in% "Resident","royalblue1",
ifelse(V(Mon_reseau)$position %in% "Attending", "mediumpurple1",
ifelse(V(Mon_reseau)$position %in% "Nurse", "coral2",
ifelse(V(Mon_reseau)$position %in% "Intern", "darkgoldenrod1",
ifelse(V(Mon_reseau)$position %in% "Non-Staff", "olivedrab3","grey50"))))))
# Cela fonctionne pour d'autres paramètres (ex : label.color, size...) et également pour les liens.
Si une variable contient beaucoup de modalités différentes, il est préférable d’utiliser la technique suivante, qui utilise les fonctionnalités de l’objet Factor :
# 1) Repèrez le nombre de modalités (levels()) et leur ordre de stockage une fois que
# le vecteur de la variable 'position' est transformé en facteur (as.factor()) :
levels(as.factor(V(Mon_reseau)$position))
## [1] "Attending" "Chief" "Intern" "Non-Staff" "Nurse" "Other"
## [7] "Resident"
# 2) Création d'un vecteur de couleur de la même longueur que le nombre de modalités :
# la première couleur sera assignée à la modalité 1, col 2 = Mod 2 ...
colrs <- c("mediumpurple1","red2","darkgoldenrod1","olivedrab3","coral2","grey50","royalblue1")
colrs
## [1] "mediumpurple1" "red2" "darkgoldenrod1" "olivedrab3"
## [5] "coral2" "grey50" "royalblue1"
# Puis, il suffit d'une ligne de code pour assigner une couleur en fonction des modalités :
V(Mon_reseau)$color <- colrs[as.factor(V(Mon_reseau)$position)]
V(Mon_reseau)$color
## [1] "mediumpurple1" "olivedrab3" "mediumpurple1" "mediumpurple1"
## [5] "mediumpurple1" "olivedrab3" "royalblue1" "mediumpurple1"
## [9] "grey50" "olivedrab3" "mediumpurple1" "red2"
## [13] "mediumpurple1" "olivedrab3" "mediumpurple1" "mediumpurple1"
## [17] "olivedrab3" "royalblue1" "mediumpurple1" "olivedrab3"
## [21] "royalblue1" "royalblue1" "royalblue1" "royalblue1"
## [25] "coral2" "mediumpurple1" "darkgoldenrod1" "darkgoldenrod1"
## [29] "olivedrab3" "olivedrab3" "coral2" "royalblue1"
## [33] "red2" "grey50" "darkgoldenrod1" "mediumpurple1"
## [37] "royalblue1" "mediumpurple1" "olivedrab3" "olivedrab3"
## [41] "olivedrab3" "mediumpurple1" "olivedrab3" "royalblue1"
Une fois que les couleurs, formes, tailles… sont prédéfinies pour les sommets et les arêtes, elles s’afficheront automatiquement :
plot(Mon_reseau,
vertex.size = 7,
vertex.label= NA,
edge.color = "black",
edge.width = 2,
edge.lty = 1,
margin = c(0,0,0.2,0),
main = "Représenter les attributs des sommets et des arêtes",
layout = layout_nicely)
Dans ce cas, il peut être utile d’ajouter une légende. Pour cela, utilisez la fonction legend()
Vous pouvez également ajouter du texte avec la fonction text()
plot(Mon_reseau,
vertex.size = 7,
vertex.label= NA,
edge.color = "black",
edge.width = 2,
edge.lty = 1,
margin = c(0,0,0.2,0),
main = "Représenter les attributs des sommets et des arêtes",
layout = layout_nicely)
# Légende - variable sex
legend(x = -1.5,
y = 1,
legend = levels(as.factor(V(Mon_reseau)$sex)),
pch = c(21, 22),
pt.bg= NA,
pt.cex=2,
bty="o",
title = "Sexe")
# Légende - variable position
legend(x = 1,
y = 1,
legend = levels(as.factor(V(Mon_reseau)$position)),
pch=18,
col=colrs,
pt.cex=2,
bty="n")
# Ajout de texte
text(x = 0,
y = -1.2,
labels = "Quel beau graphe")
Par défaut, les sommets d’un objet igraph sont positionnés sur un repère orthonormé étendu de -1 à 1 sur l’axe des abscisses et des ordonnées. Vous connaissez maintenant le secret pour bien positionner vos éléments d’habillage (légende, texte…) !.
Les principaux indicateurs
Nombre de sommets/arêtes
Les fonctions gorder()
et gsize()
permettent respectivement de calculer le nombre de sommets (ordre) et d’arêtes (taille) de votre graphe.
## [1] 44
## [1] 46
Mesurer la densité
La densité d’un graphe désigne le rapport entre le nombre de liens présents et le nombre de liens possibles. Elle varie entre 0 (graphe vide, sans aucun lien) et 1 (graphe complet). Vous pouvez utiliser la fonction graph.density()
pour calculer la densité de votre graphe :
## [1] 0.04862579
L’argument loops
permet de considérer les liens d’un sommmet vers lui-même (boucle).
Nombre de composantes connexes
Un graphe est dit connexe s’il existe au moins un chemin entre toutes les paires de sommets. Dans le cas contraire, le graphe est constitué de différentes composantes connexes. Pour connaître le nombre de composantes connexes de votre graphe, vous pouvez utiliser la fonction components()
.
## $membership
## addison adele altman amelia arizona ava
## 1 2 1 1 1 1
## avery bailey ben burton catherine chief
## 1 3 3 1 2 2
## colin denny derek ellis grey finn grey
## 1 1 1 2 1 1
## hahn hank izzie karev kepner lexi
## 1 1 1 1 1 1
## lloyd lucy megan mostow mrs. seabury nancy
## 3 1 4 4 1 1
## olivia o'malley owen perkins pierce preston
## 1 1 1 1 4 1
## reed sloan steve susan grey thatch grey torres
## 1 1 1 2 2 1
## tucker yang
## 3 1
##
## $csize
## [1] 31 6 4 3
##
## $no
## [1] 4
Cette fonction renvoie trois variables :
membership : identifiant de la composante connexe d’appartenance
csize : nombre de sommets des composantes connexes
no : nombre de composantes connexes
Il est possible d’extraire toute les composantes connexes d’un réseau pour créer plusieurs graphes.
## [[1]]
## IGRAPH f579b3e UNW- 31 36 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c), shape (v/c), color (v/c), weight
## | (e/n)
## + edges from f579b3e (vertex names):
## [1] altman --burton addison--derek derek --grey
## [4] finn --grey denny --izzie hank --izzie
## [7] addison--karev ava --karev izzie --karev
## [10] avery --kepner karev --kepner avery --lexi
## [13] karev --lexi karev --lucy karev --mrs. seabury
## [16] karev --olivia grey --o'malley izzie --o'malley
## + ... omitted several edges
##
## [[2]]
## IGRAPH 3b4bba9 UNW- 6 5 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c), shape (v/c), color (v/c), weight
## | (e/n)
## + edges from 3b4bba9 (vertex names):
## [1] adele --chief catherine --chief chief --ellis grey
## [4] ellis grey--thatch grey susan grey--thatch grey
##
## [[3]]
## IGRAPH fe18fb6 UNW- 4 3 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c), shape (v/c), color (v/c), weight
## | (e/n)
## + edges from fe18fb6 (vertex names):
## [1] bailey--ben bailey--lloyd bailey--tucker
##
## [[4]]
## IGRAPH 92d4caf UNW- 3 2 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c), shape (v/c), color (v/c), weight
## | (e/n)
## + edges from 92d4caf (vertex names):
## [1] megan--mostow megan--pierce
## IGRAPH fe18fb6 UNW- 4 3 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c), shape (v/c), color (v/c), weight
## | (e/n)
## + edges from fe18fb6 (vertex names):
## [1] bailey--ben bailey--lloyd bailey--tucker
Mesurer le diamètre
Le diamètre d’un graphe est le plus long des plus courts chemins du graphe, il se calcule avec la fonction diameter()
.
## [1] 433
Attention, la fonction diameter()
prend en compte par défaut le poids (weight) des arêtes. N’oubliez pas de renseigner tous les arguments nécessaires pour être sûr de ce que la fonction diameter()
renvoie (cette recommandation est valable pour toutes les fonctions de R et, plus généralement, tous les logiciels d’analyse et de visualisation de données).
## [1] 433
Si votre graphe possède plusieurs composantes connexes, la fonction diameter()
renvoie le plus grand diamètre par défaut.
Mesurer la transitivité globale
La transitivité d’un graphe mesure la proportion de triades fermées (clique de trois sommets) dans un réseau. Ce coefficient mesure à quel point le voisinage d’un sommet est connecté.
## [1] 0
Il n’y a donc aucun triangle amoureux !
Extraction d’un sous-graphe
Il est parfois nécessaire de sélectionner une partie d’un graphe. Vous pouvez extraire des sous-graphes de votre réseau à partir des valeurs d’un attribut des sommets ou des liens, en utilisant la fonction induced_subgraph()
et de la fonction r-base which()
.
# Sélection des personnages définis comme "praticien"
Mon_reseau_Attending <- induced_subgraph(Mon_reseau,
v = which(V(Mon_reseau)$position == c("Attending")))
# Représentation graphique
plot(Mon_reseau_Attending,
vertex.shape = "sphere",
vertex.size = 8,
vertex.label.font = 4,
vertex.label.cex = 0.6,
vertex.label.dist = 2.3,
vertex.label.degree = 0,
edge.color = "black",
edge.width = 2,
edge.lty = 1,
margin = c(0,0,0.2,0),
main = "Relations sexuelles entre les 'praticien.ne.s' du service hospitalier")
Pour extraire un sous graphe en fonction des attributs des liens, utilisez la fonction subgraph.edges()
.
# Sélection des liens d'intensité supérieure ou égale à 50
Mon_reseau_lien_select <- subgraph.edges(Mon_reseau,
eids = which(E(Mon_reseau)$weight >= 50))
Mesures locales et globales
Centralité des sommets
La centralité d’un sommet peut être calculée de plusieurs manières afin de répondre à des logiques différentes de centralité :
- Centralité de degré :
Nombre de voisins d’ordre 1 (nombre de liens entrants ou sortants, ou les deux)
## addison adele altman amelia arizona ava
## 3 1 4 1 1 1
## avery bailey ben burton catherine chief
## 2 3 1 1 1 3
## colin denny derek ellis grey finn grey
## 1 1 2 2 1 4
## hahn hank izzie karev kepner lexi
## 1 1 4 9 2 3
## lloyd lucy megan mostow mrs. seabury nancy
## 1 1 2 1 1 1
## olivia o'malley owen perkins pierce preston
## 2 4 2 1 1 1
## reed sloan steve susan grey thatch grey torres
## 1 7 1 1 2 5
## tucker yang
## 1 3
Pour calculer la centralité de degré normalisée (degré / nombre de sommet-1), utilisez l’argument normalized
Si vous travaillez sur un graphe orienté, l’argument mode
permet de calculer le degré entrant, sortant ou les deux.
## addison adele altman amelia arizona ava
## 0.06976744 0.02325581 0.09302326 0.02325581 0.02325581 0.02325581
## avery bailey ben burton catherine chief
## 0.04651163 0.06976744 0.02325581 0.02325581 0.02325581 0.06976744
## colin denny derek ellis grey finn grey
## 0.02325581 0.02325581 0.04651163 0.04651163 0.02325581 0.09302326
## hahn hank izzie karev kepner lexi
## 0.02325581 0.02325581 0.09302326 0.20930233 0.04651163 0.06976744
## lloyd lucy megan mostow mrs. seabury nancy
## 0.02325581 0.02325581 0.04651163 0.02325581 0.02325581 0.02325581
## olivia o'malley owen perkins pierce preston
## 0.04651163 0.09302326 0.04651163 0.02325581 0.02325581 0.02325581
## reed sloan steve susan grey thatch grey torres
## 0.02325581 0.16279070 0.02325581 0.02325581 0.04651163 0.11627907
## tucker yang
## 0.02325581 0.06976744
- Centralité d’intermédiarité :
Proportion de plus courts chemins passant par un sommet donné
## addison adele altman amelia arizona ava
## 18 0 153 0 0 0
## avery bailey ben burton catherine chief
## 0 3 0 0 0 7
## colin denny derek ellis grey finn grey
## 0 0 3 6 0 65
## hahn hank izzie karev kepner lexi
## 0 0 57 202 0 28
## lloyd lucy megan mostow mrs. seabury nancy
## 0 0 1 0 0 0
## olivia o'malley owen perkins pierce preston
## 29 82 81 0 0 0
## reed sloan steve susan grey thatch grey torres
## 0 224 0 0 4 200
## tucker yang
## 0 57
Attention, par défaut, le calcul de la centralité d’intermédiarité n’est pas normalisé et utilise le poids des arêtes. Utiliser les arguments weights
et normalized
pour être sûr.e de ce que vous calculez.
Les calculs des centralités d’intermédiarité et de proximité sont également faussés si votre graphe contient plusieurs composantes connexes. Calculez ces centralités sur chaque composantes
# Centralité d'intermédiarité de la composante connexe 1
betweenness(Mes_reseaux[[1]], weights = NULL, normalized=TRUE, directed = FALSE)
## addison altman amelia arizona ava avery
## 0.041379310 0.351724138 0.000000000 0.000000000 0.000000000 0.000000000
## burton colin denny derek finn grey
## 0.000000000 0.000000000 0.000000000 0.006896552 0.000000000 0.149425287
## hahn hank izzie karev kepner lexi
## 0.000000000 0.000000000 0.131034483 0.464367816 0.000000000 0.064367816
## lucy mrs. seabury nancy olivia o'malley owen
## 0.000000000 0.000000000 0.000000000 0.066666667 0.188505747 0.186206897
## perkins preston reed sloan steve torres
## 0.000000000 0.000000000 0.000000000 0.514942529 0.000000000 0.459770115
## yang
## 0.131034483
- Centralité de proximité :
Inverse de la distance moyenne des plus courts chemins d’un sommet vers tous les autres. Valeur entre 0 et 1.
# Centralité de proximité
closeness(Mes_reseaux[[1]], weights = NULL, normalized=TRUE, mode = "all")
## addison altman amelia arizona ava avery
## 0.006326445 0.007429421 0.007550969 0.005506608 0.007383707 0.005485464
## burton colin denny derek finn grey
## 0.005971338 0.004248690 0.004463621 0.004678727 0.004949678 0.005095974
## hahn hank izzie karev kepner lexi
## 0.005448602 0.004750594 0.006093845 0.008910009 0.007288630 0.007509387
## lucy mrs. seabury nancy olivia o'malley owen
## 0.005976096 0.006045949 0.004926108 0.008034280 0.006939625 0.005995204
## perkins preston reed sloan steve torres
## 0.004454343 0.003881988 0.008019246 0.008342603 0.003889033 0.008852169
## yang
## 0.004393030
Mesures de centralité pour un sommet précis
## addison
## 3
# Pour utiliser directement le nom du sommet :
betweenness(Mon_reseau, weights=NULL, normalized=TRUE)["addison"]
## addison
## 0.01993355
# Sélection multiple (ex : sommets 1,5 et 7) :
closeness(Mon_reseau, weights=NULL, normalized=TRUE)[c(1,5,7)]
## addison arizona avery
## 0.008091833 0.007142857 0.007118027
Les mesures de centralité comme attributs des sommets
# Les valeurs des centralités de degré sont insérées dans la variable 'degre'
V(Mon_reseau)$degre <- degree(Mon_reseau)
# Centralité d'intermediarité dans la variable 'intermed'
V(Mon_reseau)$intermed <- betweenness(Mon_reseau, weights=NULL, normalized=TRUE)
# Centralité de proximité dans la variable 'proximit'
V(Mon_reseau)$proximit <- closeness(Mon_reseau, weights=NULL, normalized=TRUE)
Trois attributs comportant les mesures de centralités ont été ajoutés aux sommets :
Représentation graphique
Une fois les valeurs des centralités stockées comme attribut des sommets, il est possible de les représenter graphiquement.
# Pour que la taille des sommets soit proportionnelle à une valeur :
# Par exemple, au degré des sommets :
# Il suffit de stocker le degré dans la variable 'size'
V(Mon_reseau)$size <- V(Mon_reseau)$degre*2
# Les couleurs prédéfinies s'afficheront automatiquement
plot(Mon_reseau,
vertex.shape = "sphere",
vertex.label = NA ,
edge.color = "black",
edge.lty = 1,
main = "Taille des sommets proportionnelle au degré")
Distribution des degrés
Observer la distribution des degrés, permet de caractériser un graphe.
La fonction degree.distribution()
permet de calculer pour chaque degré, la part (%) de sommets concernés. La première valeur correspond à la fréquence relative (%) des sommets de degré 0, la seconde à la part des sommets de degré 1… jusqu’au degré maximum du graphe (9 dans notre cas).
## [1] 0.00000000 0.54545455 0.18181818 0.11363636 0.09090909 0.02272727
## [7] 0.00000000 0.02272727 0.00000000 0.02272727
# Les arguments importants :
# mode = c("all", "out", "in", "total")
# loops = TRUE/FALSE
# cumulative = TURE/FALSE)
Il n’y a donc aucun sommet isolé dans notre graphe, car aucun sommet ne présente un degré égal à 0.
Représenter la distribution des degrés aide également à l’interprétation car elle peut renseigner sur la structure du réseau :
Tests de corrélation
Pour tester la corrélation entre deux indicateurs de centralité, utilisez la fonction plot()
pour la représenter et cor.test()
pour la mesurer.
# Pour plus de lisibilité :
# On crée deux nouveaux objets correspondant à deux centralités
deg <- V(Mon_reseau)$degre
bet <- V(Mon_reseau)$intermed
# Représentation graphique
plot(x = deg, y = bet)
# Pour ajouter une droite de régression. 'abline()' + 'lm()' :
abline(lm(bet ~ deg), col="red")
##
## Pearson's product-moment correlation
##
## data: deg and bet
## t = 12.646, df = 42, p-value = 6.541e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.8060084 0.9387859
## sample estimates:
## cor
## 0.8899373
La fonction renvoie 4 valeurs permettant de rejeter ou valider l’existence d’une corrélation entre les deux variables :
t : valeur de la statistique
df : degré de liberté
p-value : p-value
cor : coefficient de corrélation (de Pearson dans ce cas).
Transitivité locale et globale
La fonction transitivity()
renvoie par défaut la transitivité globale (pour l’ensemble du graphe). Mais il est possible de calculer la transitivité locale (par sommet) en le précisant avec l’argument ‘type’ :
# transitivity(Mon_reseau) = transitivity(Mon_reseau, type = c("global"))
# Pour calculer la transivitité locale :
transitivity(Mon_reseau, type = c("local"))
## [1] 0 NaN 0 NaN NaN NaN 0 0 NaN NaN NaN 0 NaN NaN 0 0 NaN 0 NaN
## [20] NaN 0 0 0 0 NaN NaN 0 NaN NaN NaN 0 0 0 NaN NaN NaN NaN 0
## [39] NaN NaN 0 0 NaN 0
Il n’est pas possible de calculer la transitivité pour les sommets qui ne sont pas liés à plus d’un autre sommet. La fonction transitivity()
renvoie alors la valeur ‘NaN’ (Not a Number).
Extraire les ego-networks
La fonction make_ego_graph()
permet d’extraire tous les ego-networks d’un réseau.
# Extraction des ego-networks
# Comme avec la fonction decompose(), cette fonction construit une liste d'objets igraph :
EgoNet_Mon_reseau <- make_ego_graph(Mon_reseau)
# Une série d'argument permet pour choisir les paramètres des ego-network :
EgoNet_Mon_reseau <- make_ego_graph(Mon_reseau,
nodes = V(Mon_reseau),
order = 2,
mode = c("all"),
mindist = 0)
# Pour sélectionner les ego-network, utilisez des [[]] et l'identifiant des ego-networks
# V(Mon_reseau)$name[22]
EgoNet_Mon_reseau[[22]]
## IGRAPH 0b8302f UNW- 18 22 --
## + attr: name (v/c), sex (v/c), race (v/c), birthyear (v/n), position
## | (v/c), season (v/n), sign (v/c), shape (v/c), color (v/c), degre
## | (v/n), intermed (v/n), proximit (v/n), size (v/n), weight (e/n)
## + edges from 0b8302f (vertex names):
## [1] addison--derek denny --izzie hank --izzie
## [4] addison--karev ava --karev izzie --karev
## [7] avery --kepner karev --kepner avery --lexi
## [10] karev --lexi karev --lucy karev --mrs. seabury
## [13] karev --olivia izzie --o'malley olivia --o'malley
## [16] addison--sloan lexi --sloan arizona--torres
## + ... omitted several edges
EgoNet_Karev <- EgoNet_Mon_reseau[[22]]
# Représentation d'un des ego-networks :
plot(EgoNet_Karev,
vertex.shape = "sphere",
vertex.label.color = "grey25",
vertex.label.font = 1,
vertex.label.cex = 0.6,
vertex.label.dist = 2,
vertex.label.degree = 0,
edge.color = "black",
edge.width = 2,
edge.lty = 1,
margin = c(0,0,0.2,0),
main = "Ego-network de Karev")
Avant de poursuivre l’analyse de votre ego-network, vous pouvez supprimer ego de votre réseau :
# Suppression d'ego
EgoNet_Karev_sans_karev <- induced_subgraph(EgoNet_Karev,
v = which(V(EgoNet_Karev)$name != c("karev")))
# Représentation de l'ego-network, sans ego :
plot(EgoNet_Karev_sans_karev,
vertex.shape = "sphere",
vertex.label.color = "grey25",
vertex.label.font = 1,
vertex.label.cex = 0.6,
vertex.label.dist = 2,
vertex.label.degree = 0,
edge.color = "black",
edge.width = 2,
edge.lty = 1,
margin = c(0,0,0.2,0),
main = "Ego-network de Torres, sans Torres")
Détection des communautés
Pour détecter les communautés, 8 fonctions sont implémentées dans igraph. La fonction cluster_edge_betweenness()
permet par exemple de créer une partition des sommets par déconnexion progressive du graphe, en supprimant les arêtes dans l’ordre décroissant de leur centralité d’intermédiarité.
# Clustering
Clus_Edge_betweness <- cluster_edge_betweenness(Mon_reseau, weights=NULL)
# Affichage du résultat
plot(Clus_Edge_betweness, Mon_reseau, vertex.label=NA)
L’objet renvoyé est appelé objet ‘communities’ et contient les éléments suivants :
## [1] "removed.edges" "edge.betweenness" "merges" "bridges"
## [5] "modularity" "membership" "names" "vcount"
## [9] "algorithm"
Pour consulter ces différentes informations, utilisez le symbol $
:
## [1] 1 2 3 1 4 5 5 6 6 3 2 2 3 7 8 2 8 8 4 7 7 5 5 5 6 5 9 9 5 1 4 4 3 3 9 3 1 1
## [39] 8 2 2 4 6 3
Il est possible d’enregistrer la position des sommets (placement dans la figure) afin qu’ils soient toujours placés au même endroit dans différentes figures :
# Enregistrement d'une position
mise_en_page <- layout.fruchterman.reingold(Mon_reseau)
# Pour réutiliser ces positions, utilisez l'argument 'layout':
plot(Clus_Edge_betweness, Mon_reseau, vertex.label=NA, layout = mise_en_page)
Les autres fonctions de classification implémentées dans igraph sont les suivantes :
cluster_fast_greedy() : greedy optimization of modularity
cluster_walktrap() : short random walks
cluster_spinglass() : based on statistical mechanics
cluster_leading_eigen() : based on the leading eigenvector of the community matrix
cluster_label_prop() : based on propagating labels
cluster_infomap() : minimizes the length of a random walker
cluster_optimal() : maximizing the modularity measure
Un algorithme de partition d’un graphe se choisit en fonction de la taille du graphe, certains algorithmes étant inadaptés aux grands graphes. Il est conseillé de tester plusieurs algorithmes pour contrôler la stabilité des communautés détectées. Les résultats sont d’ailleurs parfois très différents.
Il existe énormément d’algorithmes de détection de communautés, parfois très complexes. Dans ce billet de blog, sont expliquées les différentes méthodes de partitionnement proposées par le package igraph.
Exercice
Pour démarrer cet exercice, exécutez le code ci-dessous. Il génère une liste de liens et des attributs.
Vous pouvez choisir le nombre de sommets souhaités en modifiant la valeur de l’objet Nb_sommets
:
# Indiquez le nombre de sommets souhaités :
Nb_sommets <- 25
# Exécuter le code ci-dessous pour génerer :
# - une liste de lien (tableau from-to)
# - un tableau d'attribut décrivant les sommets
# Si vous souhaitez verrouiller les tirages aléatoires,
# Utilisez la fonction set.seed() :
# set.seed(131)
# Le graphe généré sera alors toujours le même !
##########################################################
vec2 <- NULL
for (i in 1:c(Nb_sommets*2)){vec <- paste0(sample(LETTERS[2:26], 1, TRUE),sample(LETTERS[c(1,5,9,15,21,25)], 1, TRUE),sample(LETTERS[2:26], 1, TRUE))
vec2 <- c(vec2,vec)}
Sommet <- sample(unique(vec2),Nb_sommets, replace=FALSE)
from <- sort(rep(Sommet, sort(sample(c(1,2,3,4,0), size=Nb_sommets, prob = dlnorm(1:5, sdlog = 1, log = FALSE), replace=TRUE))))
to <- sort(rep(Sommet, sort(sample(c(1,2,3,4,0), size=Nb_sommets, prob = dlnorm(1:5, sdlog = 1, log = FALSE), replace=TRUE))))
m <- min(c(length(from),length(to)))
lien <- as.data.frame(cbind(from = from[sample(1:m, replace=F)], to = to[sample(1:m, replace=F)]))
lien$from <- as.vector(lien$from)
lien$to <- as.vector(lien$to)
for (l in 1:round(Nb_sommets/6,0)){smt <- lien[rownames(lien[lien$from == lien[l,"to"],]), "to"];lien <- rbind(lien,c(lien[l,"from"],smt[1]))}
lien <- lien[lien$from!=lien$to,]
mes_liens <- unique(lien)
mes_liens$value <- sample(1:7, nrow(mes_liens), prob = dlnorm(1:7, sdlog = 2, log = FALSE), replace = TRUE)
mes_sommets <- data.frame(name = Sommet, sexe = sample(x = c("Femme", "homme"), prob=c(5.5,4.5), size = Nb_sommets, replace = TRUE),
age = sample(x = c(18:60), prob=sample(1:5,43,replace=TRUE), size = Nb_sommets, replace = TRUE),
salaire = sample(seq(from=1530,to=5130,length.out=Nb_sommets),
prob=dlnorm(1:Nb_sommets, sdlog = 3, log = FALSE)))
mes_liens <- mes_liens[!is.na(mes_liens$from),]
rm(list=setdiff(ls(), c("mes_sommets","mes_liens")))
##########################################################
##########################################################
Les deux objets créés par ce bout de code sont :
- un dataframe contenant une liste de liens valués :
## from to value
## 1 QAN YEW 5
## 2 VIL FAQ 5
## 3 QUY VIL 2
## 4 VIO UYH 1
## 5 BIO QUY 5
## 6 OIV BAO 1
## 7 WUL QUY 1
## 8 QUY ROE 1
## 9 WOL ROE 1
## 10 BIO WUL 1
- un dataframe contenant la liste des sommets et trois attributs :
## name sexe age salaire
## 1 OIV homme 45 1530
## 2 ZYE Femme 33 3930
## 3 PAF Femme 51 2130
## 4 JUP homme 36 2280
## 5 JEQ Femme 20 2880
## 6 KOX Femme 28 1680
## 7 BAO homme 22 3630
## 8 WUL Femme 48 5130
## 9 EAD Femme 49 2580
## 10 PII homme 50 3180
A chaque exécution du code, un jeu de données de réseau aléatoire (orienté et valué) est généré. Exemple :
A partir des deux objets générés par le code ci dessus, vous devez :
1) Formalisez votre réseau en objet ‘igraph’ orienté et valué
2) Affichez votre graphe en utilisant les différentes variables visuelles (couleur, forme, taille…) pour représenter les différents attributs des sommets et des arêtes.
3) Calculez les principaux indicateurs globaux
Quelle est la densité de votre graphe ? Est-il connexe ? Combien comporte-t-il de composantes connexes ?
Quel en est le diamètre, sa transitivité ?…
3) Extrayez un sous graphe en fonction de deux attributs
ex : Sous-graphe des femmes de plus de 30 ans
Puis, gardez uniquement les liens de valeur supérieure à 1
3) Calculez les différents indicateurs de centralité sur le graphe complet
Attention, il s’agit d’un graphe orienté ! Visualisez la distribution des degrés
4) Détecter des communautés en utilisant une fonction de partitionnement
Affichez le résultat. Puis, comparez différents résultats de partitionnement
5) Générez un nouveau jeu de données, puis ré-exécutez l’ensemble du code que vous venez d’écrire
L’exécution de votre programme se déroule-t-elle correctement ? Si non, trouvez pourquoi !
Sources & références
Il existe de nombreuses ressources documentaires sur R. En voici quelques-unes en libre accès et principalement portées sur l’analyse de réseau. Plusieurs d’entre elles ont été utilisées pour produire ce document.
- R pour les débutants, Emmanuel Paradis
- Analyser les réseaux avec R (packages statnet, igraph ettnet), Laurent Beauguitte
- L’analyse de graphes avec R : un aperçu avec igraph, Sébastien Plutniak
- Practical statistical network analysis (with R and igraph), Gabor Csardi
- Network Analysis and Visualization with R and igraph, Katherine Ognyanova
- Visualisation de réseaux avec R, Katherine Ognyanova
- Introduction to Network Analysis with R, Jesse Sadle
- Network Analysis in R Cookbook, Sacha Epskamp
- An awesome list of network analysis resources, François Briatte
– R Session info –
## _
## platform x86_64-pc-linux-gnu
## arch x86_64
## os linux-gnu
## system x86_64, linux-gnu
## status
## major 3
## minor 6.1
## year 2019
## month 07
## day 05
## svn rev 76782
## language R
## version.string R version 3.6.1 (2019-07-05)
## nickname Action of the Toes
## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: CentOS Linux 7 (Core)
##
## Matrix products: default
## BLAS: /opt/R/3.6.1/lib64/R/lib/libRblas.so
## LAPACK: /opt/R/3.6.1/lib64/R/lib/libRlapack.so
##
## locale:
## [1] LC_CTYPE=fr_FR.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=fr_FR.UTF-8 LC_COLLATE=fr_FR.UTF-8
## [5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8
## [7] LC_PAPER=fr_FR.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] DT_0.7 igraph_1.2.4.2 ggplot2_3.2.0 plyr_1.8.4 stringr_1.4.0
## [6] rvest_0.3.4 xml2_1.2.0
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.3 later_0.8.0 compiler_3.6.1 pillar_1.4.2
## [5] rmdformats_0.3.6 tools_3.6.1 digest_0.6.24 lattice_0.20-38
## [9] jsonlite_1.6 evaluate_0.14 tibble_2.1.3 gtable_0.3.0
## [13] pkgconfig_2.0.2 rlang_0.4.4 Matrix_1.2-17 shiny_1.3.2
## [17] crosstalk_1.0.0 curl_3.3 yaml_2.2.1 xfun_0.12
## [21] withr_2.1.2 httr_1.4.0 dplyr_0.8.4 knitr_1.28
## [25] htmlwidgets_1.3 grid_3.6.1 tidyselect_1.0.0 glue_1.3.1
## [29] R6_2.4.0 rmarkdown_1.14 bookdown_0.11 purrr_0.3.2
## [33] selectr_0.4-1 magrittr_1.5 promises_1.0.1 scales_1.0.0
## [37] htmltools_0.4.0 assertthat_0.2.1 xtable_1.8-4 mime_0.9
## [41] colorspace_1.4-1 httpuv_1.5.1 labeling_0.3 stringi_1.4.6
## [45] lazyeval_0.2.2 munsell_0.5.0 crayon_1.3.4
Ce document est mis à disposition selon les termes de la Licence Creative Commons :
Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)