User Tools

Site Tools


mohammed_senhaji:solution_homework2

Graphe géant

Projet visualisation de données

Programme européen de financement de la recherche

Les données

Nous avons choisi de travailler sur les données FP7 – European money funding research. Ce jeu de données fournit pour chaque projet de recherche, une liste des partenaires qui y ont participé ainsi que les montant des subventions reçues de la part de l'union européenne pour ce projet. Les données sont sous la forme d'un fichier Excel, contenant une ligne par participation d'un partenaire à un projet. Pour leur exploitation, nous avons considéré que chaque ligne des données représentait une arrete entre un sommet de type projet, et un de type partenaire, ainsi nous avons obtenu un graphe biparti. Le script suivant est le code de création des arrêtes.

addEdges.py
from tulip import *
 
def main(graph): 
	for e in graph.getEdges():
		graph.delEdge(e)
	f=open("data.csv","r+")
	i=0
	for line in f :
		if i!=0 :
			liste=line.split(';')
			#print liste
			project=int(liste[0])
			#print project
			partner=int(liste[18])
			#print partner
			noeudPart=tlp.node(1)
			noeudProj=tlp.node(2)
 
			for n in graph.getNodes():
				if (not TYPE[n]) :
					#print "partner="+str(LIUN_PIC[n])
					if LIUN_PIC[n]==partner:
						noeudPart=n
				if TYPE[n] and PROJECT[n]==project:
					noeudProj=n
 
			edge=graph.addEdge(noeudPart,noeudProj)
			EU_financial_contribution[edge]=int(liste[15].replace("\xc2\xa0",""))
			EU_financial_contribution_rate[edge]=liste[14]
			SO_AGGREGATED[edge]=liste[8]
		else :
			i+=1
	f.close()

Mise en forme du graphe

Pour aider à faire des hypothèses et de guider la suite du travail, on peut choisir la taille et la couleur des nœuds, et définir un label. Le label est assez naturel (entrée SHORT_NAME pour les partenaires et entrée ACRONYM pour les projets). La taille des nœuds peut représenter leur degré ; pour celà, on calcule la racine carée du degré (la surface visible est donc proportionnelle au degré du nœud). Pour la couleur, on choisit le jaune pour les projets ; on cherche à distinguer, parmi les partenaires, les institutions de recherche publiques (principalement des universités) des entreprises. Les colonnes Legal_status et Organisation_type semble pouvoir faire cette distinction. Cependant, le sens exact de ces colonnes et de leur contenu n’est pas connu.

in fine, il semble que la colonne Organisation_type suffise à distinguer les entités suivantes :

—HES : universités (bleu nuit)

—PRC : entreprises (rouge)

—REC : fondations et institutions dédiées à la recherche (bleu ciel)

—PUB : autres organismes publics, souvent sans lien avec la recherche (vert)

—OTH : autres ou inconnu (noir)

À quelques exceptions près. L’université de Karlsruhe (label AIFB) est notée PRC au lieu de HES. C’est peut-être dû à une erreur dans les données.

colorsize.py
        import math
 
 
        for n in graph.getNodes():
                if TYPE[n]:
                        viewLabel[n]=ACRONYM[n]
                        viewColor[n]=tlp.Color(255, 255, 0, 128)
                else:
                        viewLabel[n]=SHORT_NAME[n]
                        if Organisation_type[n]=='HES':
                                viewColor[n]=tlp.Color(0, 0, 255, 128)
                        elif Organisation_type[n]=='OTH':
                                viewColor[n]=tlp.Color(0, 0, 0, 128)
                        elif Organisation_type[n]=='PRC':
                                viewColor[n]=tlp.Color(255, 0, 0, 128)
                        elif Organisation_type[n]=='PUB':
                                viewColor[n]=tlp.Color(0, 255, 0, 128)
                        elif Organisation_type[n]=='REC':
                                viewColor[n]=tlp.Color(0, 255, 255, 128)
                sq=math.sqrt(viewMetric[n])
                viewSize[n]=tlp.Size(sq, sq)

Connectivité du graphe

