335 lines
11 KiB
Markdown
335 lines
11 KiB
Markdown
---
|
||
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.
|
||
|
||

|
||
|
||
----
|
||
|
||
## 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)
|
||
|
||
----
|
||
|
||

|
||
|
||
----
|
||
|
||
### 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`
|
||
|
||
----
|
||
|
||

|
||
|
||
----
|
||
|
||

|
||
|
||
----
|
||
|
||
### 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()
|
||
```
|
||
|
||
----
|
||
|
||

|
||
|
||
----
|
||
|
||
### 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}<br>%{value:.2f}€"})
|
||
figure.show()
|
||
```
|
||
|
||
[Personnalisation des camemberts](https://plotly.com/python/pie-charts/)
|
||
|
||
----
|
||
|
||

|
||
|
||
----
|
||
|
||
### 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/)
|
||
|
||
----
|
||
|
||

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

|