Développement d’un script Python générant un graphique composé de plusieurs courbes à partir d’un fichier Shape ouvert sur Qgis 1


Ceci est un tutoriel pour ceux qui souhaitent faire des graphiques comprenant plusieurs lignes générées automatiquement, à partir de la table attributaire du .shp ouvert et sélectionné avec PyQgis.

graphique

Jeu de donnée

La donnée exploitée est issue des Opendata de la SNCF concernant les taux de ponctualité et du STIF pour les fichiers Shape des gares RER en Ile-de-France.

Le taux de ponctualité est une moyenne de chaque ligne des RER relevé mensuellement. Ainsi, ce que l’on cherche à montrer est ce taux de ponctualité, pour une période choisie avec un nombre de ligne qui varie en fonction de la station choisie.

Pour notre exemple, nous avons pris le cas de la station de Châtelet-les-Halles où passe le RER A, B et D mais attention les données sont relevé pour l’ensemble des stations et pas que pour celle de Châtelet.

 

Manipulations préliminaires

Après jointure des deux données à l’aide de Qgis (déjà faite ici), ouvrir le nouveau Shape créé et nommé « gare_chatelet_j » dans Qgis également. Y ouvrir la table attributaire afin de prendre connaissance de la donnée. Les valeurs jointes et exploitables de la couche sont dans les colonnes à la fin.

chatelet

La période à utiliser se trouve dans la colonne « date » et les lignes à tracer sont les colonnes respectives « RER_A », « RER_B » et « RER_D ».

 

Puis, on ouvre dans « extension », la console Python :

On ouvre également le fichier .py, lu comme un fichier .txt, comprenant le script.

Il faut modifier i = date de départ, k = date de fin et p = sélection de la 1ère colonne équivalent à la 1ère courbe, q = idem pour la dernière courbe à avoir.

Le but est de prendre toutes les données comprises entre ces bornes.

Ctrl+a, Ctrl+c

Aller dans Qgis sur la console Python :

Faire Ctrl+v à côté du >>> et votre graphique va apparaître automatiquement.

 

Script

import os

import time

import numpy 

from pylab import *

import dateutil

from qgis.utils import iface

import matplotlib.pyplot as plt

layer = qgis.utils.iface.activeLayer() #selection de la couche en cours d’utilisation 

i=’2013-01′ #variable de la date de départ MODIFIABLE

k=’2013-12′ # variable de la date de fin MODIFIABLE

p=’RER_A’ #MODIFIABLE

q=’RER_D’ #MODIFIABLE

##selection des colonnes ‘toto’, ‘titi’,’tata’ par la detection du numero de colonne inscrit par la fenetre

cold = layer.fieldNameIndex(p) #detection numero de col depart

colf = layer.fieldNameIndex(q) #detection numero de col fin 

##creation de listes vides

abscisses = [] #Liste vide pour les abscisses

ordonnees=[[] for a in range (cold,colf+1)] #pareil pour l’ordonnee avec une condition de a inclus 

#entre cold et colf qui developpe a * ([])

##selection de toutes les donnees en abscisse, de la colonne date dans liste

for ligne in layer.getFeatures(): #importation ligne par ligne des attributs du shape

#on nomme la fonction ‘op’ qui est egale a 

# »dans la colonne date, on selectionne les lignes » 

    abscisses.append(ligne[‘date’])

##traduction des valeurs introduites en abscisses (ici date) en index (soit le numero de la ligne)

bla=abscisses.index(i) 

blo=abscisses.index(k)

#definition de la boucle pour selectionner les donnees

tp=[] #definition d’une liste vide

for ligne in layer.getFeatures():  #pareil que precedement 

    op=abscisses.index(ligne[‘date’]) #creation de « op » qui comprend la liste des valeurs index de la colonne ‘date’ 

    a=0 #compteur

    if int(op)>=(bla) and int(op)<=(blo): #delimitation des bornes de debut et fin pour les dates a selectionner 

    #par condition

        tp.append(int(op)) #si op est compris entre bla et blo (les dates choisies), alors on ajoute dans la liste ‘tp’ 

        #les valeurs index comprises dans cette borne [bla;blo]

        while (cold+a)<=colf : #Boucle : tant que cold+a est inférieur à colf

            ordonnees[a].append(ligne[cold+a]) # pour l’ordonnee, on inclut les donnees des colonnes choisies 

            #par exemple, ordonnees[0] contient les valeurs de la colonne cold

            a+=1 #fin de la boucle pour revenir à a=a+1

