Graphique

Retrouver tous les sujets résolus.
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » jeu. 2 janv. 2020 17:13

Bonjour,
tu peux commencer par extraire ce dont tu as besoin des fichiers csv :
- le code de la ligne, les coordonnées du début et de la fin de celle-ci dans le fichier lignes-par-type
- le code de la ligne, les coordonnées de la gare dans le fichier liste-des-gares.

Et convertir les chaînes de caractères obtenues en entiers ou flottants.

Avec ce code :

Code : Tout sélectionner

import csv
with open('lignes-par-type.csv',newline='') as f :
    lire = csv.reader(f) # on transforme le fichier en fichier-objet
    liste = [ligne for ligne in lire] # on transforme le fichier-objet en une liste de listes
    liste_lignes = liste[1:] # on ne prend pas la première ligne d'en-tête
    lignes_debut_fin=[[int(ligne[0]),float(ligne[15]),float(ligne[16]),float(ligne[17]),float(ligne[18])] for ligne in liste_lignes if ligne[15] != '']

with open('liste-des-gares.csv',newline='') as h :
    extraction  = csv.reader(h)
    liste_brute = [ligne for ligne in extraction]
    liste_brute = liste_brute[1:]
    liste_gares = [[int(ligne[4]),float(ligne[15]),float(ligne[16])] for ligne in liste_brute if ligne[3]=='O' and ligne[15] != '']
Essaie déjà cela dans un éditeur Python, et essaie de le comprendre, ce n'est qu'une toute petite étape d'extraction de données.
Il te restera ensuite à construire un dictionnaire où chaque entrée est une gare SNCF et chaque valeur associée est la liste des gares sur la même ligne ainsi que les distances les séparant de la gare de départ.
Bonne continuation
anonyme

Re: Graphique

Message par anonyme » jeu. 2 janv. 2020 18:53

Merci beaucoup pour votre réponse SoS-Math 21.

Grâce à vous, je comprends vraiment beaucoup mieux, c'est incroyable !! Je vais tester cela tout de suite sur Python.

Et j'ai aussi réfléchi à autre chose cet après-midi : c'est la réalisation de la comparaison des moyens de transport. Pour l'instant mon prof m'a dit dans le mail qu'il m'a envoyé ce matin de me concentrer sur la comparaison du mode ferroviaire et du mode routier.

Je cherche donc actuellement un moyen pour les comparer. Je vais comparer les critères suivants : durée, coût, impact environnemental. Pour la durée, ça va, ce sera un calcul de distance et en connaissant la vitesse du moyen de transport, on a la vitesse. Mais pour le coût et pour l'impact environnemental : comment faire ? Supposons que le mode ferroviaire coûte 1€ par km et émette 100g de CO2 par km (il faudra que je trouve les vraies valeurs), comment intégrer ces informations dans le graphe ? Sur les poids des arêtes du graphe du réseau ferroviaire peut-être ? Dans le dictionnaire dont vous parlez ?

C'est encore flou pour moi, mais peut-être que vous avez une solution ?

Merci infiniment pour votre temps.
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » jeu. 2 janv. 2020 19:12

Bonjour,
effectivement, cela va compliquer les choses.
Si ton professeur t'a demandé d'utiliser l'algorithme de Dijkstra, cela signifie qu'il pense à des graphes pondérés, ce qui sous-entend que l'on va chercher à minimiser une seule grandeur qui pourra être : durée, distance, coût, émission de gaz à effet de serre.
On pourra alors construire des graphes pondérés pour chaque grandeur et il y aura alors autant de plus courts chemins que de grandeurs à minimiser.
Le plus dur dans ce travail sera la collecte et l'extraction de données.
Ceci dit, c'est un projet sur plusieurs semaines, non ?
Peut-être que ton professeur précisera davantage ses attentes à la rentrée.
Bonne continuation
anonyme

Re: Graphique

Message par anonyme » jeu. 2 janv. 2020 19:26

Merci encore pour votre réponse.

