Archives de catégorie : Open Data

Base transparence – échec lors de la montée en charge

Dans l’article précédent, nous étions partis sur une extraction des données.
En effet, notre objectif était d’avoir une résultat rapide afin d’avoir des données affichages.  Nous sommes donc sur un cas d’école entre le cas utilisé par un développeur qui travail sur une extraction afin de valider ses travaux … qui échoue une fois les données de production utilisées.

En regardant le volume des données, rien de plus normal. Nous utilisons comme base de travail 3 fichiers de plusieurs gigas que nous combinons entre eux avant de faire les opérations. Autant dire que cela explose très rapidement.

En ré-ordonnant les opérations, et filtrant les données, tout rentre dans l’ordre.

Le code est le suivant :

 

self.loader.load_avantages(light)
data_avantages = self.loader.avantages[[‘entreprise_identifiant’, ‘avant_montant_ttc’]]

#calcul de la rémunération (avantage)
data = data_avantages.groupby([« entreprise_identifiant »])[« avant_montant_ttc »].sum().sort_values(ascending=False).head(nb_entreprise)

### jointure entreprise et avantage
self.loader.load_entreprises()
data_merge = merge(data, self.loader.entreprises, how= »left », left_on=[« entreprise_identifiant »], right_on= »identifiant »)
data_merge.to_excel(writer, sheet_name= »Avantage »)


A noter :

data = data_avantages.groupby([« entreprise_identifiant »])[« avant_montant_ttc »].sum().sort_values(ascending=False).head(nb_entreprise)

4 opérations dans cette ligne.

  • Le groupby permet de regrouper l’ensemble des avantages  par entreprise.
  • Le sum : permet de les cumuler
  • Le sort_values : permet de les trier dans l’ordre croissant
  • Le head permet de ne récupérer que les nb_entreprises les plus important.

Le github du projet a été mis à jour : https://github.com/SaugetMarc/transparence

 

 

 

 

 

 

Python Pandas Excel : un premier formatage

L’objectif de cet article est donc de montrer une chaîne complète de traitement de l’information, permettant à partir d’un ensemble de fichier résultat de type CSV, d’aller à un tableau formaté, pouvant être directement diffusé.

Le choix des données initiales

Pour avoir une base de travail, le plus simple est de partir sur des données issues de l’Open Data. Ces données sont facilement accessibles, fournies dans un résultat exploitable .. et sont souvent des mines d’information.

Mon choix c’est fait sur la base de données Transparence. Ces données sont directement accessible sur le portail suivant : transparence-santé.

La modélisation des données est la suivante :

    • Un fichier pour la description des entreprises
    • Un fichier pour la description des avantages
    • Un fichier pour la description des conventions.

La manipulation des données en Python

Nous allons faire simple, car dans ce cas précis, l’objectif est de voir comment charger les données, renseigner les jointures entre elles et produire quelques résultats.

Les données sont actuellement centrées sur l’entreprise. Notre  exemple sera de construire un graphique  contenant  les 50 entreprises les plus dépensières (convention + avantage).

Chargement et jointure des fichiers

Pour le chargement des fichiers, le plus simple est d’utiliser les méthodes mises à disposition par le frameworks Panda.  Mais avant tout chose, il est nécessaire de se faire un jeu de données possédant une taille utilisable pour les tests.

Le plus simple est de prendre une sous-sélection des fichiers de bases. Avec un environnement bash, la commande head permet de faire cela très rapidement.

head -n 50 avantage.csv > avantage_light.csv 

Une bonne habitude est d’utiliser dès que possible un fichier de configuration pour votre projet.  Les chaînes magiques ont malheureusement tendance à rester beaucoup trop longtemps dans les projets

DATA = {

'avantage' : 'data/avantage_light.csv',
'convention': 'data/convention_light.csv',
'entreprise': 'data/entreprise.csv',
'remuneration':'data/remuneration_light.csv'

}

Le chargement des fichiers se fait avec la commande suivante :

defloadcsv(self):
self.entreprises = read_csv(settings.DATA['entreprise'], header=0, delimiter=',', error_bad_lines=False)
self.avantages = read_csv(settings.DATA['avantage'], header=0, delimiter=';', error_bad_lines=False)
self.conventions = read_csv(settings.DATA['convention'], header=0, delimiter=';', error_bad_lines=False)
self.remunerations = read_csv(settings.DATA['remuneration'], header=0, delimiter=';', error_bad_lines=False)

Les travaux préparatoires sont maintenant terminés

Après une rapide analyse des fichiers, tous utilisent l’identifiant de l’entreprise comme données de jointure. Le seul point à prendre en compte porte sur le fait que suivant le fichier, l’identifiant n’a pas le même nom.  Il faut donc préciser le nom de la colonne pour pouvoir faire un rapprochement.

La jointure se fait donc à l’aide de la commande suivante :

data_merge = merge(self.loader.avantages, self.loader.entreprises, how="left", left_on=["entreprise_identifiant"], right_on="identifiant")
 
Puis, afin de regrouper les données par secteurs, il faut faire une opération de regroupement sur deux informations : le secteur et le nom de l’entreprise :
(La commande finale  head(50) permet de limiter l’extraction au 50 premières lignes, utile en cas de test)
 
data = data_merge.groupby(["secteur","entreprise_identifiant"])["avant_montant_ttc"].sum().head(50)
L’enregistrement basic dans un fichier excel se fait avec la commande suivante :
data.to_excel(writer, sheet_name="Avantage")
Simple, mais peu exploitable en production. En effet, le résultat obtenu n’est pas des plus présentable.
 

