S41 - Projet 2013/2014 - 1 - Extraction et transformation des données
Les données sont produites par la station météo sous la forme d’une séquence de caractère (pour commencer nous le simulerons avec un fichier texte) dont la forme est la suivante :
20.9degC RHT03 : H=55% T=19.5degC BMP085 : P=998hPa T=21degC LDR : 23.0% Anemometre : 0.0m/s Girouette : 90degres Pluviometre : 0mm [HRTCC : 21/01/2014 09:25:37 Solaire : Vpan=0.00V Batterie : Vbat=0.00V Ibat=0.00A Duty cycle : R=50% DS18S20 : 20.9degC RHT03 : H=55% T=19.5degC BMP085 : P=998hPa T=21degC LDR : 23.0% Anemometre : 0.3m/s Girouette : 90degres Pluviometre : 0mm [HRTCC : 21/01/2014 09:25:39 Solaire : Vpan=0.00V Batterie : Vbat=0.00V Ibat=0.00A Duty cycle : R=50% DS18S20 : 20.9degC RHT03 : H=55% T=20.5degC BMP085 : P=998hPa T=22degC LDR : 23.0% Anemometre : 0.5m/s Girouette : 45degres Pluviometre : 0mm
Le fichier data.txt contient une capture d’envoie d’un station météo.
On remarque que :
- la station envoie régulièrement le même bloc d’information (la date en premier et le pluviomètre en dernier). En réalité chaque bloc d’information commence toujours par deux caractères : le caractère d’échappement (code ASCII 27, invisible sur un écran) et le caractère '['. Cela permet de trouver le début du prochain bloc.
- Il y a un ensemble d’information fournie par un capteur par ligne, elle commence par une étiquette (Solaire, Batterie, …) suivie de ':'
- Après le ':' se trouvent des informations qui sont :
- soit une date (21/01/2014) puis une heure (09:25:39)
- soit des listes de couples nom=valeur (H=55% T=19.5degC) séparées par des espaces et des tabulations
- soit simplement une valeur (23.0%).
- Toutes les valeurs (55%) sont composées d’une nombre (55) et d’une unité (%)
Dans le bloc précédent, il y a donc deux mesures utilisables (la première est incomplète).
Structure de données
Après extraction, toutes les informations seront stockées dans une liste dont chaque élément est un dictionnaire (un par groupe de mesures à un moment donné). L’entrée du dictionnaire est indexé par l’étiquette de la ligne. A l’intérieur, chaque mesure est représentée par un tableau à deux éléments (valeur et unité). Dans le cas où plusieurs mesures existent pour un label, elles sont stockées dans un dictionnaire.
Les dates est stockée dans datetime (http://docs.python.org/2/library/datetime.html#datetime-objects). Pour les utiliser il faut importer la class datetime du module datetime :
Voilà un exemple d’affectation de deux mesures construites ‘à la main’:
data=[{'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'], 'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [21.0, 'degC']}, 'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 37), 'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'], 'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [22.0, 'degC']}, 'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 39), 'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'], 'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [23.0, 'degC']}, 'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 41), 'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'], 'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [21.0, 'degC']}, 'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 43), 'Solaire': {'Vpan': [0.0, 'V']}}]
Le fichier data.py contient la déclaration python des mesures précédentes.
En haut de chaque module qui doit utiliser datetime
ajouter :
from datetime import datetime
L’intérêt est ensuite de pouvoir accéder simplement aux valeurs :
print("Nombre de mesures:", len(data)) print('Les deux premieres mesures ', data[:3]) print('La pression donnee par le capteur BMP085 de la 5eme mesure ', data[4]['BMP085']['P'])
Créer un projet python pymeteo
. Créer un module main.py
. Déclarer une variable data
qui contient quelques mesures. Tester les expressions précédentes. Afficher la valeur R
sans l’unité de l’étiquette Duty cycle
de la seconde mesure.
Extraction du label d'une ligne
Lire la section chaîne de caractères de la page Traitement simple des chaînes de caractère en python avant de faire cet exercice.
Créer un module parser.py
et la fonction def extract_label(ligne)
.
Cette fonction retourne l’étiquette de la ligne passée en paramètre comme une chaîne de caractères.
Ajouter dans le module main.py
le test de la fonction précédente :
print(parser.extract_label("HRTCC : 21/1/14 9:25:37"))
Il doit retourner HRTCC
.
Extraction de la date et de l'heure
Lire la section expression régulière de la page Traitement simple des chaînes de caractère en python avant de faire cet exercice et les suivants.
Ajouter la fonction extract_datetime(data)
au module parser
. Elle doit retourner un datetime à partir d’une chaîne de caractère qui contient une date et une heure (comme dans les données de HRTCC). Pour créer un datetime, vous utiliserez la fonction datetime(int(annee), int(mois), int(jour), int(heure), int(minute), int(seconde))
.
Vous tester votre fonction dans le module main.py
:
print(parser.extract_datetime("21/1/2014 9:25:37")) print(parser.extract_datetime("21/01/14 9:25:37"))
qui doit retourner
2014-01-21 09:25:37 2014-01-21 09:25:37
Séparation des valeurs et des unités
Dans le module parser
ajouter la fonction extract_unit(data)
qui prend en paramètre une chaîne de caractères qui contient un nombre et une unité et qui retourne un tableau avec deux éléments (la valeur et l’unité).
Vous testerez votre fonction :
print(parser.extract_unit("23deg")) print(parser.extract_unit("+23°")) print(parser.extract_unit("-23P")) print(parser.extract_unit("23.4%")) print(parser.extract_unit("+23.4E-3%"))
ce qui doit retourner :
[23.0, 'deg'] [23.0, '°'] [-23.0, 'P'] [23.4, '%'] [0.0234, '%']
Extraction des séquences de couple attribut/valeur
Dans le module parser
ajouter la fonction attribute_value(data)
qui prend en paramètre une chaîne de caractères contenant des couple de la forme NOM=MESURE et retourne un dictionnaire indexé par les noms et contenant un tableau séparant la valeur et l’unité.
Vous testerez votre fonction :
print(parser.attribute_value("H=55% T=19.5degC")) print(parser.attribute_value("R=50%"))
ce qui doit retourner :
{'H': [55.0, '%'], 'T': [19.5, 'degC']} {'R': [50.0, '%']}
Analyse complète des données
Ecrire la fonction parse(filename)
qui retourne le tableau complet des données en utilisant les fonctions précédentes et en analysant le fichier dont le nom est passé en paramètre.
La démarche suivante est conseillée :
- chercher une ligne qui commence une nouvelle mesure, c’est à dire qui débute par les caractères escape (dont le code ASCII est 27) et “[”. La fonction
ord(ch[i])
retourne le code ASCII du ième caractère de la chaîne ch), la fonctionchr(i)
retourne le caractère dont le code ascii est passé en paramètre. - pour chaque ligne extraire l’étiquette et exécuter la bonne fonction pour extraire les données, l’ajouter à un dictionnaire temporaire qui sera ajouté à un tableau à chaque fois que l’on trouve le début d’un nouveau groupe de mesure (le caractère escape).
Exploitation des résultats
Ecrire les fonctions qui permettent de créer simplement des tableaux de valeurs à partir des clés
extractMesures(data, key, subkey) extractMesures(data, key) extractValues(data, key, subkey) extractValues(data, key)
print('Le tableau des 3 premières temperatures données par BMP085', parser.extractMesures(data,'BMP085', 'T')[:3]) print('Le tableau des 3 premières temperatures données par BMP085 (sans unité)', parser.extractValues(data,'BMP085', 'T')[:3])
Un défi (optionnel) Création d'un tableur à partir des données
En vous inspirant de Lien avec OpenOffice, ecrire un module libreoffice.py
qui permet d’exporter toutes les mesures dans différents onglets d’un tableur.
—- dataentry page —- type : TP enseignement_tags : S41 technologie_tags : Python,UNO