##insertion des listes dans des matrices (pour avoir x et y dans la meme dimension)

n_dates=numpy.array(tp) #matrice pour x

n_ordonnees=numpy.array(ordonnees) #matrice pour y

##selection du nom des champs (pour la legende) 

fields=layer.pendingFields()

fieldus=[field.name() for field in fields]

##generescence du graph   

z=0 #nouveau compteur pour boucle

while (cold+z)<=(colf): #pareil que la boucle precedente

plot(n_dates, n_ordonnees[z], ls=’-‘, label=fieldus[cold+z]) #on pose les conditions du graph soit 

#(x,y,la couleur des courbes(modifiable par une autre boucle, type de ligne)

z+=1 #fin de la boucle

##definition d’une autre boucle pour la nomination des noms en abscisse pour le graphique

liste=[]

for ligne in layer.getFeatures():  

    liste.append(ligne[‘date’])

##Mise en page du graphique

plt.xlim()

plt.ylim()

plt.title(‘Releve de la ponctualite pour les RER de la gare de Chatelet-Les-Halles en 2013’) # insertion du titre 

plt.xlabel(‘annee/mois’) #insertion du nom de l’abscisse

plt.ylabel(‘Taux de ponctualite’) #pareil pour l’ordonnee

plt.xticks(n_dates, liste)

plt.legend()

plt.grid(True, ‘major’, ‘y’, ls=’–‘, lw=.5, c=’k’, alpha=.3) #creation de pointilles

plt.legend()

plt.show() #execution du graph 

Contexte

Etudiante en Master 1, Géomatique appliquée aux études urbaines et aux risques à l’Université de Cergy-Pontoise et actuellement stagiaire à la direction ingénierie et projets de SNCF Réseau, mon projet est de développer des outils SIG pour les données d’auscultation d’ouvrages d’art.

Ainsi, l’une des solutions apportée fut de créer un graphique comprenant plusieurs points relevés par période aléatoire en fonction du chantier. On y mesure l’altitude à chaque déplacement, relevée par les géomètres et on compare dans le temps l’évolution des points pour voir s’il y a une différence avec les relevés précédents.

 

Dossier : data_diffusion 2


Laissez un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Commentaire sur “Développement d’un script Python générant un graphique composé de plusieurs courbes à partir d’un fichier Shape ouvert sur Qgis

  • Pierre Vivet

    Salut Clothilde,
    Merci pour ce tutoriel bien pratique qui nous montre une autre façon d’utiliser QGIS.

    J’ai juste eu un problème avec la légende en abscisse : les dates commençaient toujours à la première date présente dans notre colonne ‘date’. Donc ça marchait très bien quand, comme montré dans cet exemple, notre date de départ était la première date à disposition. Mais si on définit par exemple i=’2013-06′ et k=’2014-05′ notre légende sera quand même écrite comme allant du 2013-01 au 2013-12.

    Le souci se trouvait dans le bloc suivant (accessoirement il manque vraiment une fonction ‘code’ à veillecarto pour écrire ça plus lisiblement dans les commentaires):
    ##definition d’une autre boucle pour la nomination des noms en abscisse pour le graphique
    liste=[]
    for ligne in layer.getFeatures():
    liste.append(ligne[‘date’])

    Dans cette boucle on récupère toutes lignes, alors qu’il nous faut seulement celles comprises entre nos deux index. On doit mettre en place un filtre pour sélectionner les index qui nous intéressent :
    ##definition d’une autre boucle pour la nomination des noms en abscisse pour le graphique
    fids=[]
    for x in xrange(bla,blo+1): #+1 sinon il nous manque la dernière date
    fids.append(x) #remplir la liste fids avec les index de toutes les dates étudiées

    request = QgsFeatureRequest()
    request.setFilterFids(fids) #mise en place du filtre pour le getFeatures

    liste=[]
    for ligne in layer.getFeatures(request):
    liste.append(ligne[d])

    A noter aussi que la variable d est utilisée pour la colonne ‘date’, ça facilitera la réutilisation pour d’autres données.
    Alors python n’est pas le langage que je connais le mieux, il y a peut-être plus efficace que cette proposition, mais ça a l’air de résoudre le problème de légende et ne pas en provoquer d’autres.