Construction du fichier excel formaté.

worksheet = writer.sheets["Avantage"]
format_size = 'C2:C'+str(data.shape[0]+1)
worksheet.conditional_format(format_size, {'type': '3_color_scale'})
worksheet.set_column('A:C', 20)

Avec ces 4 petites lignes, on a :

    • Déterminer la taille de la table
    • Changer le format de la dernière colonne (en gradiant)
    • Redimensionner la taille des 3 colonnes de notre table.

 

Pour aller plus loin, allez faire tour sur  Xlswriter.   L’ensemble des sources de ce petit projet sont ici

 

 

 

 

Un modèle de formulaire dynamique en Python / Django

Le concept : Un n-ième outil de création de formulaire

Le sujet n’est pas réellement innovant : il doit exister autant de site de formulaire dynamique que de développeur  … Pourtant, à chaque nouveau développement, il est rare de trouver l’outil, le module, qui va permettre de ne pas développer son modèle de formulaire. Il manque souvent, la fonctionnalité, ou le paramétrage qui va permettre d’avoir le paramétrage ou la personnalisation nécessaire.  Le principe de ce développement ne sera donc pas de faire le module de formulaire le plus complet possible … mais au contraire, de proposer un outil simple, robuste qui pourra être utilisé tel quel … ou étendu pour des besoins spécifiques.

L’innovation : Penser directement pour l’exploitation des résultats

En effet, un formulaire, quel qu’il soit n’est utile que si l’exploitation des résultats est possible.  L’objectif de ce développement sera donc de fournir l’ensemble des outils permettant la conception et l’utilisation d’un formulaire mais également, ceux qui permettent une exploitation ou un export des résultats.

Le mode de distribution

Sur ce point,  je vais essayer d’être le plus complet possible afin que tous puisse y trouver leur compte.  L’objectif sera donc de proposer :

  • Un service en ligne complet et autonome.
  • Une Api, permettant à des solutions de personnaliser complètement une partie de l’interface tout profitant d’un backend et de solution d’export existante.
  • Sous forme de brique logicielle autonome pouvant être déployant directement au sein d’une infrastructure
  • et pour ceux qui veulent aller plus loin dans la personnalisation, directement les sources de la solution (open ou closed source) en fonction de la cible du logiciel.

la stack technique

Pour le moment, rien n’est définitif … Mais le premier jet sera basé sur Python Django + un serveur MariaDB.  L’objectif de cette stack est de permettre d’obtenir un premier résultat rapide. De plus, ce choix permet de jolies évolutions. 

La cerise sur le gâteau est que Python est Le langage a suivre pour le moment. Ce choix est donc à la fois pour l’évolution du produit .. que pour mon évolution. 

Power Bi, Open Data et listing des pharmacies

Voici un petit article présentant comment il est possible d’obtenir un listing dans Power BI présentant une grande majorité des pharmacies.

La première étape est de récupérer un fichier contenant l’ensemble des établissements de santé.
Le choix se fait sur le fichier Fichier Finess:

Le choix est déterminé par la certification du fichier et sa fréquence de sa mise à jour.

Ce dossier du site Open Data contient en fait plusieurs documents distincts dont le détail est visible dans l’aperçu précédent.

Pour ce premier article, nous n’aurons besoin que du fichier contenant les extractions Finess des établissements ainsi que la géolocalisation de ces établissements. En supplément, il est possible de consulter le 1er fichier permettant d’obtenir un descriptif des différentes informations contenus dans le dossier.

Le traitement dans Power Bi sera minimaliste. La première étape consiste à importer les différents fichiers CSV. Après import des fichiers, il faut faire attention au typage automatique des colonnes. En effet, pour se faire, Power BI fait un échantillonnage sur les premières colonnes du fichier. Dans le cas des départements, cela pose problème car le type numérique du début de fichier n’est pas conservé sur son intégralité (2A / 2B pour la corse par exemple). Il est donc recommandé de conserver le type alphanumérique pour toutes valeurs qui n’est pas un nombre exploitable. Ceci se fait très facilement en appliquant changeant le type.

Pour le fichier structure, les étapes sont les suivantes :

  1. Source : import initial
  2. Promoted Headers : permet de sélectionner la première ligne comme entête de la table
  3. Changed Type : permet de passer du type numérique à alphanumérique
  4. Merged Queries : permet de faire une jointure entre le référentiel des types de voie et la table structure.

Un autre point à mentionner est que, dans le fichier fournit, le type de voie est donné sous la forme d’un référentiel qui n’est pas fourni. Pour le construire relativement rapidement, il suffit d’utiliser un tableur et de sélectionner l’ensemble des valeurs distincte de la colonne typvoie. Une fois la sélection obtenue, il est possible de créer son propre référentiel après avoir complété l’ensemble des libellés associés.

 

Nous obtenons donc 3 fichiers qu’il est possible le lier par la suite dans l’écran de modélisation.

Un dernier point de détail concerne le widget utilisé pour la localisation des établissements. Celui fonctionne à l’aide des adresses postales. L’inconvénient est quand le fichier fourni, l’adresse est éclaté dans plusieurs champs. Un moyen simple pour contourner ce problème est d’ajouter une colonne calculée à notre table, regroupant l’ensemble des champs devant être joint. On peut voir dans cette formule l’utilisation du référentiel sur le type de voie et l’ajout, en dur, du pays. Le fichier étant localisé par nature, il ne contient pas la notion de pays.

En conclusion, nous obtenons l’ensemble des établissements de santé, géolocalisées, dans des listes filtrables.