Oui, cela s'étale sur plusieurs semaines. Mon professeur a dit qu'il faudra rendre cela début février. Le problème est qu'il a dit avant les vacances qu'il souhaiterait que nous arrivions à la rentrée avec le graphe du réseau ferroviaire. En fait, sur une arête du graphe, peut-on y indiquer plusieurs poids ? Par exemple, si on a une arête entre A et B, et que la distance entre A et B fait un kilomètre. Peut-on indiquer comme poids sur l'arête AB : 1 (distance), 1 (coût en euro), et 100 (g de CO2 émis) ? Ou bien il faut construire un graphe pour chaque poids ?

Bonne soirée et merci !

Je suis vraiment désolé de vous déranger autant, mais ce projet compte pour mon dossier Parcoursup, j'ai vraiment envie de rendre un bon travail, surtout que je trouve ça intéressant.
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » jeu. 2 janv. 2020 22:20

Bonjour,
d'un point de vue mathématique, un graphe pondéré ne contient qu'une seule valeur sur les arêtes, donc j'aurais envie de dire qu'il te faudrait un graphe par grandeur.
Après, tu peux très bien mettre comme poids une liste de valeurs et construire un algorithme de Dijkstra avec une option de rang (0,1, 2,...) et qui appliquera la recherche du plus court chemin avec les éléments de rang 0 de la liste, ou avec les éléments de rang 1,...
Tout cela peut très bien se concevoir avec une fonction Python bien pensée.
Bon courage, il te reste pas mal de travail :)
Invité

Re: Graphique

Message par Invité » jeu. 2 janv. 2020 22:32

Merci pour la réponse. Effectivement, il reste encore énormément de travail, cela m'inquiète beaucoup... Cela vous dérange de m'aider sur le moyen terme ou pas ? Je suis vraiment très inquiet de ne pas réussir à finir...

Et dans un message, vous écriviez :
Il te restera ensuite à construire un dictionnaire où chaque entrée est une gare SNCF et chaque valeur associée est la liste des gares sur la même ligne ainsi que les distances les séparant de la gare de départ.
Comment construire un tel dictionnaire ? Quel est le code type à écrire ?

Merci encore...
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » jeu. 2 janv. 2020 23:25

Bonjour,
j'ai déjà dû te donner les grandes lignes :
il faudra parcourir la liste des gares (fichier liste-gare.csv) et pour chaque gare récupérer son code de ligne.
Ensuite parcourir les éléments de cette ligne et calculer leur distance par rapport à cette gare, avec le module geopy par exemple et mettre tout cela dans une liste.
Il y aura sûrement des boucles for à utiliser....
Je ne peux pas t'en dire plus, ton professeur est là pour cela. Le forum est sos-math est destiné à de l'aide ponctuelle, pas à un accompagnement au long cours.
Bonne continuation
Invité

Re: Graphique

Message par Invité » ven. 3 janv. 2020 03:52

L'ennui est que je n'ai pas bien compris la manipulation des dictionnaires...
Surtout, vous me dites qu'il y a des boucles for, mais je ne vois vraiment pas pourquoi.

Malheureusement, mon professeur est du genre, peu aidant... Il refuse de m'en dire plus.

C'est pour cela que je vous posais la question... Pourriez-vous me donner le code, ou une partie, ou le pseudo-code, pour construire ce dictionnaire ?
Tout ce que j'ai compris des dictionnaires, c'est ça :

Code : Tout sélectionner

capitales = dict()
capitales = {}  # dictionnaire vide
liste_capitales = [("France","Paris"), ("Allemagne","Berlin")]
capitales = dict(liste_capitales)
print(capitales)
Ou pourriez-vous au moins me donner un exemple de ce que je dois faire pour avoir le dictionnaire où chaque entrée est une gare SNCF et chaque valeur associée est la liste des gares sur la même ligne ainsi que les distances les séparant de la gare de départ ?

C'est promis, je ne vous dérangerai plus quand la rentrée sera passée, mais là j'ai vraiment besoin d'aide d'ici la rentrée...