Pour mieux naviguer dans le graphe, on construit un sous graphe pour chaque nœud contenant son voisinage. Comme le graphe est biparti, on obtient pour chaque nœud une étoile. Cependant, le décompte des arrêtes et des sommets contredit parfois cette affirmation. Le sous-graphe représentant le voisinage du CNRS (CNRS1) compte 277 nœuds (276 projets soutenus, et le CNRS lui-même), mais 284 arêtes. Ceci est certainement dû à ce que le CNRS peut soutenir un même projet via plusieurs composantes (typiquement des UMR). Dans le graphe, cela se traduit par des arêtes multiples.

Cela permet par exemple de constater que le projet SIQS intéresse presque exclusivement les universités et les institutions de recherche, et que le projet FI-WARE (voir image ci-dessous) intéresse plus spécifiquement des entreprises. On trouve facilement les nœuds “intéressants” en triant les sous-graphes selon leur nombre de sommets ou d’arêtes.

Partenaires particaipant au projet FI-WARE

Cette première approche laisse déjà voir que la distribution des degrés est sensiblement différente pour les projets et les partenaires. On construit deux histogrammes représentants la distribution de ces degrés pour deux sous-graphes : celui des partenaires et celui des projets (en l’occurence, ces sous-graphes sont sans arêtes).

La distribution des degrés des partenaires (voir image ci-dessous) est d’un type fréquent dans les grand graphes de terrains (exponentielle décroissante : on utilise une échelle log-log pour le visualiser correctement). En analysant un peu plus, on constate que la distribution de chaque type d’organisation est du même type, mais que les entreprises contribuent nettement plus aux nœuds de petit degré que les autres types d’institutions, mais nettement moins au nœuds de gros degré. Ainsi, les partenaires de plus gros degré sont essentiellement des instituts dédiés à la recherche et des universités.

Histogramme des degrés des partenaires

La distribution des projets est une courbe en cloche ; un projet tend à avoir environ 8 partenaires.

projPart.py
        import math
 
	gcopie=graph.getSubGraph("gcopie")
	if graph.isSubGraph(gcopie) :
		graph.delSubGraph(gcopie)
 
 
	gcopie=graph.addSubGraph("gcopie")
	gprojet=gcopie.addSubGraph("gprojet")
	gpart=gcopie.addSubGraph("gpart")
	subproj=gcopie.addSubGraph("subproj")
	subpart=gcopie.addSubGraph("subpart")
	subuniv=gcopie.addSubGraph("subuniv")
	subentr=gcopie.addSubGraph("subentr")
	subrech=gcopie.addSubGraph("subrech")
	subpubl=gcopie.addSubGraph("subpubl")
	subothe=gcopie.addSubGraph("subothe")
 
 
	list=[]
 
	for n in graph.getNodes():
		gcopie.addNode(n)
	for e in graph.getEdges():
		gcopie.addEdge(e)
 
	for n in gcopie.getNodes():
		gprojet.addNode(n)
		gpart.addNode(n)
		if TYPE[n]:
			subproj.addNode(n)
		else:
			subpart.addNode(n)
			if Organisation_type[n]=='HES':
				subuniv.addNode(n)
			if Organisation_type[n]=='PRC':
				subentr.addNode(n)
			if Organisation_type[n]=='REC':
				subrech.addNode(n)
			if Organisation_type[n]=='PUB':
				subpubl.addNode(n)
			if Organisation_type[n]=='OTH':
				subothe.addNode(n)
		if viewMetric[n]>55:
			list.append(n)
	for e in gcopie.getEdges():
		gprojet.addEdge(e)
		gpart.addEdge(e)
 
 
	Hubs=gcopie.inducedSubGraph(list)
	Hubs.setName("Hubs")
 
	for n in gcopie.getNodes():
		list=[n]
		for m in gcopie.getInOutNodes(n):
			list.append(m)
		if TYPE[n]:
			p=gprojet.inducedSubGraph(list)
			p.setName(ACRONYM[list[0]])
		else:
			p=gpart.inducedSubGraph(list)
			p.setName(SHORT_NAME[list[0]])

https://visualisationfp7.googlecode.com/svn/degrs.tlpx

Question 1

