Initiation à Pandas

Logo 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.

results matching ""

    No results matching ""