[OSM-talk-fr] Carte des emprunts toxiques

yohanboniface at free.fr yohanboniface at free.fr
Sam 24 Sep 14:46:38 UTC 2011


> Là, je suis un peu speed, mais je peux essayer de faire une réponse un peu détaillée tant que c'est chaud ce week-end (si je vais pas faire du voilier...)

La bonne nouvelle, c'est qu'Eridan, à Brest, ne peut (veut?) plus louer de voilier pour le solo, et, tous mes acolytes marins étant indisponibles, me voici coincé à Paris pour le week-end, et donc je peux tâcher de donner quelques détails sur le "making-of" de la carte sur les emprunts toxiques. En particulier sur la géolocalisation, qui, comme l'a souligné Pieren, nous a causé quelques problèmes.

Je précise d'emblée combien je considère OSM comme un projet intéressant, à soutenir, à utiliser. Preuve en est que je bataille à Libé pour utiliser OSM chaque fois que possible. (Et c'est pas gagné d'avance...)
Et donc, s'il y a quelques critiques dans la suite de ce mail, c'est uniquement dans un but constructif. :)

Voici donc avec quelque détail comment nous avons procédé pour la géolocalisation automatiques des clients Dexia.

== Structure du fichier ==

Le fichier qu'on nous a donné à traiter en entrée était remarquablement bien structuré (merci Dexia, ).
Une colonne pour typer les clients (région, département, commune, communauté urbaine, etc.). Cette donnée se retrouve dans les "catégories de clients" de la carte, avec quelques regroupements (notamment dans "autres", mais pas seulement).

Ensuite, pour chaque ligne, concernant les données pouvant servir à la géolocalisation, les colonnes disponibles étaient :
- pays (systématiquement "FRANCE")
- région, en toutes lettres (ex.: "Picardie")
- code département (01, 02...)
- code postal
- ville (avec des valeurs brutes parfois un peu polluées, par exemple : "ST MEDARD EN JALLES CEDEX", "RENNES Cedex 9", "CHARLEVILLE MEZIERES CDX")
- adresse, avec à boire et à manger dans le champ, voici quelques exemples :
    
    - 15, RUE FRANCIADE                  C.S.3414
    - HOTEL DE VILLE                     PLACE CARNOT                       BP 20
    - MAIRIE
    - ODARC                              19 AVENUE NOEL FRANCHINI
    - LIEU DIT CASETTA
    - SERVICES FINANCIERS                27, AVENUE IMPERATRICE-EUGENIE
    - DIR DES AFF. ECO ET FINANCIERES    BD DU GOUVERNEUR FELIX EBOUE       BP 109
    - 8 Rue du Rh“ne
    - ECOPOLE                            ZI ET PORTUAIRE DE BOUROGNE
    - PPINIÔRES D'ENTREPRISES           LA MARE · JOUY
    - Mr XXX YYY /B 454 SPF/DEF    Bureau financement et tresorerie   3,Avenue Victoria
    - SOUS DIRECTION DE LA DETTE ET DU    CONTROLE EXTERNE                  HOTEL DU DEPARTEMENT
    - 159 RUE PDF FRANCOIS MITTERAND     BP 125
    - HOTEL DU DEPARTEMENT               2  16 BOULEVARD SOUFFLOT           MMe XXX YYY-DGA Finances
    - 93 AVENUE F ET I JOLIOT CURIE
    - 22 AVE DU 3EME MILENAIRE           BP26
    - 22 -24 VIADUC KENNEDY              CASE OFFICIELLE No36
    - Maison de la Communaut‚            sise 2 avenue du G‚n‚ral           De Gaulle
    - MAISON DE REPOS ET                 DE CONVALESCENCE
    - 27Bis AllŠes Jean-JaurŠs
    - etc.

== Obstacles rencontrés ==

Notre précédente (et unique) expérience de géolocalisation automatique remontait à la carte sur la loi SRU. Les données pour cette carte consistaient "simplement" en une liste de communes, et plutôt des communes importantes puisque concernées par la loi SRU.