Y'a-t-il des organisations HUB, qui couvrent la majorité des projets ? Les hubs sont-ils les mêmes pour tous les objectifs stratégiques ? Quelles sont les organisations qui couvrent plusieurs objectifs stratégiques ?

Pour répondre à cette question, on a procédé en deux étapes, premièrement nous avons mis en évidence l'existence des Hubs, en triant les partenaires selon le nombre de projets auxquels ils participent (leur degré dans le graphe), et en déssinant une courbe du nombre cumulé de projets couverts par les plus gros partenaires. La courbe obtenue a confirmé l'existence de partenaires Hubs, comme le montre la figure suivante.

hub.py
from tulip import *
from sets import *
 
def main(graph):
 
	proj=[]
	part=[]
	partcouv=[]
	projcouv=set()
 
	for l in graph.getNodes():
		if TYPE[l]:
			proj.append(l)
		else:
			part.append(l)
 
	dmax=0
	for n in part:
		if graph.deg(n)>dmax :
			dmax=graph.deg(n)
	listeDeg=[]
	for i in range(dmax+1):
		listeDeg.append([])
	for n in part :
		listeDeg[dmax-graph.deg(n)].append(n)
 
	valeurs=[1,2,3,4,5,6,8,10,15,20,30,40,50,60,70,80,200]
	for nbpart in valeurs :
		i=0
 
		for l in listeDeg:
			for n in l :
				if i<nbpart:
					i+=1
					partcouv.append(n)
					for k in graph.getInOutNodes(n):
						projcouv.add(k)
 
		print str(nbpart)+' : '+str((float(len(projcouv))/len(proj))*100)

La couverture des projets par les plus gros partenaires

Dans un second temps, on a créé un script python qui, crée un graphe dont les sommets sont des partenaires et des SO. Ensuite pour chaque Objectif Stratégique (SO), on trouve les partenaires participant à plus de 11% des projets, et on crée un sous-graphe avec les sommets de ces partenaires auxquels on ajoute le sommet du SO. Les pourcentages de participations de chaque partenaire à un SO, sont stockés dans un attribut 'Weight' des arrêtes. A la fin on rajoute un sommet représentant l'ensemble des SO, et on le relie aux plus gros hubs détectés avec le script précédent. Le but étant de voir si ces hubs sont communs à beaucoup de SO. La visualisation de ce graphe permet de dire que seuls certains partenaires sont communs à la majorité des SO, mais qu'en général chaque SO possède ses propres hubs, qui ne font pas forcément partie des hubs du graphe entier (voir image). Snapshot du graphe final obtenu

Le fichier tlpx ainsi que le code sont disponibles sur ce lien. https://visualisationfp7.googlecode.com/svn/HUB_SO.tlpx

Question 2

Y a-t-il des différences significatives entre les financement des objectifs stratégiques ? Quelle est la répartition des financements par pays ? Y a-t-il une différence selon les objectifs stratégiques ?

Premièrement pour la répartition des financements par SO, on a produit deux graphiques qu'on peut voir sur les images qui suivent :

Répartition des financements par SO

 Histogramme des financements des SO

Par la suite, nous avons généré un sous-graphe appelé “souspart” qui ne contient que des sommets de type partenaire et les relie s'ils ont au moins un projet en commun. Nous avons ensuite créé un méta-nœud par pays, que nous avons placé sur un fond de carte en utilisant la vue cartographique de tulip. Les couleurs des sommets représentent le statut du pays (état membre, pays en développement…). Enfin la taille des sommets correspond à la somme des financement reçus par le pays. Nous nous sommes rendus compte de la grande différence de financement des pays européens et des autres et avons créé une deuxième version où nous avons retiré les pays de l'UE et associés. La couleur des arrête représente le nombre de projets partagés entre les pays.

Financement par pays

Financement par pays hors europe

Les scripts sont dans les tlpx disponibles sur ces liens :

https://visualisationfp7.googlecode.com/svn/Europe_Budget.tlpx

https://visualisationfp7.googlecode.com/svn/World_Budget.tlpx

