--- title: Plotly Express author: Steve Kossouho --- # Rendu de graphiques avec Plotly ---- ## Qu'est-ce que Plotly ? Selon le site de Plotly : La bibliothèque graphique Python Plotly crée des graphiques interactifs de qualité propre à la publication. ![Logo de Plotly](assets/images/eda-plotly-logo.png) ---- ## Comment fonctionne Plotly ? Plotly est une bibliothèque Python compatible avec les `DataFrame`{.python} Pandas, qui permet de créer des graphiques interactifs, et cela grâce aux technologies web (HTML, CSS et JS). Un navigateur suffit à afficher le contenu d'un graphique généré avec Plotly. La bibliothèque est relativement facile à prendre en main et bien documentée, de sorte qu'il est simple de faire des choses simples, et abordable de produire des choses plus complexes. [Documentation de Plotly pour Python](https://plotly.com/python/) ---- ## Plotly Express Plotly express est une bibliothèque de Plotly proposant très simplement de créer des graphiques, depuis des `DataFrame`{.python} Pandas. Elle propose toute la variété de graphiques générables avec Plotly, via des fonctions prêtes à l'emploi prenant en argument un `DataFrame`{.python}. ---- ### Installer Plotly Express ```bash= {.numberLines} pip install plotly ``` ---- ### Barres Générer un graphique en barres est assez simple avec Plotly, et fonctionne de manière relativement satisfaisante par défaut (ex. texte en blanc sur fond sombre) ```python {.numberLines} import pandas as pd from plotly import express data = pd.DataFrame(data={ "product": ["pomme", "poire", "banane", "pêche"], "price": [1.99, 2.49, 2.99, 3.49], "wpu": [200, 180, 140, 200] }) # Générer un graphique figure = express.bar(data, x="product", y=["price", "wpu"], barmode="group", title="Prix et poids unitaires") figure.show() ``` [Documentation de `bar`](https://plotly.com/python-api-reference/generated/plotly.express.bar.html) ---- ![Rendu de base en barres](assets/images/eda-plotly-express-bar-default.png) ---- ### Barres (sur un objet `Series`) Vous pouvez également générer un graphique en partant d'un objet de type `Series`, même si l'objet ne contient en lui-même qu'une seule colonne. Les valeurs d'index peuvent également servir sur un axe; il suffit d'utiliser la valeur `None`{.python} : ```python {.numberLines} import pandas as pd from plotly import express values = pd.Series( data=[1.99, 2.49, 2.99, 3.49], index=["pomme", "poire", "banane", "peche"], name="price" ) # Générer un graphique figure = express.bar(values, x=None, y="price") figure.show() ``` L'axe des Y pourra utiliser le nom associé à l'objet `Series` (`values.name`{.python}) ---- Quelques personnalisations sont possibles, notamment via la notion de `template` (thème), et de `layout` (organisation du contenu). ```python {.numberLines} import pandas as pd from plotly import express data = pd.DataFrame(data={ "product": ["pomme", "poire", "banane", "pêche"], "price": [1.99, 2.49, 2.99, 3.49], "wpu": [200, 180, 140, 200] }) # Générer un graphique. Plotly express ne prend en charge qu'un seul graphique par figure figure = express.bar(data, x="product", y="price", title="Prix", template="seaborn", labels={"price": "Prix", "product": "Produit"}) figure.layout.update({"font": {"family": "Cabin", "size": 13}}) figure.show() ``` ---- Voici une liste des valeurs possibles fournies par Plotly pour l'argument `template`{.python}: - `ggplot2` : Thème par défaut de GGPlot2 pour [R]{.naming} - `seaborn` : Thème par défaut de Seaborn pour Python - `plotly` : Thème par défaut de Plotly - `plotly_white` - `plotly_dark` - `presentation` - `xgridoff` - `ygridoff` - `gridon` - `none` ---- ![Rendu personnalisé en barres](assets/images/eda-plotly-express-bar-themed.png) ---- ![Rendu personnalisé en barres 2](assets/images/eda-plotly-express-bar-custom.png) ---- ### Secteurs concentriques Le graphique [sunburst]{.naming} permet d'afficher des secteurs, et de les découper en sous-catégories dans des anneaux concentriques. Ici, nous avons un `DataFrame`{.python} avec des ventes par ville, chaque ville appartenant à un pays. ```python {.numberLines} import pandas as pd import plotly from plotly.express import sunburst if __name__ == '__main__': df = pd.DataFrame(data={ "country": ["France", "France", "Spain", "Spain", "England", "England", "England"], "city": ["Montpellier", "Bordeaux", "Madrid", "Valencia", "London", "Manchester", "Bristol"], "sales": [150_000, 127_000, 97_200, 137_250, 200_000, 180_000, 150_000] }) plot = sunburst(df, path=["country", "city"], values="sales", title="Sales by country and city", template="ggplot2", color_discrete_sequence=plotly.colors.qualitative.Dark2) plot.layout.update({"font": {"family": "Cabin", "size": 13}}) plot.show() ``` [Documentation de `sunburst`](https://plotly.com/python-api-reference/generated/plotly.express.sunburst.html) ---- ![Rendu personnalisé en [sunburst]{.naming}](assets/images/eda-plotly-express-sunburst-themed.png) ---- ### Nuages de points Les nuages de points ([scatter plot]{.naming}) sont un moyen pratique de mettre en regard deux valeurs d'une même observation afin d'essayer de déduire une tendance ou une corrélation. Ils se présentent en 2 dimensions, mais deux autres axes peuvent être représentés via la taille ou la couleur des points du graphique. ```python {.numberLines} import pandas as pd from plotly import express as px data = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data", header=None, names=["sepal-length", "sepal-width", "petal-length", "petal-width", "class"]) plot = px.scatter(data, x="sepal-length", y="sepal-width", size="petal-width", color="class", template="seaborn", title="Iris flowers dataset", labels={"sepal-length": "Sepal length", "sepal-width": "Sepal width", "petal-width": "Petal width", "class": "Class"}) plot.layout.update({"font": {"family": "Cabin", "size": 13}}) plot.show() ``` [Documentation de `scatter`](https://plotly.com/python-api-reference/generated/plotly.express.scatter.html) ---- ![Rendu personnalisé en [scatter]{.naming}](assets/images/eda-plotly-express-scatter-themed.png) ---- ## Construction Cette section regroupe plusieurs solutions pour parvenir à certains résultats. ---- ### Deux axes Y dans un graphique en barres Par défaut, Plotly Express ne génère pas deux axes distincts lorsque vous affichez un graphique avec deux colonnes pour l'axe Y. Si leurs ordres de grandeur sont différents, les barres partageront toutefois la même échelle. Pour obtenir deux axes distincts en Y, nous devons utiliser Plotly manuellement. Rien d'anormalement complexe toutefois : ```python {.numberLines} import pandas as pd from plotly.graph_objs import Figure, Bar data = pd.DataFrame(data={ "product": ["pomme", "poire", "banane", "pêche"], "price": [1.99, 2.49, 2.99, 3.49], "wpu": [200, 180, 140, 200] }) figure = Figure([ Bar(name="Prix", x=data["product"], y=data["price"], yaxis="y", offsetgroup=1), Bar(name="Poids", x=data["product"], y=data["wpu"], yaxis="y2", offsetgroup=2), ]) # Afficher le dernier graphique généré figure.layout.update({ "template": "seaborn", "title": "Prix et poids unitaires", "font": {"family": "Cabin", "size": 13}, "yaxis": {"title": "Prix (€)"}, "yaxis2": {"title": "Poids (g)", "overlaying": "y", "side": "right"} }) figure.show() ``` ---- ![Rendu avec deux axes Y](assets/images/eda-plotly-compose-2axes.png) ---- ### Texte personnalisé dans un camembert Par défaut, les secteurs de graphique camembert ([pie]{.naming}) affichent la taille d'un secteur en pourcents du total. Vous pouvez y formater d'autres infos : ```python {.numberLines} import pandas as pd from plotly import express as px data = pd.DataFrame(data={ "product": ["pomme", "poire", "banane", "pêche"], "price": [1.99, 2.49, 2.99, 3.49], "wpu": [200, 180, 140, 200] }) figure = px.pie(data, values="price", names="product", title="Prix") # Afficher le dernier graphique généré figure.layout.update({ "template": "seaborn", "title": "Prix au kilo", "font": {"family": "Cabin", "size": 13}, }) figure.update_traces(**{"textinfo": "label+value", "texttemplate": "%{label}
%{value:.2f}€"}) figure.show() ``` [Personnalisation des camemberts](https://plotly.com/python/pie-charts/) ---- ![Rendu avec deux lignes de texte par secteur](assets/images/eda-plotly-compose-pie-label.png) ---- ### Choix de couleurs Vous pouvez définir votre propre choix de couleurs pour certains graphiques, avec certains arguments. L'argument `color_discrete_sequence`{.python} permet de définir une liste de couleurs à appliquer en tourniquet aux éléments du dessin. ```python {.numberLines} import pandas as pd from plotly import express as px data = pd.DataFrame(data={ "product": ["pomme", "poire", "banane", "pêche"], "price": [1.99, 2.49, 2.99, 3.49], "wpu": [200, 180, 140, 200] }) figure = px.pie(data, values="price", names="product", title="Prix", color_discrete_sequence=["red", "orange", "yellow", "#8F0"]) figure.layout.update({"template": "seaborn", "title": "Prix au kilo", "font": {"family": "Cabin", "size": 13}}) figure.show() ``` Plotly Express fournit des séquences ou dégradés de couleurs, dont la référence est disponible ci-dessous : [Couleurs et séquences de couleurs](https://plotly.com/python/discrete-color/) ---- ![Rendu avec choix de couleurs par secteur](assets/images/eda-plotly-express-pie-colors.png) ---- ### Couleur dépendante de la valeur Vous pouvez sur certains graphiques définir un gradient à appliquer aux éléments du dessin selon une valeur qui leur est associée. Ici, nous avons un graphique en barres, où la couleur de chaque barre dépend de la valeur de la colonne `price`. ```python {.numberLines} import pandas as pd from plotly import express as px data = pd.DataFrame(data={ "product": ["pomme", "poire", "banane", "pêche"], "price": [1.99, 2.49, 2.99, 3.49], "wpu": [200, 180, 140, 200] }) figure = px.bar(data, y="price", x="product", title="Prix", color="price", color_continuous_scale=["red", "orange", "yellow", "#8F0"]) figure.layout.update({"template": "seaborn", "title": "Prix au kilo", "font": {"family": "Cabin", "size": 13}}) figure.show() ``` Ici, l'argument `color` permet d'indiquer sur les valeurs de quelle colonne colorier les barres. L'argument `color_continuous_scale` permet de définir les couleurs d'un dégradé à utiliser pour colorier les barres. ---- ![Rendu avec gradient de couleurs](assets/images/eda-plotly-express-bar-gradient.png)