Merci infiniment pour votre temps.
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » ven. 3 janv. 2020 09:22

Bonjour,
un dictionnaire Python est un tableau associatif qui se présente sous la forme d'une liste de couple clé : valeur.
Par exemple, si je veux associer chaque personne a son âge, j'écris :

Code : Tout sélectionner

dico = {} # création d'un dictionnaire vide
dico['Edouard'] = 23
dico['Sophie'] = 13
dico['Antoine'] = 34
,
alors le dictionnaire vaudra

Code : Tout sélectionner

{'Edouard' : 23, 'Sophie' : 13, 'Antoine' : 34}
Si j'ai besoin de réutiliser l'âge d'une personne, j'appelle dico['Antoine'] et cela me renvoie directement son âge
Dans ton cas, à la place des prénoms, tes clés seraient les numéros de gares (il faudra alors un peu modifier le code que je t'ai envoyé afin que la liste liste-gares contienne aussi le numéro d'identifiant code_uic première colonne, je te le donne dessous) et leurs valeurs seraient un dictionnaire dont les clés seraient les autres gares appartenant à la même ligne et leur valeur la distance qui les sépare de la gare du début.
Je te redonne le code modifié avec en prime une fonction distance qui calcule la distance entre deux coordonnées géographiques :

Code : Tout sélectionner

import csv
import geopy.distance as gd
"""with open('ligne_debut_fin.csv',newline='') as f :
    lire = csv.reader(f)
    liste = [ligne for ligne in lire if ligne[1]!='']
    liste_lignes = liste[1:]
    for ligne in liste_lignes :
        ligne[0] = int(ligne[0])
        for i in range(1,len(ligne)):
            ligne[i] = float(ligne[i])"""

with open('lignes-par-type.csv',newline='') as f :
    lire = csv.reader(f)
    liste = [ligne for ligne in lire]
    liste_lignes = liste[1:]
    lignes_debut_fin=[[int(ligne[0]),float(ligne[15]),float(ligne[16]),float(ligne[17]),float(ligne[18])] for ligne in liste_lignes if ligne[15] != '']

with open('liste-des-gares.csv',newline='') as h :
    extraction  = csv.reader(h)
    liste_brute = [ligne for ligne in extraction]
    liste_brute = liste_brute[1:]
    liste_gares = [[int(ligne[0]),int(ligne[4]),float(ligne[15]),float(ligne[16])] for ligne in liste_brute if ligne[3]=='O' and ligne[15] != '']

def distance(point1,point2):
    return gd.distance(point1, point2).kilometers
Il te reste à construire le dictionnaire de dictionnaires.
Bon courage
Invité

Re: Graphique

Message par Invité » ven. 3 janv. 2020 11:54

Bonjour,

Merci infiniment pour votre réponse.

Est-ce qu'avec ça je pourrai calculer la distance entre une gare A et une gare B ?

Mon problème est surtout : comment relier les lignes entre elles ? Par exemple, comment savoir que la ligne numéro 420000 est reliée à la 289000 (j'ai pris des numéros de ligne au hasard, ce n'est probablement pas relié en réalité) ? Et comment inscrire cette information dans le dictionnaire ?

En fait, comment savoir si des correspondances sont possibles à telle gare donnée ? En s'aidant des numéros de ligne qui sont dans les documents ?

Enfin, pourquoi un dictionnaire de dictionnaires ? On avait pas dit uniquement un dictionnaire ? Que contiendrait ce dictionnaire de dictionnaires ? Là je n'ai pas compris, j'en suis très désolé...

Merci beaucoup pour votre patience.
Invité

Re: Graphique

Message par Invité » ven. 3 janv. 2020 12:53

J'ai encore une question :

En Python, comment écrire un code donnant, pour une gare donnée, toutes les lignes qui passent par cette gare ? Sachant qu'on a les infos nécessaires avec votre fichier data.gouv.fr.

J'ai essayé d'écrire un tel code avec une boucle for, mais je n'ai pas réussi... Auriez-vous donc une idée de code ?

