Session de ~2h avec pour objectifs:
5 février 2015, 14h-16h30, animé par Pierre Haessig
* mise en abîme: la session a lieu dans la salle où est installée ce capteur...
La distribution Ananconda, de Continuum Analytics, contient tous les paquets nécessaires pour une utilisation scientifique classique.
lien direct de téléchargement (300 Mo, gratuit)
→ choisir la version adaptée au système d'exploitation (e.g. 32 vs. 64 bits)
Sous Windows, dans le Menu Démarrer, lancer "Anaconda/IPython Notebook".
→ Ouvre une fenêtre de commande (le serveur) et une fenêtre de navigateur: l'interface du Notebook avec laquelle on va interagir
Cellule de type "Code":
a = 1
a+2
3
Cellule de type "Markdown":
Aide sur la syntaxe: "Markdown basics"
Importer des modules (avec un alias court, plus pratique)
import numpy as np
import matplotlib.pyplot as plt
Importer juste un élément:
from numpy import pi
pi
3.141592653589793
Activer l'affichage des graphiques dans le Notebook (image statique)
%matplotlib inline
Activer l'affichage dans une fenêtre séparé (interactif)
%matplotlib qt
Vecteur de données à tracer
t = np.linspace(0, 4*pi)
y = np.sin(t)
Syntaxe de graphs avec Matplotlib: très proche de Matlab (volontairement)
Galerie d'exemples, très pratique pour découvrir: http://matplotlib.org/gallery.html
plt.plot(t, y) # affiche y=f(t)
plt.title('sinus')
plt.xlabel('temps (s)')
plt.grid(True)
import pandas as pd
La "magic" %ls
permet de lister le contenu d'un répertoire (comme ls
sour Linux, dir
sous Windows)
%ls *.csv
log-20150128-092830.csv
Nom du fichier à lire (qui est ici dans le répertoire courant où le Notebook a été exécuté).
%pwd
u'/home/pierre'
fname = 'log-20150128-092830.csv'
Affichage du contenu du fichier:
head
et tail
sous Linux (appel au shell avec le signe !
)%more
!tail $fname
# affiche *tout* le fichier dans le pager
%more $fname
la fonction qui fait le travail: read_csv
.
# Afficher l'aide (syntaxe spécifique à la console IPython)
pd.read_csv?
Appel simple, en précisant juste le séparateur des champs:
d = pd.read_csv(fname, sep=';')
d.head()
date | time | type | value | unit | |
---|---|---|---|---|---|
0 | 28/01/2015 | 09:28:45.871 | indoor relative humidity | 36.00 | % |
1 | 28/01/2015 | 09:29:44.274 | indoor relative humidity | 36.00 | % |
2 | 28/01/2015 | 09:30:46.377 | indoor relative humidity | 37.00 | % |
3 | 28/01/2015 | 09:30:50.697 | indoor temperature | 21.20 | �C |
4 | 28/01/2015 | 09:30:55.908 | volatile organic compounds | 0.06 | ppm |
→ Lecture sans erreur, mais les dates ne sont pas analysées (elles restent sous forme de chaînes de caractères)
d['date'][0]
'28/01/2015'
type(d['date'][0])
str
Appel de read_csv
avec des options adaptées à ce fichier:
d = pd.read_csv(fname, sep=';',
parse_dates=[[0,1]], # aller chercher la date dans les 2 première colonnes
index_col=0, # utiliser la date comme index des données
dayfirst=True, # ne pas confondre le 5 février avec le 2 mai (format américain MM-DD-YYYY)
)
d.head()
type | value | unit | |
---|---|---|---|
date_time | |||
2015-01-28 09:28:45.871000 | indoor relative humidity | 36.00 | % |
2015-01-28 09:29:44.274000 | indoor relative humidity | 36.00 | % |
2015-01-28 09:30:46.377000 | indoor relative humidity | 37.00 | % |
2015-01-28 09:30:50.697000 | indoor temperature | 21.20 | �C |
2015-01-28 09:30:55.908000 | volatile organic compounds | 0.06 | ppm |
les donnés sont dans un pandas.DataFrame
type(d)
pandas.core.frame.DataFrame
On récupère une colonne par indexation. Objet de type Series
vals = d['value']
vals.head()
date_time 2015-01-28 09:28:45.871000 36.00 2015-01-28 09:29:44.274000 36.00 2015-01-28 09:30:46.377000 37.00 2015-01-28 09:30:50.697000 21.20 2015-01-28 09:30:55.908000 0.06 Name: value, dtype: float64
type(vals)
pandas.core.series.Series
Tout les type de mesures issues du capteur
type_meas = d['type']
type_meas.unique()
array(['indoor relative humidity', 'indoor temperature', 'volatile organic compounds', 'carbon dioxide'], dtype=object)
Récupérer seulement un type de mesures: la température
temp = vals[d['type'] == 'indoor temperature']
temp.head(3)
date_time 2015-01-28 09:30:50.697000 21.2 2015-01-28 09:33:49.494000 21.4 2015-01-28 09:36:51.682000 21.2 Name: value, dtype: float64
Exo: faire la même chose pour le CO2
co2 = vals[d['type'] == 'carbon dioxide']
co2.head(3)
date_time 2015-01-28 09:31:01.408000 390 2015-01-28 09:33:59.015000 390 2015-01-28 09:37:01.512000 390 Name: value, dtype: float64
groupby
¶Par type de mesure
d.groupby('type').mean()
value | |
---|---|
type | |
carbon dioxide | 441.214809 |
indoor relative humidity | 29.069816 |
indoor temperature | 20.549659 |
volatile organic compounds | 0.059591 |
Statistiques par jour
temp.groupby(temp.index.dayofyear).mean()
28 21.091349 29 21.766250 30 21.304792 31 19.128750 32 18.576458 33 20.560417 34 21.048125 35 20.702917 36 21.225649 Name: value, dtype: float64
Sous échantillonage: moyennes journalières
temp.resample('1D')
date_time 2015-01-28 21.091349 2015-01-29 21.766250 2015-01-30 21.304792 2015-01-31 19.128750 2015-02-01 18.576458 2015-02-02 20.560417 2015-02-03 21.048125 2015-02-04 20.702917 2015-02-05 21.225649 Freq: D, Name: value, dtype: float64
Sur échantillonage: il faut combler les trous
temp.resample('1Min').head()
date_time 2015-01-28 09:30:00 21.2 2015-01-28 09:31:00 NaN 2015-01-28 09:32:00 NaN 2015-01-28 09:33:00 21.4 2015-01-28 09:34:00 NaN Freq: T, Name: value, dtype: float64
temp.resample('1Min', fill_method='bfill').head()
date_time 2015-01-28 09:30:00 21.2 2015-01-28 09:31:00 21.4 2015-01-28 09:32:00 21.4 2015-01-28 09:33:00 21.4 2015-01-28 09:34:00 21.2 Freq: T, Name: value, dtype: float64
temp.resample('1Min').interpolate().head()
date_time 2015-01-28 09:30:00 21.200000 2015-01-28 09:31:00 21.266667 2015-01-28 09:32:00 21.333333 2015-01-28 09:33:00 21.400000 2015-01-28 09:34:00 21.333333 Freq: T, Name: value, dtype: float64
%matplotlib inline
temp.plot()
plt.ylabel(u'température (°C)') # u'' pour des textes accentués
<matplotlib.text.Text at 0x7f208c9ec410>
Deux tracés sur le même axe: twinx
(pb de grille non superposée)
temp.plot()
plt.twinx()
co2.plot(style='r');
La température et le CO2, superposés: subplots
fig, (ax1, ax2) = plt.subplots(2,1, sharex=True)
temp.plot(ax=ax1)
co2.plot(ax=ax2, style='r')
plt.xlim('2015-02-03','2015-02-04')
ax2.set_ylim(200, 1200);
Remarque: grâce au paramètre sharex
, le zoom est synchronisé (utile en mode interactif, avec %matplotlib qt
).