Initiation à Pandas
Pandas http://pandas.pydata.org/ est une bibliothèque Python pour manipuler simplement et efficacement des données structurées.
Pandas possède essentiellement 3 structures de données
- Series
- DataFrame
- Panel
Les principales possibilités sont :
- récupérer des données depuis des fichiers CSV, tableaux Excel, des pages web, HDF5, etc. http://pandas.pydata.org/pandas-docs/dev/io.html ;
- grouper, découper, alléger, déplacer, écrire les données ;
- manipuler ces données (qui peuvent être à une ou deux dimensions), avec des manques, ou encore de façon temporelle avec ou sans périodicité.
Si les données sont correctement formatées, pandas peut s'en sortir même dans le cas où la quantité dépasse les capacités de votre machine en traitant les sources morceaux par morceaux (chunk by chunk http://pandas.pydata.org/pandas-docs/dev/io.html#iterating-through-files-chunk-by-chunk).
Comparaison avec R
pandas se base sur les bonnes idées de R et s'attache à apporter les fonctionnalités manquantes. Pandas profite de l'engouement autour des outils scientifiques en Python.
L'aspect généraliste de Python permet également de développer l'intégralité d'une application avec un seul langage ce qui n'est pas le cas de R.
Reste la licence de R (GPL) qui peut sembler un obstacle pour certaines finalités, Pandas étant sous licence BSD.
Ressources
Bien que la documentation soit étoffée, pour ceux qui souhaitent être accompagnés sur des cas concrets, il existe un livre de recettes (Pandas cookbook) https://github.com/jvns/pandas-cookbook ou bien un guide en 10 minutes http://pandas.pydata.org/pandas-docs/dev/10min.html.
Voici également une page la page officielle de la documentation qui rassemble un certain nombre de tutoriels : http://pandas.pydata.org/pandas-docs/stable/tutorials.html
Séries, DataFrame et Panel
Séries
Création
>>> import pandas as pd
>>> import numpy as np
>>> s = pd.Series(np.random.randn(5))
>>> s
0 -0.203811
1 -0.551419
2 1.687802
3 0.182499
4 1.189289
dtype: float64
Propriétés
Une série est composée d'un index et des valeurs
>>> s.index
Int64Index([0, 1, 2, 3, 4], dtype='int64')
>>> s.values
array([-0.20381096, -0.55141904, 1.68780186, 0.18249923, 1.18928948])
La série est donc une forme de sur-couche au array de Numpy.
Le type des valeurs peut être déterminé à l'aide de :
>>> s.dtype
dtype('float64')
Le type d'une série est pandas.core.series.Series
>>> type(s)
pandas.core.series.Series
L'index peut être défini au moment de la création.
>>> pd.Series(np.random.randn(3), index=['row1', 'row2', 'row3'])
row1 -1.201536
row2 0.712213
row3 -1.528360
dtype: float64
Par défaut, le nom de la série est une chaîne vide mais il est possible de le modifier :
>>> s.name = "Temperature"
>>> s
A 100
B 200
C 300
Name: Temperature, dtype: int64
Autre technique de création d'une série
Une série peut-être construite à partir d'un dictionnaire :
>>> d = {'A': 100, 'B': 200, 'C': 250}
>>> s = pd.Series(d)
Affichage
On peut afficher une série en tapant
>>> s
A 100
B 200
C 250
dtype: int64
ou à l'aide de print(s)
Création d'une série temporelle
Exemple de création d'une série temporelle avec 100 valeurs aléatoires (une valeur par jour depuis le 1er septembre 2015)
>>> N = 100
>>> s = pd.Series(np.random.random(N), index=pd.date_range('2015-09-01', periods=N, freq='1D'))
2015-09-01 0.162645
2015-09-02 0.451501
2015-09-03 0.923967
2015-09-04 0.815285
2015-09-05 0.097870
...
2015-12-05 0.508401
2015-12-06 0.618696
2015-12-07 0.913769
2015-12-08 0.267932
2015-12-09 0.836149
Freq: D, dtype: float64
Limitation de l'affichage
On peut limiter l'affichage de la série à l'aide de :
>>> pd.set_option('max_rows', 6)
>>> s
2015-09-01 0.162645
2015-09-02 0.451501
2015-09-03 0.923967
...
2015-12-07 0.913769
2015-12-08 0.267932
2015-12-09 0.836149
Freq: D, dtype: float64
Indexing
Elle peut s'utiliser de manière similaire.
>>> s['B']
250
ou
>>> s.loc['B']
250
mais propose d'autre méthode d'indexing comme
L'indexing par numéro entier (i
= integer) de ligne (1ère ligne = indice 0)
>>> s.iloc[0]
100
Slicing
Le slicing (tranche) est également possible.
Tant avec des entiers,
>>> s.iloc[1:3]
B 200
C 250
dtype: int64
qu'avec des chaînes de caractères :
>>> s.loc['B':'C']
B 200
C 250
dtype: int64
Les 2 premières valeurs peuvent s'obtenir via :
>>> s[:2]
A 100
B 200
Name: Temperature, dtype: int64
Les 2 dernières via :
>>> s[-2:]
B 200
C 250
Tracé
Pandas permet d'avoir accès à des fonctions de tracés (utilisant Matplotlib).
s.plot()
plt.show() # pas nécessaire dans un notebook IPython
Cela permet de tracé les valeurs de la série s en fonction des index.
On peut également tracer un histogramme à l'aide de :
s.plot(kind='bar')
On peut également tracer un scatter plot à l'aide de :
s.plot(kind='scatter')
Remarque : la plupart des méthodes graphiques de Pandas permettent de passer un AxesSubplot
afin de faire plusieurs tracés sur une même figure.
s.plot(ax=ax1)
DataFrame
Les DataFrame sont des structures de données à 2 dimensions avec des colonnes qui peuvent être de différent type. C'est une sorte de tableau.
Il est possible de créeer un DataFrame à partir des structures de données suivantes :
- arrays NumPy
- listes
- dictionnaires
- series
- array NumPy de dimension 2
Création
Création à partir d'un dictionnaire de Series
>>> d = {'c0': pd.Series(['A', 'B', 'C']),
'c1': pd.Series([1, 2., 3., 4.])}
>>> df = pd.DataFrame(d)
>>> df
c0 c1
0 A 1
1 B 2
2 C 3
3 NaN 4
Création à partir d'un dictionnaire de listes
>>> d = {
... 'c0': ['A', 'B', 'C', 'D'],
... 'c1': [1, 2., 3., 4.]
... }
>>> df = pd.DataFrame(d)
c0 c1
0 A 1
1 B 2
2 C 3
3 D 4
Quelques informations à propos d'un DataFrame
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4 entries, 0 to 3
Data columns (total 2 columns):
c0 4 non-null object
c1 4 non-null float64
dtypes: float64(1), object(1)
memory usage: 144.0+ bytes
Propriétés
Comme une série un DataFrame possède un index :
>>> df.index
Int64Index([0, 1, 2, 3], dtype='int64')
mais contrairement à une série il a plusieurs colonnes :
>>> df.columns
Index(['c0', 'c1'], dtype='object')
qu'il est d'ailleurs possible de renommer via un dictionnaire :
>>> df = df.rename(columns={
... 'c0': 'col0',
... 'c1': 'col1'
... })
>>> df
col0 col1
0 A 1
1 B 2
2 C 3
3 D 4
Le type de chaque colonne peut être déterminé à l'aide de l'attribut dtypes
>>> df.dtypes
col1 object
col2 float64
dtype: object
Indexing
L'indexing "par défaut" est fait par colonne.
>>> df['col1']
0 1
1 2
2 3
3 4
Name: col2, dtype: float64
>>> type(df['col1'])
pandas.core.series.Series
On obtient ici une série (Series
) dont on peut répérer l'élément associé à l'index 2
par exemple à l'aide de :
>>> df['col1'][2]
3.0
Il est également possible d'utiliser loc
(mais attention l'ordre est inversé)
>>> df.loc[2, 'col1']
ou iloc
>>> df.iloc[2, 1]
Pour sélectionner tous les colonnes d'une ligne donnée, plusieurs solutions sont possibles :
Transposition
>>> df.transpose()[2]
col0 C
col1 3
Loc avec :
>>> df.loc[2, :]
col0 C
col1 3
Name: 2, dtype: object
Les indexes sont sur l'axe nommé axis=0
. C'est l'axe par défaut du DataFrame.
Les colonnes sont sur l'axe nommé axis=1
.
Entrées / sorties
Fichiers CSV
Les fichiers CSV (Comma-separated_values) contiennent des données tabulaires sous forme de valeurs séparées par des virgules (ou des points-virgules ou des tabulations).
Lecture
Il est possible de lire un fichier CSV et obtenir un DataFrame
via :
>>> import pandas as pd
>>> filename = 'chemin/vers/fichier.csv'
>>> df = pd.read_csv(filename)
Ecriture
On peut écrire dans un fichier CSV le contenu d'un DataFrame
via :
>>> filename = 'chemin/vers/fichier_sortie.csv'
>>> df.to_csv(filename)
Fichiers Excel
Les fichiers Excel (.xls
et .xlsx
) sont pris en charge par Pandas.
Lecture
Il est possible de lire un fichier Excel et obtenir un DataFrame
via :
>>> filename = 'chemin/vers/fichier.xls'
>>> df = pd.read_excel(filename)
Ecriture
On peut créer un fichier Excel avec le contenu d'un DataFrame
via :
>>> filename = 'chemin/vers/fichier_sortie.xls'
>>> df.to_excel(filename)
Il est possible de passer un engine
- moteur de génération de fichier Excel :
engine = 'xlsxwriter'
engine = 'openpyxl'
engine = 'xlwt'
Il est également possible de créer un fichier Excel avec plusieurs onglets:
>>> df1 = pd.DataFrame({'c1': [1, 2, 3], 'c2': [4, 5, 6]})
>>> df2 = pd.DataFrame({'c1': [10, 20, 30], 'c2': [40, 50, 60]})
>>> writer = pd.ExcelWriter(filename)
>>> df1.to_excel(writer, 'Sheet1')
>>> df2.to_excel(writer, 'Sheet2')
>>> writer.save()
ou avec with
>>> with pd.ExcelWriter(filename) as writter:
>>> df1.to_excel(writer, 'Sheet1')
>>> df2.to_excel(writer, 'Sheet2')
Fichiers JSON
Lecture
Il est possible de lire un fichier JSON et obtenir un DataFrame
via :
>>> filename = 'chemin/vers/fichier.json'
>>> df = pd.read_json(filename)
Si le document JSON est dans une chaîne de caractères :
Ecriture
Un fichier JSON peut être généré avec :
>>> filename = 'chemin/vers/fichier_sortie.json'
>>> df.to_json(filename)
Il est possible de changer la manière dont le fichier JSON est généré à l'aide du
paramètre orient
pouvant prendre la valeur 'split'
, 'records'
, 'index'
,
'columns'
, 'values'
.
Plus d'informations grâce à la docstring accessible via :
>>> ?df.to_json
Autres entrées / sorties
Pandas possède beaucoup d'autres méthodes d'entrées / sorties comme :
- presse papier (clipboard)
- Pickle
- HTML (HyperText Mark-Up Language)
- SQL (Structured Query Language)
- HDF (Hierarchical Data Format)
- ...
http://pandas.pydata.org/pandas-docs/stable/io.html
Autres notions
>>> df = pd.DataFrame(np.random.randn(4, 3), columns=list('ABC'), index=np.arange(0, 4))
>>> df = pd.DataFrame(
[[-0.31044740287134603, -1.7125844360733045, 0.8983887824503948],
[1.7580716134201375, 0.5549231362310614, -0.6599096049847861],
[-0.711561271353247, -0.14915876017045665, -2.8424133601291346],
[2.278362681941062, 1.0452963523579037, -0.8134966152002406]],
index = np.arange(4),
columns = list('ABC')
)
A B C
0 -0.310447 -1.712584 0.898389
1 1.758072 0.554923 -0.659910
2 -0.711561 -0.149159 -2.842413
3 2.278363 1.045296 -0.813497
sort_index
Il est possible de trier les axes d'un DataFrame.
axis=0
et ascending=False
donc trie du DataFrame en utilisant les index (axis=0
- axe par défaut) par l'ordre décroissant (ascending=False
).
>>> df.sort_index(0, ascending=False)
A B C
3 2.278363 1.045296 -0.813497
2 -0.711561 -0.149159 -2.842413
1 1.758072 0.554923 -0.659910
0 -0.310447 -1.712584 0.898389
axis=1
et ascending=False
donc trie du DataFrame en utilisant les colonnes (axis=1
) par l'ordre décroissant (ascending=False
).
>>> df.sort_index(1, ascending=False)
C B A
0 0.898389 -1.712584 -0.310447
1 -0.659910 0.554923 1.758072
2 -2.842413 -0.149159 -0.711561
3 -0.813497 1.045296 2.278363
sort_values
sort_values
(anciennement sort
) permet de classer le DataFrame df par colonne B croissante
>>> df.sort_values('B')
A B C
0 -0.310447 -1.712584 0.898389
2 -0.711561 -0.149159 -2.842413
1 1.758072 0.554923 -0.659910
3 2.278363 1.045296 -0.813497
Classer le DataFrame
df
par colonnes :
- A décroissante
- puis B décroissante
- puis C décroissante
>>> df.sort_values(['A', 'B', 'C'], ascending=[False, False, False])
A B C
3 2.278363 1.045296 -0.813497
1 1.758072 0.554923 -0.659910
0 -0.310447 -1.712584 0.898389
2 -0.711561 -0.149159 -2.842413
Remarque : par défaut le paramètre inplace=False
cela signifie que
le DataFrame
n'est pas trié en place mais il doit être copié dans une nouvelle
variable.
describe
Afficher les stats (nombre d'éléments, moyenne, écart type (std=standard deviation), ...)
>>> df.describe()
A B C
count 4.000000 4.000000 4.000000
mean 0.753606 -0.065381 -0.854358
std 1.484673 1.202592 1.534489
min -0.711561 -1.712584 -2.842413
25% -0.410726 -0.540015 -1.320726
50% 0.723812 0.202882 -0.736703
75% 1.888144 0.677516 -0.270335
max 2.278363 1.045296 0.898389
>>> df.T.describe()
0 1 2 3
count 3.000000 3.000000 3.000000 3.000000
mean -0.374881 0.551028 -1.234378 0.836721
std 1.306679 1.208995 1.420707 1.556447
min -1.712584 -0.659910 -2.842413 -0.813497
25% -1.011516 -0.052493 -1.776987 0.115900
50% -0.310447 0.554923 -0.711561 1.045296
75% 0.293971 1.156497 -0.430360 1.661830
max 0.898389 1.758072 -0.149159 2.278363
Quelques autres méthodes utiles
set_index
La méthode set_index
permet de définir une colonne d'un DataFrame
comme nouvel index.
Exemple:
>>> idx = pd.date_range("2010-01-01", "2011-12-31")
>>> df = pd.DataFrame(np.random.randn(len(idx), 3), columns=list('ABC'))
>>> df["DateTime"] = idx
>>> df
A B C DateTime
0 -0.601814 -2.391967 0.279425 2010-01-01
1 -0.409895 -0.584120 0.398827 2010-01-02
2 -0.507415 -0.048778 -1.359944 2010-01-03
3 -0.902353 -0.004175 0.635948 2010-01-04
4 1.028238 1.850996 1.400967 2010-01-05
.. ... ... ... ...
725 -0.105517 -0.221570 1.607805 2011-12-27
726 -0.947596 -2.754443 -1.217261 2011-12-28
727 -0.721938 0.431173 1.045649 2011-12-29
728 -0.858780 0.349792 -1.423916 2011-12-30
729 -2.093146 -1.131250 0.604046 2011-12-31
[730 rows x 4 columns]
>>> df = df.set_index("DateTime")
>>> df
A B C
DateTime
2010-01-01 -0.601814 -2.391967 0.279425
2010-01-02 -0.409895 -0.584120 0.398827
2010-01-03 -0.507415 -0.048778 -1.359944
2010-01-04 -0.902353 -0.004175 0.635948
2010-01-05 1.028238 1.850996 1.400967
... ... ... ...
2011-12-27 -0.105517 -0.221570 1.607805
2011-12-28 -0.947596 -2.754443 -1.217261
2011-12-29 -0.721938 0.431173 1.045649
2011-12-30 -0.858780 0.349792 -1.423916
2011-12-31 -2.093146 -1.131250 0.604046
[730 rows x 3 columns]
Remarque : par défaut, il ne s'agit pas d'une opération en place (inplace=False
), il donc nécessaire de sauvegarder le nouveau DataFrame.
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.set_index.html
shift
Permet de décaler une série d'un certain nombre d'échantillons
Exemple
Soit le DataFrame suivant pour lequel la colonne E
représente la consommation d'énergie (en kW.h) d'une installation.
>>> idx = pd.date_range("2010-01-01", "2010-01-05")
>>> df = pd.DataFrame({"E": [20.2,22.3,24.4,28.2,30]}, index=idx)
>>> df
E
2010-01-01 20.2
2010-01-02 22.3
2010-01-03 24.4
2010-01-04 28.2
2010-01-05 30.0
Il est possible de calculer la puissance (moyenne) consommée par l'installation
>>> df["E_2"] = df["E"].shift()
>>> df
E E_2
2010-01-01 20.2 NaN
2010-01-02 22.3 20.2
2010-01-03 24.4 22.3
2010-01-04 28.2 24.4
2010-01-05 30.0 28.2
>>> df["P"] = (df["E"] - df["E_2"]) * 1000 / 24
>>> df
E E_2 P
2010-01-01 20.2 NaN NaN
2010-01-02 22.3 20.2 87.500000
2010-01-03 24.4 22.3 87.500000
2010-01-04 28.2 24.4 158.333333
2010-01-05 30.0 28.2 75.000000
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.shift.html
value_counts
La méthode value_counts
permet de compter le nombre de valeurs uniques dans une Series
.
>>> s = pd.Series(["a","a","b","c","d","d","d"])
>>> s
0 a
1 a
2 b
3 c
4 d
5 d
6 d
dtype: object
>>> s.value_counts()
d 3
a 2
c 1
b 1
dtype: int64
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.value_counts.html
Exemple : comptage des intervalles de temps entre 2 mesures.
>>> idx = pd.DatetimeIndex(["2010-01-1", "2010-01-02", "2010-01-04", "2010-01-05", "2010-01-06", "2010-01-10"])
>>> s = pd.Series(100*np.random.rand(len(idx)), idx)
>>> s.name="Value"; s.index.name="DateTime"
>>> s
DateTime
2010-01-01 64.589411
2010-01-02 43.758721
2010-01-04 89.177300
2010-01-05 96.366276
2010-01-06 38.344152
2010-01-10 79.172504
Name: Value, dtype: float64
>>> ecarts = pd.Series(s.index) - pd.Series(s.index).shift()
>>> ecarts
0 NaT
1 1 days
2 2 days
3 1 days
4 1 days
5 4 days
Name: DateTime, dtype: timedelta64[ns]
>>> ecarts.value_counts()
1 days 3
2 days 1
4 days 1
fillna
La méthode fillna
(d'une Series
ou d'un DataFrame
) permet de remplacer une donnée absente (NaN
pour Not a Number ou NaT
pour Not a Time).
Exemple:
Soit la Series
définie par
>>> idx = pd.date_range("2010-01-01", "2010-01-05")
>>> s = pd.Series([20.2,22.3,None,28.2,30], idx)
>>> s
2010-01-01 20.2
2010-01-02 22.3
2010-01-03 NaN
2010-01-04 28.2
2010-01-05 30.0
Freq: D, dtype: float64
Il est possible de remplacer la valeur absente (du 3/1/2010)
- par une valeur constante
>>> s.fillna(0)
2010-01-01 20.2
2010-01-02 22.3
2010-01-03 0.0
2010-01-04 28.2
2010-01-05 30.0
Freq: D, dtype: float64
- par la prochaine valeur observée (non nulle)
>>> s.fillna(method='backfill')
2010-01-01 20.2
2010-01-02 22.3
2010-01-03 28.2
2010-01-04 28.2
2010-01-05 30.0
Freq: D, dtype: float64
- par la valeur non nulle précédemment observée
>>> s.fillna(method='ffill')
2010-01-01 20.2
2010-01-02 22.3
2010-01-03 22.3
2010-01-04 28.2
2010-01-05 30.0
Freq: D, dtype: float64
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.fillna.html
resample
La méthode resample
permet de rééchantillonner des séries temporelles (Series
ou DataFrame
).
Exemple: Il est par exemple possible à partir de grandeurs mesurées toutes les heures (ou irrégulièrement espacées) de rééchantillionner ces données avec une période journalière.
>>> np.random.seed(0)
>>> idx = pd.date_range("2010-01-01", "2010-01-05", freq="1H")
>>> s = pd.Series(np.random.randn(len(idx)), index=idx).cumsum() + 100
>>> s
2010-01-01 00:00:00 101.764052
2010-01-01 01:00:00 102.164210
2010-01-01 02:00:00 103.142948
2010-01-01 03:00:00 105.383841
2010-01-01 04:00:00 107.251399
...
2010-01-04 20:00:00 101.615951
2010-01-04 21:00:00 102.592590
2010-01-04 22:00:00 102.948956
2010-01-04 23:00:00 103.655530
2010-01-05 00:00:00 103.666030
Freq: H, dtype: float64
En prenant la valeur moyenne par jour
>>> s.resample("1D").mean()
2010-01-01 108.235231
2010-01-02 111.136193
2010-01-03 103.208369
2010-01-04 99.570333
2010-01-05 103.666030
Freq: D, dtype: float64
ou avec l'ancienne syntaxe:
>>> s.resample("1D", how="mean")
En utilisant la méthode ohlc
(open high low close) qui permet de connaître les valeurs extrêmes durant la période d'échantillonage.
>>> s.resample("1D").ohlc()
open high low close
2010-01-01 101.764052 112.240788 101.764052 109.609592
2010-01-02 111.879346 113.818803 108.077111 108.854602
2010-01-03 107.240704 107.240704 98.729526 99.639545
2010-01-04 100.778946 103.655530 96.221713 103.655530
2010-01-05 103.666030 103.666030 103.666030 103.666030
ou avec l'ancienne syntaxe:
>>> s.resample("1D", how="ohlc")
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.resample.html
isnull()
/ notnull()
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.isnull.html http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.notnull.html
Exemple: compter des valeurs manquantes (absences d'enregistrement de données)
map
/ apply
/ applymap
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.map.html http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.apply.html http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.applymap.html
groupby
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html
Fuseaux horaires
Les méthodes tz_localize
et tz_convert
permettent de gérer les timezones (fuseaux horaires) de l'index d'une Series
ou d'un DataFrame
Soit une série temporelle définie par:
>>> idx = pd.date_range("2010-01-01", "2010-01-05")
>>> s = pd.Series(100*np.random.rand(len(idx)), idx)
2010-01-01 54.881350
2010-01-02 71.518937
2010-01-03 60.276338
2010-01-04 54.488318
2010-01-05 42.365480
Freq: D, dtype: float64
tz_localize
permet d'affecter une timezone (fuseau horaire) aux date/heure de l'index.
>>> s_paris=s.tz_localize('Europe/Paris')
>>> s_paris
2010-01-01 00:00:00+01:00 54.881350
2010-01-02 00:00:00+01:00 71.518937
2010-01-03 00:00:00+01:00 60.276338
2010-01-04 00:00:00+01:00 54.488318
2010-01-05 00:00:00+01:00 42.365480
Freq: D, dtype: float64
tz_convert
permet de convertir les date/heure de l'index d'une timezone vers une autre timezone.
>>> s_paris.tz_convert('UTC')
2009-12-31 23:00:00+00:00 54.881350
2010-01-01 23:00:00+00:00 71.518937
2010-01-02 23:00:00+00:00 60.276338
2010-01-03 23:00:00+00:00 54.488318
2010-01-04 23:00:00+00:00 42.365480
Freq: D, dtype: float64
http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.tz_localize.html
concat
/ append
Exemples
Trouver tous les vendredi 13 depuis le 1er janvier 2000 jusqu'au 31 décembre 2015
>>> idx = pd.date_range('2000-01-01', '2015-12-31')
>>> idx
DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04',
'2000-01-05', '2000-01-06', '2000-01-07', '2000-01-08',
'2000-01-09', '2000-01-10',
...
'2015-12-22', '2015-12-23', '2015-12-24', '2015-12-25',
'2015-12-26', '2015-12-27', '2015-12-28', '2015-12-29',
'2015-12-30', '2015-12-31'],
dtype='datetime64[ns]', length=5844, freq='D', tz=None)
>>> df = pd.DataFrame(index=idx)
>>> df['Année'] = df.index.map(lambda dt: dt.year)
>>> df['Mois'] = df.index.map(lambda dt: dt.month)
>>> df['Jour'] = df.index.map(lambda dt: dt.day)
>>> df['JourSemaine'] = df.index.map(lambda dt: dt.weekday())
>>> # weekday (jour de la semaine) Lundi=0 Ma=1 Me=2 Je=3 Ve=4 Sa=5 Di=6
>>> df_ven_13 = df[(df['JourSemaine'] == 4) & (df['Jour'] == 13)] # boolean indexing
>>> df_ven_13
Année Mois Jour JourSemaine
2000-10-13 2000 10 13 4
2001-04-13 2001 4 13 4
2001-07-13 2001 7 13 4
2002-09-13 2002 9 13 4
2002-12-13 2002 12 13 4
... ... ... ... ...
2013-12-13 2013 12 13 4
2014-06-13 2014 6 13 4
2015-02-13 2015 2 13 4
2015-03-13 2015 3 13 4
2015-11-13 2015 11 13 4
[28 rows x 4 columns]
>>> df_ven_13.to_excel("vendredi13.xlsx") # export vers un fichier Ecel
Compter le nombre de vendredi 13 par an
>>> df_ven_13.groupby("Année")["Jour"].count()
Année
2000 1
2001 2
2002 2
2003 1
2004 2
..
2011 1
2012 3
2013 2
2014 1
2015 3
Name: Jour, dtype: int64
Panel
Le Panel
est une structure ressemblant à un DataFrame
mais qui possède une 3ième dimension.
Un exemple de Panel : les prix journaliers de 3 actifs (réchantillonnage ohlc).
>>> #from pandas.io import data, wb
>>> from pandas_datareader import pdr
>>> panel = pdr.DataReader(['MSFT', 'GOOG', 'AAPL'], 'yahoo')
>>> panel
<class 'pandas.core.panel.Panel'>
Dimensions: 6 (items) x 1380 (major_axis) x 3 (minor_axis)
Items axis: Open to Adj Close
Major_axis axis: 2010-01-04 00:00:00 to 2015-06-26 00:00:00
Minor_axis axis: AAPL to MSFT
Un panel possède donc 3 dimensions :
- Items axis
panel.items
(axis=0) - Minor axis
panel.minor_axis
(axis=2) - Major axis
panel.major_axis
(axis=1, axe par défaut du Panel)
On peut en prenant un item donné obtenir un DataFrame :
>>> panel['Adj Close']
AAPL GOOG MSFT
Date
2010-01-04 28.718094 NaN 26.769336
2010-01-05 28.767737 NaN 26.777984
2010-01-06 28.310151 NaN 26.613650
...
2015-06-24 128.110001 537.840027 45.639999
2015-06-25 127.500000 535.229980 45.650002
2015-06-26 126.750000 531.690002 45.259998
On peut également accéder à une information donnée via
>>> panel['Adj Close', '2015-06-01', 'GOOG']
533.98999000000003
ou via [items_indexer][minor_axis_indexer][major_axis_indexer]
>>> panel['Adj Close']['GOOG']['2015-06-01']
533.98999000000003
ou via .loc[...]
:
>>> panel.loc['Adj Close', '2015-06-01', 'GOOG']
533.98999000000003
Le symbole :
est utile, il permet de sélectionner l'ensemble des données d'un axe du Panel.
>>> panel[:, '2015-06-01', :]
Open High Low Close Volume Adj Close
AAPL 130.279999 131.389999 130.050003 130.539993 32112800.0 126.581548
GOOG 536.789978 536.789978 529.760010 533.989990 1904300.0 533.989990
MSFT 47.060001 47.770000 46.619999 47.230000 28837300.0 45.361712
Remarque : Le projet xarray (anciennement nommé xray) http://xarray.pydata.org/ (N-D labeled arrays and datasets in Python) est un alternative aux Panel supportant un nombre entier quelconque de dimensions.