Ensuite, nous nous sommes posés la même question mais pour chacun des différents SO. Pour cela nous avons procédé de la même façon mais au lieu de relier les pays entre eux nous les avons relié à de nouveaux sommets, un par SO. La couleur des arrêtes représente le financement reçu par le pays pour le SO en question.

 Pays participant à un SO

Pour les mêmes raisons que précédemment nous avons créé une version où les pays européens n'apparaissent pas.

Pays non européens participant à un SO

Les scripts sont dans les tlpx disponibles sur ces liens :

https://visualisationfp7.googlecode.com/svn/projet_SO.tlpx

https://visualisationfp7.googlecode.com/svn/projet_SOWorld.tlpx

Le fichier “europe_budget.ylpx” peut aussi grâce à l'outil “afficher le voisinage” montrer les pays collaborant le plus avec un pays donné. Par exemple ci dessous on peut observer les collaborateurs principaux du Brésil:

Les principaux pays partenaires du Brésil

Question 3

Existe-t-il des objectifs qui intéressent spécifiquement des organismes d’un certain type ?

Pour répondre à cette question, il suffit d’agglomérer dans un méta-nœud les projets par objectifs d’une part, et les partenaires par types d’autre part. La taille des méta-nœuds représente le nombre de sommets qui y sont agglomérés, indépendament de l’importance de ces sommets.

Le graphe résultant est biparti quasi-complet, mais on peut visualiser l’importance des méta-arêtes (en nombre d’arêtes), en jouant sur leur taille (pour distinguer entre elles les méta-arêtes les plus importantes, i.e. celles qui regroupent plus de 100 arêtes) et sur leur transparence (pour distinguer les autres méta-arêtes entre elles).

On constate ici par exemple que les entreprises s’impliquent moins dans l’objectif 22, qui concerne les technologies du futur (i.e. non encore exploitables par les entreprises), et favorisent les objectifs 17, 18 et 19 (concernant respectivement l’efficaité énergétique, les transports et… les entreprises).

metatype.py
	for e in graph.getEdges():
		if graph.isMetaEdge(e):
			graph.delEdge(e)	
 
	listeSO=['e-infrastructures','01 Future Networks and Internet','02 Software, Services and internet connected objects','03 Trustworthy ICT','04 Networked Media','05 Cognitive Systems and Robotics','06 Nanoelectronics','07 Micro/nanosystems','08 Embedded Systems','09 Photonics',
	'10 Organic and large area Electronics','11 Language Technologies','12 Intelligent Information Management','13 ICT for Health','14 ICT and Ageing','15 ICT for Inclusion','16 ICT for Governance and Policy Modelling','17 ICT for Energy Efficiency','18 ICT for Transport',
	'19 ICT for the Enterprise','20 ICT for Learning','21 Digital Libraries','22 FET','23 International Cooperation','24 Accompanying Measures','25 Big Data','26 Creativity']
 
	def SO(n):
		if SO_AGGREGATED[n]=="e-infrastructures" :
			return 0
		else :
			return int((SO_AGGREGATED[n])[0:2])
 
 
	gcopie=graph.addSubGraph("gcopie")
	gccopie=gcopie.addSubGraph("gccopie")
 
	projlist=[]
	for n in graph.getNodes():
		gcopie.addNode(n)
		gccopie.addNode(n)
		if TYPE[n]:
			projlist.append(n)
	for e in graph.getEdges():
		gcopie.addEdge(e)
		gccopie.addEdge(e)
 
	#def sortdeg(m, n):
	#	return int(viewMetric[m]-viewMetric[n])
#		
#	projlist.sort(sortdeg)	
 
	d={0:[], 1:[], 2:[], 3:[], 4:[], 5:[], 6:[], 7:[], 8:[], 9:[], 10:[], 11:[], 12:[], 13:[], 14:[], 15:[], 16:[], 17:[], 18:[], 19:[],
	   20:[], 21:[], 22:[], 23:[], 24:[], 25:[], 26:[]}
 
	for n in projlist:
		nn=SO(n)
		viewLayout[n]=tlp.Coord(150, nn)
		d[nn].append(n)
 
	mnl=[]
	labels=[]
	for i in range(27):
		mn=gccopie.createMetaNode(d[i], False, False)
		viewSize[mn]=tlp.Size(sqrt(len(d[i])), sqrt(len(d[i])))
		viewLayout[mn]=tlp.Coord(10+(400*i)/27, 150)
		viewColor[mn]=tlp.Color(255, 255, 0, 32)
		viewLabel[mn]="test"
		assert viewLabel[mn]=="test"
		mnl.append(mn)
 
	hes=[]
	oth=[]
	prc=[]
	pub=[]
	rec=[]
 
