Initial commit
This commit is contained in:
334
documentation/new-02.2-eda-plotly.md
Normal file
334
documentation/new-02.2-eda-plotly.md
Normal file
@ -0,0 +1,334 @@
|
||||
---
|
||||
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.
|
||||
|
||||
----
|
||||
|
||||

|
Reference in New Issue
Block a user