Nous avions utilisé Nominatim pour la géolocalisation automatique, et les résultats étaient parfaits. Mais, j'insiste, les données étaient particulièrement homogènes et bien cartographiées dans OSM.

Ayant cette bonne expérience de Nominatim, nous sommes partis sur la même piste. Mais cette fois, la bataille fut autrement plus ardue.

Notre code comporte deux parties: une partie javascript front-end exploitant des geojson, et une partie backend en amont générant ces geojson une bonne fois pour toutes.

Pour la géolocalisation, comme principe général, nous avons généré une chaîne à chercher par ligne du fichier, en fonction de son type. Par exemple, pour une région, nous n'envoyions que le nom de la région. Pour une commune, seulement le contenu de la colonne "Ville". Pour les organismes tels que les communautés de communes, les syndicats mixtes, les offices HLM, nous envoyions une chaîne composée avec l'adresse (nettoyée de ce qui pouvait l'être automatiquement) et la ville.

Voici les paramètres envoyés à Nominatim:

        params = {
            'q' : querystring,
            'format' : 'json',
            'polygon': 1,
            'addressdetails': 1,
            'countrycodes': 'fr',
            'osm_type': osm_type,
        }

Quelques premières remarques:

- querystring correspond bien évidemment à la chaîne générée en python
- 'osm_type' était défini dynamiquement selon les types de clients (comme vous pouvez le voir sur la carte, il y a des points pour les communes, les communautés urbaines, etc. et des polygons pour les régions et les départements).
- le paramètre "polygon", permettant d'avoir les polygonpoints d'un point, était envoyé en permanence, une optimisation aurait été de ne l'envoyer que pour les régions et les départements
- countrycodes n'a pas toujours été utilisé
- on ne le voit pas ici, mais il est arrivé dans le cas de traitements manuels qu'un exclude_place_ids soit précisé

A la première itération globale du script, fantastique! nous avions des points par centaines et des polygones sur notre carte.

En y regardant d'un peu plus près, on a vu qu'il manquait des données et que certaines étaient erronées.

Je vais diviser les problèmes en trois catégories: ceux concernant les polygones (régions et départements), ceux concernant les communes, et ceux concernant les clients ayant une adresse précise.

Quelle que soit la catégorie, on verra que les problèmes ont trois sources générales: notre inexpérience de Nominatim et OSM d'une part, des infos erronées dans le fichier en entrée d'autre part, des "incohérences" dans les données d'OSM enfin.

* Régions et départements

Comme dit plus haut, à la première itération du script, plein de départements et régions sont apparus sur notre carte, ce qui était plutôt bon signe.
Mais très vite, on a remarqué qu'il en manquait.

Il y avait apparemment trois types de manques:

- soit Nominatim renvoyait un polygonpoints vide (exemple: Finistère)
- soit les données renvoyées étaient verrolées (tous les départements autour des Charentes étaient concernés, mais aussi le Calvados ; apparemment le node Bénauges mettait le bazar - à l'heure où j'écris, c'est toujours le cas sur la vue détail de MapQuest, par exemple: http://open.mapquestapi.com/nominatim/v1/details.php?place_id=79143957)
- soit Nominatim ne connaissait tout simplement pas (ex.: Côtes-d'Armor)

Nous avons donc dû chercher des sources alternatives, parmi lesquelles:

- un export d'OSM en shp fait par Freed (merci !), mais malheureusement incomplet (l'Aquitaine ou la Corse par exemple n'avaient pas le bon polygon)
- un script permettant de parser sauvagement les pages détails de MapQuest, par exemple: http://open.mapquestapi.com/nominatim/v1/details.php?place_id=79266078
- pour la Corse, l'Aquitaine et Poitou-Charentes, des shp glanés sur Internet

* Communes

Là encore, l'expérience de la carte SRU nous a joué un tour: dans un premier temps, nous n'avions envoyé QUE le nom de la ville à Nominatim.

Le premier piège dans lequel nous sommes tombés est que le paramètre countrycodes: "fr" empêchait la géolocalisation de tous les points situés en dehors de la France métropolitaine.

Nous l'avons donc provisoirement retiré, mais alors bonjour les faux-amis. Par exemple, recherchez "Nice 02" (02 étant un reliquat d'un nettoyage partiel de "CEDEX 02") dans Nominatim, et vous verrez du pays ;) Le bled en question, aux Etats-Unis, est un vrai attrape-mouches avec ses rues portant le nom de villes françaises.

Ensuite, les nombreuses homonymies nous ont piégés, et quelques maires de communes pointées à tort n'étaient pas contents, et à juste titre!

A force de jouer avec Nominatim, nous avions remarqué que le display_name avait presque systématiquement la structure suivante (plus ou moins détaillée selon l'item): numéro de rue, rue, ville, département, région, pays

Ainsi, pour essayer de cibler avec plus de précision, nous avons généré une chaîne équivalente pour les communes (mais sans l'adresse): ville, département, région, France. Résultat: 100% de réussite... sauf en Bretagne! "Paimpol, Côtes-d'Armor, Bretagne, France" ne donne aucun résultat, alors que "Paimpol, Bretagne, France" donne le bon. Idem pour "Douarnenez, Finistère, Bretagne, France", mais là "Douarnenez, Bretagne, France" ne donne rien non plus, il faut mettre seulement "Douarnenez, Finistère, France" pour avoir une réponse. C'était le cas aussi pour quelques communes isolées hors de Bretagne, "Saint-Lary-Soulan", par exemple, qui ne veut pas qu'on lui accole "Hautes-Pyrénées".

Autre problème: certaines avaient des noms d'usage non reconnus, par exemple: "LE TEIL D'ARDECHE", "LA MURE D'ISERE", "OUISTREHAM RIVA-BELLA".

Parfois, l'absence d'une apostrophe donnait des mauvais résultats, par exemple "COURNON D AUVERGNE".

Enfin, quelques communes étaient tout simplement inconnues de notre cher Nominatim, par exemple: "CONNANTRE", "LINGUIZZETTA", "REAUP-LISSE", "SAINT LANGIS LES MORTAGNE", "SAINT-PAUL-DE-JARRAT"...

Il est à noter que les codes postaux que nous avions dans le fichier ont généré plus de bruit en général qu'ils nous ont été utiles, et donc rapidement nous les avons ignorés pour la géolocalisation. En revanche, nous les avons affichés sur les popups des points, sur la carte, car cela nous aidait (et les internautes) à repérer les erreurs en la consultant.

* Points ayant une adresse précise

Il s'agit des syndicats mixtes, communautés de communes, communautés urbaines, organismes de logement, etc. C'est la catégorie qui nous a donné le plus de mal.

Comme on a pu le voir plus haut, la colonne "adresse" avait des valeurs très polluées.

La première étape fut donc de trouver le plus de règles possibles pour les nettoyer automatiquement.

Néanmoins, 460 lignes ont dû être traitées à la main. "Traitées à la main", cela consistait à nettoyer la chaîne envoyée à Nominatim avant un nouvel envoi. Parfois cela revenait à corriger une faute (ajouter un "R" à "MITTERAND" par exemple), parfois c'était beaucoup plus laborieux, et il fallait en passer par une recherche internet, des essais sur Nominatim, etc. Souvent, nous avons dû mettre des données approchantes: par exemple, la rue d'à côté quand une rue n'existait pas, ou parfois même le nom du village seulement quand aucune rue n'était disponible. Le plus gros écueil de ce contournement est que parfois deux points on pu être géolocalisés au même endroit, et sont donc affichés l'un sur l'autre, sans pour l'instant de possibilité de les différencier, dès lors qu'ils sont dans la même catégorie de clients (sinon, bien sûr, il suffit de décocher une catégorie pour avoir accès à l'autre).

Une fois toutes ces lignes traitées à la main, nous sommes tombés dans un autre piège. Pour une raison que je n'explique pas, même quand on précise lors de l'appel à Nominatim un osm_type, la réponse contient des items de tous les types.
Or, selon les catégories des clients, notre script cherchait un osm_type précis: une "relation" pour les régions et les départements, un "node" pour les autres.
Sauf que, et nous ne nous en sommes rendu compte que bien tard, quand on donne à Nominatim un nom de rue sans lui donner de numéro, la réponse est de type "way", et ce même si on précise "osm_type": "node" dans l'appel (j'ai aussi essayé avec la valeur "N", vu que je n'ai pas bien compris le point de la doc à ce sujet: http://open.mapquestapi.com/nominatim/ ; remarque: la page wiki, elle, laisse à penser que le paramètre ne serait utile que pour le reverse: http://wiki.openstreetmap.org/wiki/Nominatim).

Par conséquent, de nombreux points étaient ignorés par le script, qui attendait des "node", mais ne trouvait que des "way". N'ayant pas anticipé ce point, ces erreurs n'étaient pas mises au jour par le script. Et nous avons mis un peu de temps à nous en rendre compte.

La géolocalisation des adresses est, comme je disais, ce qui a coûté le plus de temps de contournement. Voici quelques exemples où l'on aurait pu attendre une réponse de Nominatim:

- "BOULEVARD DE LATTRE DE TASSIGNY TARBES", il faut ajouter "DU GENERAL" pour avoir une réponse => "BOULEVARD DU GENERAL DE LATTRE DE TASSIGNY TARBES"
- "42, CHEMIN POURPIER, SAINT-PAUL" => "42, CHEMIN DU GRAND POURPIER, SAINT-PAUL"
- "16 AVENUE GEORGE LEVY, VENISSIEUX" => "16, AVENUE DU DOCTEUR GEORGES LEVY, VENISSIEUX"
- "28/32 RUE DU XXE CORPS AMERICAIN METZ" => "28/32 AVENUE DU XXE CORPS AMERICAIN METZ"
- "rue du 12eme arrondissement MORTAIN" => "rue du XIIeme arrondissement MORTAIN"

Il y a aussi des erreurs parfois, par exemple "BOULEVARD SALVATOR ALLENDE", à SAINT-HERBAIN, au lieu de SalvaDor.

Ajoutons à ça, donc, un grand nombre de rue tout simplement pas encore cartographiées.


Malheureusement, on n'a pas noté systématiquement, lors de nos traitements manuels, pourquoi telle ou telle adresse avait posé problème. Et donc je ne cite ici que quelques exemples de mémoire. Je ne sais pas si ça peut aider, mais je dois pouvoir mettre à disposition les adresses en question, dans un fichier brut.


== Bilan ==

Rapidement:

- 5500 lignes à traiter, ça donne forcément un nombre de cas particuliers élevé...

- si c'était à refaire, je pense que je partirais plutôt sur la piste d'installer un PostgreSQL avec les données OSM de la France en local (avec ma propre indexation) plutôt que d'interroger Nominatim ; mais peut-être que j'aurais dit l'inverse si j'avais suivi cette option ;) Par ailleurs, maintenant que j'ai en local toutes les coordonnées des départements, des régions, et de milliers de ville, je ne partirai pas de zéro la prochaine fois...

- tout le monde a été très content du résultat à Libé, mais je dois dire que quand je vais voir le journaliste en lui disant: "ahem, il me reste 460 points à traiter à la main, on fait moit'-moit' ?" et qu'il me répond "Euh, mais Google, il les trouve, lui?", je sais que je perds quelques points ;)

- rien à voir avec la géolocalisation, mais clairement on a perdu pas mal de temps et de cheveux dans les méandres d'OpenLayers, dont la documentation et l'API sont certainement sponsorisés par les laboratoires Servier, ou au moins par un marchant d'aspirine. J'attendais que Leaflet gère le geojson pour envisager de l'utiliser, c'est maintenant chose faite, et je crois que je suis mûr pour faire l'expérience lors de notre prochaine carte ; voire pour Chimère, sur lequel nous avons commencé à travailler (https://gitorious.org/~yohanboniface/chimere/djangoize/commits/refactoring), pour l'instant surtout moi pour un projet perso (http://epicures.enix.org:8000/), mais comme souvent c'est en éclaireur d'une utilisation au boulot plus tard.


D'avance merci pour vos remarques !

Yohan, marin à terre




Plus d'informations sur la liste de diffusion Talk-fr