Archives de catégorie : Astuce

Deux Podcasts à Découvrir dans l’Univers de la Tech Française

La technologie est un domaine en constante évolution, et pour rester informé, j’ai pris l’habitude d’écouter des podcasts. Aujourd’hui, je souhaite partager avec vous deux d’entre eux qui m’ont particulièrement marqué.

Le Board: Pour les Solopreneurs et Plus Encore

Le Board est initialement conçu pour les solopreneurs, ces entrepreneurs qui travaillent seuls. Pourtant, j’ai trouvé que les sujets abordés touchaient un public bien plus large. Le podcast offre de nombreux conseils, en particulier sur la gestion du temps, qui peuvent s’avérer utiles pour tout professionnel.

Artisan Développeur: Un Regard sur le Développement de Qualité

Artisan Développeur est une source d’inspiration pour les développeurs qui cherchent à améliorer leurs compétences. Il traite des méthodes de développement, comme le TDD, mais aussi de comment instaurer ces bonnes pratiques au sein d’une équipe.

La Valeur des Invités

La variété des intervenants est un atout majeur de ces podcasts. Chaque épisode propose des perspectives différentes, offrant une vue d’ensemble enrichissante sur le monde de la tech freelance en France.

Pour Conclure

J’ai trouvé ces podcasts à la fois informatifs et accessibles. Que vous soyez dans le domaine de la tech ou simplement curieux, je vous recommande de leur donner une chance. Ils offrent des insights précieux dans un format agréable à écouter.

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

 

 

 

 

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.

C’est connu et reconnu mais avec la libéralisation des données, avoir un référentiel géographique prêt à l’emploi et actualisé est maintenant très rapide.

Le site de l’INSEE met les données dispositions l’ensemble de ces référentiels en libre accès sous forme de fichier dbf ou txt. Le travail d’actualisation des données est pré-mâché (puisqu’une liste de données d’actualisation est disponible).
Il n’y a donc plus aucune excuse à fournir un outil ne permettant pas de faire des statistiques fines sur le positionnement de ces utilisateurs.

Lien sur les référentiels : http://www.insee.fr/fr/methodes/nomenclatures/cog/telechargement.asp

Bonne intégration

Oracle : Update or Insert = MERGE

J’ai du répondre à une question simple de prime abord, comment mettre un jour un référentiel, non prévu pour être versionné, et ayant pu évoluer de manière différente sur chacun des différents sites de manière indépendante.

Après quelques recherches, le principal mot clé qui pouvait revenir était : MERGE

Un merge pour un développeur, c’est quelque chose de connu et ce n’est pas souvent envisager comme quelque chose de simple et de généralisable.
En théorie si, mais en pratique, c’est souvent durant cette étape que la livraison de son code prend un retard inattendu.

Alors avant d’envisager une telle pratique quand on utilise traditionnellement le SQL pour faire de simple CRUD … on cherche du simple … on envisage de se mettre au PL …. voir de faire une mini application faisant ce que l’on veut.

Et pourtant, le merge cela peut aussi être simple dans certain cas et cela peut rapidement être mis en place.

Comme dit en introduction, mon contexte était le suivant :
– Mise à jour de référentiel
– Pas d’assurance sur l’état du référentiel avant travaux
– Pas nécessairement le temps de s’assurer de la cohérence des données pour chacun des sites.

A priori, il existe plusieurs techniques, plus ou moins simple pouvant arriver à ce résultat.
Dans mon cas, il fallait que le génération du script se fasse dans un temps relativement court … et en ne demandant pas de devenir DBA au passage.

Le processus choisit pour l’actualisation de la table fut le suivant :

– Mise en place d’une date de fin pour l’ensemble des champs du référentiel utilisé en production (assurance de conserver les champs pour les données déjà saisies).
– Injection de la nouvelle table de référentiel
– merge proprement dit entre l’ancienne table et la nouvelle afin d’actualiser les champs utiles, quelques soit l’état de la table initialement.

En SQL, cela donne cela :


-- Généralisation de la date de fin à l'ensemble des occurrences de la table
update SOC_TYPE_DOMICILE set datefin= '01/11/14';