#	y=-200
	y=0
	for n in gccopie.getNodes():
		if not TYPE[n]:
			if Organisation_type[n]=='HES':
				hes.append(n)
	#			viewLayout[n]=tlp.Coord(0,  0)
			if Organisation_type[n]=='PRC':
				prc.append(n)
#				viewLayout
			if Organisation_type[n]=='REC':
				rec.append(n)
			if Organisation_type[n]=='PUB':
				pub.append(n)
			if Organisation_type[n]=='OTH':
				oth.append(n)
 
	Hes=gccopie.createMetaNode(hes, False, False)
	viewSize[Hes]=tlp.Size(sqrt(len(hes)), sqrt(len(hes)))
	viewColor[Hes]=tlp.Color(0, 0, 255, 32)
	viewLayout[Hes]=tlp.Coord(0, 0)
	viewLabel[Hes]="Univ."
 
	Prc=gccopie.createMetaNode(prc, False, False)
	viewSize[Prc]=tlp.Size(sqrt(len(prc)), sqrt(len(prc)))
	viewColor[Prc]=tlp.Color(255, 0, 0, 32)
	viewLayout[Prc]=tlp.Coord(0, 300)
	viewLabel[Prc]="Ent."
 
	Rec=gccopie.createMetaNode(rec, False, False)
	viewSize[Rec]=tlp.Size(sqrt(len(rec)), sqrt(len(rec)))
	viewColor[Rec]=tlp.Color(0, 255, 255, 32)
	viewLayout[Rec]=tlp.Coord(400, 0)
	viewLabel[Rec]="Rec."
 
	Pub=gccopie.createMetaNode(pub, False, False)
	viewSize[Pub]=tlp.Size(sqrt(len(pub)), sqrt(len(pub)))
	viewColor[Pub]=tlp.Color(0, 255, 0, 32)
	viewLayout[Pub]=tlp.Coord(400, 300)
	viewLabel[Pub]="Pub."
 
	Oth=gccopie.createMetaNode(oth, False, False)
	viewSize[Oth]=tlp.Size(sqrt(len(oth)), sqrt(len(oth)))
	viewColor[Oth]=tlp.Color(0, 0, 0, 32)
	viewLayout[Oth]=tlp.Coord(200, 300)
	viewLabel[Oth]="Oth."
 
 
 
	for i in range(27):
		viewLabel[mnl[i]]=str(i)
 
	for e in graph.getEdges():
		if not graph.isMetaEdge(e):
			n=graph.source(e)
			proj=graph.target(e)
			so=SO(proj)
			pproj=mnl[so]
			if Organisation_type[n]=='HES':
				ppart=Hes
			elif Organisation_type[n]=='OTH':
				ppart=Oth
			elif Organisation_type[n]=='PRC':
				ppart=Prc
			elif Organisation_type[n]=='PUB':
				ppart=Pub
			elif Organisation_type[n]=='REC':
				ppart=Rec
			else:
				print Organisation_type[n]
			ee=graph.existEdge(pproj, ppart, False)
			weight[ee]+=1
	ww=0
	for e in graph.getEdges():
		ww=max(ww, weight[e])
		cc=weight[e]
		viewColor[e]=tlp.Color(0)
		viewSize[e]=tlp.Size(cc/100)
		if viewSize[e][0]==0:
			viewColor[e]=tlp.Color(0, 0, 0, int(2.55*cc))
	print ww

 Liens entre les SO et les types de partenaires

https://visualisationfp7.googlecode.com/svn/metatypes.tlpx

/net/html/perso/melancon/Visual_Analytics_Course/data/pages/mohammed_senhaji/solution_homework2.txt · Last modified: 2015/01/22 18:12 by senhaji