{"word_count": 601, "character_count": 4900}
La cartographie automatisée de flux n'est pas une chose facile à réaliser, et ce quelque soit le logiciel utilisé.L'objectif de ce billet est de proposer un exemple de cartographie de flux avec R.[MAJ] J'ai déplacé les données et ajouté le code sur GitHub. [/MAJ]Les données utilisées sont des données de migration résidentielles issues de l'Insee et un fond de carte des départements français diffusé par l'IGN. Le tout est à télécharger ici sous forme de RData.Cet exemple s'appuie sur le package igraph dédié à l'analyse et à la représentation de graphs. Les fonctionnalités de représentation de graphs orientés sont mobilisés pour représenter les migrations résidentielles entre les 6 départements les plus attractifs (hors Ile de France) entre 2003 et 2008.# chargement des packages nécessaireslibrary(igraph)library(maptools)# chargement des données # téléchargeables ici : http://wukan.ums-riate.fr/flow/dep.RDataload("dep.RData")# extraction des coordonnées des centroides des departementscentres &#60;- cbind(depGeom@data[,"CODE_DEPT"],                 as.data.frame(coordinates(depGeom)))names(centres)&#60;-c("id","X","Y")# création de la variable d'attractivité des départements :# le nombre d'arrivéesattract &#60;- aggregate(depMig$fij, by = list(depMig$dest), sum)names(attract) &#60;- c("id", "nbarrivee")# Sélection flux entre les 6 départements recevant le plus de # migrations résidentielles à l'exeption des département # de l'IDF, de l'étranger (99) et des DOM (97)# liste des départements à exclurelistExcl &#60;- c("75", "92", "77", "78", "93", "94", "95", "97", "99")# exclusion de ces départementsmig &#60;- depMig[!depMig$dest %in% listExcl &#38;                 !depMig$orig %in% listExcl,]# liste des départements à sélectionner listDep &#60;- attract[order(attract$nbarrivee[!attract$id %in% listExcl],                          decreasing = T),][1:6,"id"]# sélection de ces départementsmig &#60;- mig[mig$orig %in% listDep &#38; mig$dest %in% listDep, ]# transformation des flux sélectionnés en graphg &#60;- data.frame(mig[,c("orig", "dest")])g &#60;- as.matrix(g)g &#60;- graph.edgelist(g, directed=TRUE)# création de la liste des noeuds (vertex)vert &#60;- data.frame(id = V(g)$name)# affectation des positions des coordonnées des centroides aux noeudscoords &#60;- centres[match(vert$id, table = centres$id), ]coords &#60;- as.matrix(coords[,2:3])g$layout &#60;- coords# ajout d'un attribut  aux noeudsV(g)$weights &#60;- attract[match(vert$id, table = attract$i), "nbarrivee"]# ajout d'un attribut d'épaisseur aux liens (edge)x &#60;- get.edgelist(g)E(g)$fij &#60;- mig[match(x = paste(x[,1],x[,2],sep="_"),                       table = paste(mig$orig,mig$dest,sep="_")),"fij"]# affichage du fond de carteplot(depGeom, col="pink")# affichage du graph#png("carte1.png", width = 415, height = 450)par(mar=c(0,0,0,0),oma = c(0,0,0,0) )plot.igraph(g, add=T, rescale = F,             vertex.size = (V(g)$weights)*100,            edge.curved = 0.4,             edge.width =  E(g)$fij/250,            edge.color = "red")#dev.off()Cette première représentation pose un problème : la taille des pointes de flèches est la même pour toutes les flèches, le paramètre edge.arrow.size n’accepte pas de vecteur en entrée.Une solution est de faire autant de plots que de flèche et de les superposer (solution proposée ici).# png("toto.png", width = 415, height = 450)par(mar=c(0,0,0,0),oma = c(0,0,0,0) )# Affichage de la carte des départementsplot(depGeom, col="black", bg = "grey", border = "#ffffff00")# Titre et légendemtext(text = " Migrations résidentielles majeures entre les \n départements les plus attractifs (hors IDF)\n",      side = 3,adj=0, cex=1.5, line = -4.5)mtext(text = "Source : Insee, migrations résidentielles 2003-2008 ",      side = 1,adj=1,cex=0.8, line = -2)mtext(text = " T. Giraud, 2014",side = 1,adj=0,cex=0.8, line = -2)# ajout des flèches une par unefor (e in seq_len(ecount(g))) {  graph2 = delete.edges(g, E(g)[(1:ecount(g))[-e]])  plot(graph2,        vertex.size = (V(g)$weights)*250,       edge.curved = 0.5,       edge.width=E(graph2)$fij / 170,       # nous limitons la taille des plus grosses flèches à 1.75        edge.arrow.size = if(E(graph2)$fij / 700 &#62;= 1.75){         1.75         } else {           E(graph2)$fij/700           },       edge.color = "red",       vertex.label=NA,        add=TRUE,        rescale = F  )}#dev.off()Si le résultat est quand même très satisfaisant pour une cartographie automatique de flux, quelques problèmes subsistent :La pointe des flèches est moche (surtout pour les grandes flèches et on ne peut pas la changer.Le départ et les arrivées de flux ne "visent" pas les centres des cercles.L'ajout d'une belle légende concernant à la fois les cercles et les flux n'est vraiment pas évident.L'adaptation des tailles de cercles, des épaisseurs de flux et des tailles de pointes de flèches n'est pas gérée.