-- Injection de la table référentiel nouvelle version
CREATE TABLE "SOC_TYPE_DOMICILE_REF"
( "CODE" VARCHAR2(10 BYTE),
"CODEREGROUPEMENT" VARCHAR2(10 BYTE),
"DATEDEBUT" DATE,
"DATEFIN" DATE,
"LIBELLE" VARCHAR2(100 BYTE),
"RANGAFFICHAGE" NUMBER(3,0),
"ANCIENCODECSD" VARCHAR2(10 BYTE),
"CODEREGROUPEMENTTYPE" VARCHAR2(10 BYTE),
"ID_LIBELLE" NUMBER(7,0)
);

Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('SIFO','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Sans information','1','0',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('HEBST','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Hébergement stable','2','2',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('HEBPR','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Hébergement précaire ou de durée incertaine','3','A',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('HOP','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Hôpital sans perspective de logement à la sortie','4','B',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('SAB','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Sans abri, absence totale d hébergement','5','1',null,null);

-- Merge
-- deux cas : la ligne existe : dans ce cas on modifie le libellé pour qu'il corresponde exactement avec le résultat attendu (les valeurs, même modifiées, ne changent pas de sens)
-- La ligne n'existe pas, on l'insère
MERGE INTO SOC_TYPE_DOMICILE S
USING SOC_TYPE_DOMICILE_REF R
ON ( S.CODE = R.CODE )
WHEN matched
THEN UPDATE SET S.DATEFIN = null, S.LIBELLE = R.LIBELLE, S.RANGAFFICHAGE = R.RANGAFFICHAGE, S.ANCIENCODECSD = R.ANCIENCODECSD
WHEN not MATCHED
THEN INSERT (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE)
VALUES (R.CODE,R.CODEREGROUPEMENT,R.DATEDEBUT,R.DATEFIN,R.LIBELLE,R.RANGAFFICHAGE,R.ANCIENCODECSD,R.CODEREGROUPEMENTTYPE,R.ID_LIBELLE);

-- et c'est fini ...

Duplication de clé USB

des fois on se fait plaisir avec peu de ligne de commande ..

Duplication de la clé
dd if=/dev/sdc of=/dev/sdd bs=4096 conv=notrunc,noerror

Hors avec des clés de tailles différentes, on obtient :

fsck /dev/sde1
fsck from util-linux 2.20.1
e2fsck 1.42.8 (20-Jun-2013)
La taille du système de fichiers (selon le superbloc) est de 7793408 blocs
La taille physique du périphérique est de 7674624 blocs
Le superbloc ou la table des partitions est peut-être corrompue !

Un simple : resize2fs -f /dev/sde1 7674624

et tout est de nouveau opérationnel :

fsck /dev/sde1
fsck from util-linux 2.20.1
e2fsck 1.42.8 (20-Jun-2013)
/dev/sde1 : propre, 25468/1925120 fichiers, 303289/7674624 blocs

Je vais de nouveau mettre ma sd card classique dans le Eeepc et la microSD dans une nouvelle go-pro ^^

Toujours lire les warnings … ils peuvent être plus génants que des erreurs …

3 sessions de travail, 3 sessions à me battre avec Eclipse, Hibernate et Tomcat pour comprendre pourquoi aucune de mes configurations ne marchait.

3 Sessions à tricher, à rechercher où coller mes fichiers de configuration pour qu’ils soient pris en compte …

3 sessions à avancer pas à pas, sans comprendre pourquoi tout ne marchait pas comme prévu, à ne pas comprendre le pourquoi des problèmes …

Jusqu’à ce moment où j’ai pensé à lire les warnings, tous les warnings …
———————————————-
Description Resource Path Location TypeClasspath entry WebContent/WEB-INF/classes will not be exported or published. Runtime ClassNotFoundExceptions may result.
———————————————-

Et voilà, j’avais oublié de cocher une case pour la construction de mon ClassPath, et le répertoire local de mon application n’était pas pris en compte … et donc Hibernate ne retrouvait pas ses fichiers … La case cochée, tout est rentré dans l’ordre …

Un warning qu’il faudrait peut être passer en erreur …

Astuces systèmes

1 Manipulation de fichier.

Travaillant actuellement sous plusieurs système, je me suis retrouvé à avoir des fichiers mal encodés … résultat, dans un même projet, j’avais des fichiers en ISO-XxX et d’autre en UTF-8. Donc pour homogénéiser le tout, le plus simple est d’utiliser la commande Linux suivante :

file nom_du_fichier > Permet de connaître l’encodage utilisé

iconv -f type_initial -t type_voulu nomFichier > nouveauFichier

Et le problème est résolu.

[ad#Google Adsense]

Astuce de prog

Cet article/section n’est pas un. Il va simplement me permettre de lister une petite série d’astuces ou de techniques qui peuvent être utiles … et que l’on met souvent un temps fou à retrouver.

Astuce 1 : Spécifier le nombre de digits d’un nombre (Très utile quand le lecteur associé aux programmes demande un format strict)

Utilisation de la STL

std::ostringstream oss;
oss <<std::setw(3)<<std::setfill('0')<<rg;

la fonction fill va permettre de présenter le nombre rg avec obligatoirement 3 digits (120 -> 120 mais 1 -> 001)

[ad#Google Adsense]

Astuce 2 : Faire un tri rapide sur une liste.

Si vous avez besoin de QT dans votre développement, et que à certains moment, vous devez faire appel à des techniques de tri … Le plus simple est de laisser à l’environnement QT faire le tri à votre place.

Pour ce faire, il suffit d’utiliser des QList et, son tri se limitera à l’appel à la fonction suivante :

qSort(listeMat.begin(), listeMat.end(), qGreater<int>());

Dans ce context, listeMat correspond à une liste d’entier, mais si vous travaillez sur des listes d’objets, il suffit de ré-implementer les méthodes qGreater pour votre objet.