Encore merci.
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » ven. 3 janv. 2020 14:02

Bonjour,
pour une gare nommée A, il faut bien déterminer les gares qui appartiennent à la même ligne qu'elle et qu'on puisse accéder à la distance qui les sépare pour la gare A, on associera un dictionnaire qui contiendra en valeurs les gares de la même ligne et leur distance.
Par exemple {A:{A1:34,A2:16, A3:67}}, ce qui signifie qu'il y a 3 autres gares sur la même ligne que A et qui sont à une distance de A de 34 km pour A1, de 16 km pour A2, de 67 km pour A3.
Effectivement, tu peux aussi traiter cela avec un dictionnaire de listes
Normalement, en faisant comme cela, on traite aussi les connexions entre lignes, puisque dans le fichier liste-gares, une même gare apparaît autant de fois qu'elle appartient à des lignes différentes. Il s'agira alors d'actualiser la liste si la gare existe déjà dans le dictionnaire.
Par exemple, on a les liens pour la gare de Niort :

Code : Tout sélectionner

>>> dico_lignes()['Niort']
{'Chalonnes': (117.19758416383092, 523000), 'Chemillé': (103.39151332564929, 523000), 'Bressuire': (59.20587330879124, 523000), 'La Possonnière': (119.68321880090612, 523000), 'Cholet': (90.00158428518112, 523000), 'La Crèche': (13.042777144914695, 538000), 'Aigrefeuille-Le Thou': (45.8190171903175, 538000), 'Rouillé': (39.78596202503947, 538000), 'Surgères': (32.93808764501201, 538000), 'La Jarrie': (49.24085902853933, 538000), 'Mauzé': (21.471534444574203, 538000), "St-Maixent-l'Ecole": (21.801852719216942, 538000), 'Prin-Deyrançon': (17.88629747142722, 538000), 'Lusignan': (45.81770090248994, 538000), 'Pamproux': (32.285922225012406, 538000), 'La Mothe-St-Héray': (25.939120494897207, 538000)}
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » ven. 3 janv. 2020 14:12

Bonjour,
pour trouver les lignes auxquelles appartient une gare, il suffit de parcourir la liste des gares d'ajouter le numéro de ligne à une liste s'il n'y est pas déjà :

Code : Tout sélectionner

import csv
with open('liste-des-gares.csv',newline='',encoding='utf-8') as h :
    extraction  = csv.reader(h)
    liste_brute = [ligne for ligne in extraction]
    liste_brute = liste_brute[1:]
    lignes_par_gare = [[element[1],int(element[4])] for element in liste_brute if element[3]=='O' and element[15] != '']

def liste_lignes(gare):
    liste = []
    for element in lignes_par_gare :
        if element[0] == gare and element[1] not in liste :
            liste.append(element[1])
    return liste
Par exemple, pour la gare de Nantes, on a

Code : Tout sélectionner

>>> liste_lignes('Nantes')
[530000, 515000, 519000]
Invité

Re: Graphique

Message par Invité » ven. 3 janv. 2020 19:49

Merci beaucoup, là je commence vraiment à bien "rentrer" dans la logique du projet. Je pense que, grâce à votre aide, je devrais comprendre plus vite par la suite.

J'ai encore bossé dessus cet après-midi. Et je suis (encore une fois, désolé) tombé sur un problème que je vais vous décrire par un exemple. Prenons la gare de Dunkerque Port Ouest. Comment faire pour dire que la ligne sur laquelle elle est est reliée à la ligne qui contient la gare de Dunkerque ?

Car le numéro de la ligne qui contient la gare Dunkerque Port Ouest montre que c'est la seule gare sur cette ligne... Dans ce cas, comment la relier à la ligne qui contient la gare de Dunkerque (centre-ville) ? Quel serait le code Python à écrire ? On pourrait peut-être utiliser les coordonnées de départ et d'arrivée de la ligne qui a la gare Dunkerque Port Ouest disponibles dans le fichier liste-par-type ?

