{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Cube de données et pandas\n", "\n", "[pandas](https://pandas.pydata.org/)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Un cube\n", "\n", "Les données sont disposées sous forme de table, il y a N colonnes de coordonnées et une colonne numérique. Avec ``N=4``, cela équivaut à une fonction $f(x_1,x_2,x_3,x_4)=y$." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X1X2X3X4Y
0A1B1C1D13
1A1B1C1D24
2A1B1C2D15
3A1B1C2D26
4A1B2C1D17
5A1B2C1D28
6A1B2C2D19
7A1B2C2D22
8A2B2C2D21
\n", "
" ], "text/plain": [ " X1 X2 X3 X4 Y\n", "0 A1 B1 C1 D1 3\n", "1 A1 B1 C1 D2 4\n", "2 A1 B1 C2 D1 5\n", "3 A1 B1 C2 D2 6\n", "4 A1 B2 C1 D1 7\n", "5 A1 B2 C1 D2 8\n", "6 A1 B2 C2 D1 9\n", "7 A1 B2 C2 D2 2\n", "8 A2 B2 C2 D2 1" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas\n", "\n", "data = [\n", " {\"X1\": \"A1\", \"X2\": \"B1\", \"X3\": \"C1\", \"X4\": \"D1\", \"Y\": 3},\n", " {\"X1\": \"A1\", \"X2\": \"B1\", \"X3\": \"C1\", \"X4\": \"D2\", \"Y\": 4},\n", " {\"X1\": \"A1\", \"X2\": \"B1\", \"X3\": \"C2\", \"X4\": \"D1\", \"Y\": 5},\n", " {\"X1\": \"A1\", \"X2\": \"B1\", \"X3\": \"C2\", \"X4\": \"D2\", \"Y\": 6},\n", " {\"X1\": \"A1\", \"X2\": \"B2\", \"X3\": \"C1\", \"X4\": \"D1\", \"Y\": 7},\n", " {\"X1\": \"A1\", \"X2\": \"B2\", \"X3\": \"C1\", \"X4\": \"D2\", \"Y\": 8},\n", " {\"X1\": \"A1\", \"X2\": \"B2\", \"X3\": \"C2\", \"X4\": \"D1\", \"Y\": 9},\n", " {\"X1\": \"A1\", \"X2\": \"B2\", \"X3\": \"C2\", \"X4\": \"D2\", \"Y\": 2},\n", " {\"X1\": \"A2\", \"X2\": \"B2\", \"X3\": \"C2\", \"X4\": \"D2\", \"Y\": 1},\n", "]\n", "df = pandas.DataFrame(data)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pivot\n", "\n", "Le pivot consiste à choisir des colonnes pour les indices des lignes, et d'autres pour les colonnes. Le pivot fonctionne si chaque valeur numérique peut être identifiée de manière unique." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X4D1D2D1D2
X1X2
A1B13.04.05.06.0
B27.08.09.02.0
A2B2NaNNaNNaN1.0
\n", "
" ], "text/plain": [ "X3 C1 C2 \n", "X4 D1 D2 D1 D2\n", "X1 X2 \n", "A1 B1 3.0 4.0 5.0 6.0\n", " B2 7.0 8.0 9.0 2.0\n", "A2 B2 NaN NaN NaN 1.0" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot(index=[\"X1\", \"X2\"], columns=[\"X3\", \"X4\"], values=\"Y\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X2B1B2
X3C1C2C1C2
X4D1D2D1D2D1D2D1D2
X1
A13.04.05.06.07.08.09.02.0
A2NaNNaNNaNNaNNaNNaNNaN1.0
\n", "
" ], "text/plain": [ "X2 B1 B2 \n", "X3 C1 C2 C1 C2 \n", "X4 D1 D2 D1 D2 D1 D2 D1 D2\n", "X1 \n", "A1 3.0 4.0 5.0 6.0 7.0 8.0 9.0 2.0\n", "A2 NaN NaN NaN NaN NaN NaN NaN 1.0" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot(index=[\"X1\"], columns=[\"X2\", \"X3\", \"X4\"], values=\"Y\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Index et MultiIndex\n", "\n", "A quoi correspondent les index ?" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MultiIndex([('B1', 'C1', 'D1'),\n", " ('B1', 'C1', 'D2'),\n", " ('B1', 'C2', 'D1'),\n", " ('B1', 'C2', 'D2'),\n", " ('B2', 'C1', 'D1'),\n", " ('B2', 'C1', 'D2'),\n", " ('B2', 'C2', 'D1'),\n", " ('B2', 'C2', 'D2')],\n", " names=['X2', 'X3', 'X4'])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv = df.pivot(index=[\"X1\"], columns=[\"X2\", \"X3\", \"X4\"], values=\"Y\")\n", "piv.columns" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['A1', 'A2'], dtype='object', name='X1')" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.index" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MultiIndex([('C1', 'D1'),\n", " ('C1', 'D2'),\n", " ('C2', 'D1'),\n", " ('C2', 'D2')],\n", " names=['X3', 'X4'])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv = df.pivot(index=[\"X1\", \"X2\"], columns=[\"X3\", \"X4\"], values=\"Y\")\n", "piv.columns" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MultiIndex([('A1', 'B1'),\n", " ('A1', 'B2'),\n", " ('A2', 'B2')],\n", " names=['X1', 'X2'])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les [Index](https://pandas.pydata.org/docs/reference/api/pandas.Index.html) indexent les valeurs et sont équivalents à des colonnes, les [MultiIndex](https://pandas.pydata.org/docs/reference/api/pandas.MultiIndex.html) indexent les valeurs et sont équivalents à plusieurs colonnes. On récupère le nom des colonnes avec la propriété [names](https://pandas.pydata.org/docs/reference/api/pandas.MultiIndex.names.html#pandas.MultiIndex.names)." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "FrozenList(['X3', 'X4'])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.columns.names" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "FrozenList(['X1', 'X2'])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.index.names" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On récupère le nombre de colonnes avec [nlevels](https://pandas.pydata.org/docs/reference/api/pandas.MultiIndex.nlevels.html#pandas.MultiIndex.nlevels)." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(2, 2)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.columns.nlevels, piv.index.nlevels" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ou encore [levels](https://pandas.pydata.org/docs/reference/api/pandas.MultiIndex.nlevels.html#pandas.MultiIndex.levels)." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(FrozenList([['C1', 'C2'], ['D1', 'D2']]),\n", " FrozenList([['A1', 'A2'], ['B1', 'B2']]))" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.columns.levels, piv.index.levels" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On veut accéder à un élément." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X4D1D2D1D2
X2
B13.04.05.06.0
B27.08.09.02.0
\n", "
" ], "text/plain": [ "X3 C1 C2 \n", "X4 D1 D2 D1 D2\n", "X2 \n", "B1 3.0 4.0 5.0 6.0\n", "B2 7.0 8.0 9.0 2.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.loc[\"A1\"]" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "X3 X4\n", "C1 D1 3.0\n", " D2 4.0\n", "C2 D1 5.0\n", " D2 6.0\n", "Name: (A1, B1), dtype: float64" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.loc[\"A1\", \"B1\"]" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X4D1D2
X1X2
A1B13.04.0
B27.08.0
A2B2NaNNaN
\n", "
" ], "text/plain": [ "X4 D1 D2\n", "X1 X2 \n", "A1 B1 3.0 4.0\n", " B2 7.0 8.0\n", "A2 B2 NaN NaN" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv[\"C1\"]" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "X1 X2\n", "A1 B1 3.0\n", " B2 7.0\n", "A2 B2 NaN\n", "Name: (C1, D1), dtype: float64" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv[\"C1\", \"D1\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Passer de l'un à l'autre\n", "\n", "Peut-on retrouver les données originales à partir du pivot?" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X4D1D2D1D2
X1X2
A1B13.04.05.06.0
B27.08.09.02.0
A2B2NaNNaNNaN1.0
\n", "
" ], "text/plain": [ "X3 C1 C2 \n", "X4 D1 D2 D1 D2\n", "X1 X2 \n", "A1 B1 3.0 4.0 5.0 6.0\n", " B2 7.0 8.0 9.0 2.0\n", "A2 B2 NaN NaN NaN 1.0" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ce qui ne marche pas [reset_index](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html)." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3X1X2C1C2
X4D1D2D1D2
0A1B13.04.05.06.0
1A1B27.08.09.02.0
2A2B2NaNNaNNaN1.0
\n", "
" ], "text/plain": [ "X3 X1 X2 C1 C2 \n", "X4 D1 D2 D1 D2\n", "0 A1 B1 3.0 4.0 5.0 6.0\n", "1 A1 B2 7.0 8.0 9.0 2.0\n", "2 A2 B2 NaN NaN NaN 1.0" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.reset_index(drop=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ce qui marche...\n", "\n", "* [stack](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html) : fait passer une coordonnée des colonnes aux lignes\n", "* [unstack](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.unstack.html) : fait passer une coordonnée des lignes aux colonnes" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X4D1D2
X1X2X3
A1B1C13.04.0
C25.06.0
B2C17.08.0
C29.02.0
A2B2C1NaNNaN
C2NaN1.0
\n", "
" ], "text/plain": [ "X4 D1 D2\n", "X1 X2 X3 \n", "A1 B1 C1 3.0 4.0\n", " C2 5.0 6.0\n", " B2 C1 7.0 8.0\n", " C2 9.0 2.0\n", "A2 B2 C1 NaN NaN\n", " C2 NaN 1.0" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.stack(0, future_stack=True)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "X1 X2 X3 X4\n", "A1 B1 C1 D1 3.0\n", " D2 4.0\n", " C2 D1 5.0\n", " D2 6.0\n", " B2 C1 D1 7.0\n", " D2 8.0\n", " C2 D1 9.0\n", " D2 2.0\n", "A2 B2 C1 D1 NaN\n", " D2 NaN\n", " C2 D1 NaN\n", " D2 1.0\n", "dtype: float64" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.stack([0, 1], future_stack=True)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X1X2X4
A1B1D13.05.0
D24.06.0
B2D17.09.0
D28.02.0
A2B2D1NaNNaN
D2NaN1.0
\n", "
" ], "text/plain": [ "X3 C1 C2\n", "X1 X2 X4 \n", "A1 B1 D1 3.0 5.0\n", " D2 4.0 6.0\n", " B2 D1 7.0 9.0\n", " D2 8.0 2.0\n", "A2 B2 D1 NaN NaN\n", " D2 NaN 1.0" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.stack(\"X4\", future_stack=True)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X4D1D2D1D2
X1A1A2A1A2A1A2A1A2
X2
B13.0NaN4.0NaN5.0NaN6.0NaN
B27.0NaN8.0NaN9.0NaN2.01.0
\n", "
" ], "text/plain": [ "X3 C1 C2 \n", "X4 D1 D2 D1 D2 \n", "X1 A1 A2 A1 A2 A1 A2 A1 A2\n", "X2 \n", "B1 3.0 NaN 4.0 NaN 5.0 NaN 6.0 NaN\n", "B2 7.0 NaN 8.0 NaN 9.0 NaN 2.0 1.0" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "piv.unstack(\"X1\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut changer l'ordre des index." ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MultiIndex([('A1', 'C1', 'D1'),\n", " ('A2', 'C1', 'D1'),\n", " ('A1', 'C1', 'D2'),\n", " ('A2', 'C1', 'D2'),\n", " ('A1', 'C2', 'D1'),\n", " ('A2', 'C2', 'D1'),\n", " ('A1', 'C2', 'D2'),\n", " ('A2', 'C2', 'D2')],\n", " names=['X1', 'X3', 'X4'])" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "view = piv.unstack(\"X1\")\n", "new_index = view.columns.reorder_levels([\"X1\", \"X3\", \"X4\"])\n", "new_index" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X1A1A2A1A2A1A2A1A2
X3C1C1C1C1C2C2C2C2
X4D1D1D2D2D1D1D2D2
X2
B13.0NaN4.0NaN5.0NaN6.0NaN
B27.0NaN8.0NaN9.0NaN2.01.0
\n", "
" ], "text/plain": [ "X1 A1 A2 A1 A2 A1 A2 A1 A2\n", "X3 C1 C1 C1 C1 C2 C2 C2 C2\n", "X4 D1 D1 D2 D2 D1 D1 D2 D2\n", "X2 \n", "B1 3.0 NaN 4.0 NaN 5.0 NaN 6.0 NaN\n", "B2 7.0 NaN 8.0 NaN 9.0 NaN 2.0 1.0" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "view.columns = new_index\n", "view" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Un pivot aggrégé\n", "\n", "La fonction pivot suppose que la transformation conserve chaque valeur sans les aggréger ce qui permet de restaurer les données sous leurs forme initiale. Mais ce n'est pas toujours ce qu'on souhaite faire." ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X1X2X3X4Y
0A1B1C1D13
1A1B1C1D24
2A1B1C2D15
3A1B1C2D26
4A1B2C1D17
5A1B2C1D28
6A1B2C2D19
7A1B2C2D22
8A2B2C2D21
\n", "
" ], "text/plain": [ " X1 X2 X3 X4 Y\n", "0 A1 B1 C1 D1 3\n", "1 A1 B1 C1 D2 4\n", "2 A1 B1 C2 D1 5\n", "3 A1 B1 C2 D2 6\n", "4 A1 B2 C1 D1 7\n", "5 A1 B2 C1 D2 8\n", "6 A1 B2 C2 D1 9\n", "7 A1 B2 C2 D2 2\n", "8 A2 B2 C2 D2 1" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Le pivot ne conserve pas les données.\n", "Index contains duplicate entries, cannot reshape\n" ] } ], "source": [ "try:\n", " df.pivot(index=[\"X2\"], columns=[\"X3\", \"X4\"], values=\"Y\")\n", "except Exception as e:\n", " print(\"Le pivot ne conserve pas les données.\")\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On utlise alors [pivot_table](https://pandas.pydata.org/docs/reference/api/pandas.pivot_table.html)." ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X4D1D2D1D2
X2
B11111
B21112
\n", "
" ], "text/plain": [ "X3 C1 C2 \n", "X4 D1 D2 D1 D2\n", "X2 \n", "B1 1 1 1 1\n", "B2 1 1 1 2" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index=[\"X2\"], columns=[\"X3\", \"X4\"], values=\"Y\", aggfunc=\"count\")" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
X3C1C2
X4D1D2D1D2
X2
B13456
B27893
\n", "
" ], "text/plain": [ "X3 C1 C2 \n", "X4 D1 D2 D1 D2\n", "X2 \n", "B1 3 4 5 6\n", "B2 7 8 9 3" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index=[\"X2\"], columns=[\"X3\", \"X4\"], values=\"Y\", aggfunc=\"sum\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## XArray\n", "\n", "Le package [XArray](https://docs.xarray.dev/en/stable/index.html) représente des cubes de données de façon plus efficace mais parfois moins intuitive." ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 192B\n",
       "Dimensions:  (X1: 2, X2: 2, X3: 2, X4: 2)\n",
       "Coordinates:\n",
       "  * X1       (X1) object 16B 'A1' 'A2'\n",
       "  * X2       (X2) object 16B 'B1' 'B2'\n",
       "  * X3       (X3) object 16B 'C1' 'C2'\n",
       "  * X4       (X4) object 16B 'D1' 'D2'\n",
       "Data variables:\n",
       "    Y        (X1, X2, X3, X4) float64 128B 3.0 4.0 5.0 6.0 ... nan nan nan 1.0
" ], "text/plain": [ " Size: 192B\n", "Dimensions: (X1: 2, X2: 2, X3: 2, X4: 2)\n", "Coordinates:\n", " * X1 (X1) object 16B 'A1' 'A2'\n", " * X2 (X2) object 16B 'B1' 'B2'\n", " * X3 (X3) object 16B 'C1' 'C2'\n", " * X4 (X4) object 16B 'D1' 'D2'\n", "Data variables:\n", " Y (X1, X2, X3, X4) float64 128B 3.0 4.0 5.0 6.0 ... nan nan nan 1.0" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import xarray as xr\n", "\n", "cube = xr.Dataset.from_dataframe(df.set_index([\"X1\", \"X2\", \"X3\", \"X4\"]))\n", "cube" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Modifier une valeur existante." ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 192B\n",
       "Dimensions:  (X1: 2, X2: 2, X3: 2, X4: 2)\n",
       "Coordinates:\n",
       "  * X1       (X1) object 16B 'A1' 'A2'\n",
       "  * X2       (X2) object 16B 'B1' 'B2'\n",
       "  * X3       (X3) object 16B 'C1' 'C2'\n",
       "  * X4       (X4) object 16B 'D1' 'D2'\n",
       "Data variables:\n",
       "    Y        (X1, X2, X3, X4) float64 128B 3.0 4.0 5.0 6.0 ... nan nan nan 1.0
" ], "text/plain": [ " Size: 192B\n", "Dimensions: (X1: 2, X2: 2, X3: 2, X4: 2)\n", "Coordinates:\n", " * X1 (X1) object 16B 'A1' 'A2'\n", " * X2 (X2) object 16B 'B1' 'B2'\n", " * X3 (X3) object 16B 'C1' 'C2'\n", " * X4 (X4) object 16B 'D1' 'D2'\n", "Data variables:\n", " Y (X1, X2, X3, X4) float64 128B 3.0 4.0 5.0 6.0 ... nan nan nan 1.0" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cube[\"Y\"].loc[{\"X1\": \"A1\", \"X2\": \"B2\", \"X3\": \"C2\", \"X4\": \"D1\"}] = 100\n", "cube" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 64B\n",
       "Dimensions:  (X1: 2, X4: 2)\n",
       "Coordinates:\n",
       "  * X1       (X1) object 16B 'A1' 'A2'\n",
       "  * X4       (X4) object 16B 'D1' 'D2'\n",
       "Data variables:\n",
       "    Y        (X1, X4) float64 32B 28.75 5.0 nan 1.0
" ], "text/plain": [ " Size: 64B\n", "Dimensions: (X1: 2, X4: 2)\n", "Coordinates:\n", " * X1 (X1) object 16B 'A1' 'A2'\n", " * X4 (X4) object 16B 'D1' 'D2'\n", "Data variables:\n", " Y (X1, X4) float64 32B 28.75 5.0 nan 1.0" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cube.mean(dim=(\"X2\", \"X3\"))" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Y
X1X2X3X4
A1B1C1D13.0
D24.0
C2D15.0
D26.0
B2C1D17.0
D28.0
C2D1100.0
D22.0
A2B1C1D1NaN
D2NaN
C2D1NaN
D2NaN
B2C1D1NaN
D2NaN
C2D1NaN
D21.0
\n", "
" ], "text/plain": [ " Y\n", "X1 X2 X3 X4 \n", "A1 B1 C1 D1 3.0\n", " D2 4.0\n", " C2 D1 5.0\n", " D2 6.0\n", " B2 C1 D1 7.0\n", " D2 8.0\n", " C2 D1 100.0\n", " D2 2.0\n", "A2 B1 C1 D1 NaN\n", " D2 NaN\n", " C2 D1 NaN\n", " D2 NaN\n", " B2 C1 D1 NaN\n", " D2 NaN\n", " C2 D1 NaN\n", " D2 1.0" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cube.to_dataframe()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.8" } }, "nbformat": 4, "nbformat_minor": 2 }