Je ne sais pas si j'ai été clair... J'espère que oui. Encore merci, je ne sais pas comment vous remercier tellement vous m'aidez.
sos-math(21)
Messages : 7625
Enregistré le : lun. 30 août 2010 11:15

Re: Graphique

Message par sos-math(21) » ven. 3 janv. 2020 21:52

Bonjour,
attention, il ne faut pas travailler avec les lignes de fret (c'est bien du transport de passagers qu'on veut faire ?)
Dunkerque port ouest est une gare de fret qui ne prend pas de voyageurs, c'est pour cela que dans la liste que j'ai créée, liste_gares, j'ai mis la condition if ligne[3] == 'O', c'est-à-dire oui dans la colonne voyageurs.
Ce qui donne le code (je te donne aussi le code pour la fonction graphes_lignes (dictionnaire de liste) et dico_lignes pour un dictionnaire de dictionnaires :

Code : Tout sélectionner

import csv
import geopy.distance as gd
with open('liste-des-gares.csv',newline='',encoding='utf-8') as h :
    extraction  = csv.reader(h)
    liste_brute = [ligne for ligne in extraction]
    liste_brute = liste_brute[1:]
    liste_gares = [[int(ligne[0]),ligne[1],int(ligne[4]),float(ligne[15]),float(ligne[16])] for ligne in liste_brute if ligne[3]=='O' and ligne[15] != '']

def distance(point1,point2):
    return gd.distance(point1, point2).kilometers

def graphe_lignes() :
    dico={}
    numero_lignes = lignes_debut_fin
    for gare in liste_gares :
        liste = []
        for element in liste_gares :
            if element[0] != gare[0] and element[2] == gare[2]:
                liste.append((element[1],distance((gare[3],gare[4]),(element[3],element[4])),element[2]))
        if gare[1] in dico.keys():
            dico[gare[1]] = dico[gare[1]] + liste
        else :
            dico[gare[1]] = liste
    return dico

def dico_lignes() :
    dico={}
    for gare in liste_gares :
        dico_noeud = {}
        for element in liste_gares :
            if element[0] != gare[0] and element[2] == gare[2]:
                dico_noeud[element[1]] = (distance((gare[3],gare[4]),(element[3],element[4])),element[2])
        if gare[1] in dico.keys():
            dico[gare[1]].update(dico_noeud)
        else :
            dico[gare[1]] = dico_noeud
    return dico 
Ainsi, si on veut les connexions liées à la gare de Dunkerque, on a :

Code : Tout sélectionner

>>> dico_lignes()['Dunkerque']
{'Lillers': (52.67065568069707, 301000), 'Mazingarbe': (67.41327489873221, 301000), 'Arras': (87.60721979706912, 301000), 'Farbus': (81.5189339100945, 301000), 'Arnèke': (22.24641891929466, 301000), 'Fouquereuil': (58.51116083041878, 301000), 'Vimy': (79.71236981811138, 301000), 'Cassel': (27.726351964301944, 301000), 'Steenbecque': (40.037026044300276, 301000), 'Coudekerque-Branche': (1.4408979997708593, 301000), 'Noeux-les-Mines': (64.47191455147392, 301000), 'Bailleul-Sir-Berthoult': (84.17089215297207, 301000), 'Bergues': (7.928546794387492, 301000), 'Liévin': (72.03501471454848, 301000), 'Bully-Grenay': (69.53333021262979, 301000), 'Chocques': (56.35241221791202, 301000), 'Ham-en-Artois': (49.38950680150897, 301000), 'Loos-en-Gohelle': (72.2535946089676, 301000), 'Isbergues': (46.581564586341045, 301000), 'Esquelbecq': (15.90365697499279, 301000), 'Lens': (74.39689188864531, 301000), 'Béthune': (59.695727840738456, 301000), 'Avion': (76.65418153905934, 301000), 'Thiennes': (42.603789246709, 301000)}
Bonne poursuite de projet
Répondre