Introduction
Lire des tableaux de chiffres peut etre long et fastidieux, alors qu’il est bien plus facile et rapide de comparer visuellement des longueurs de barres ou des degrades de couleurs. Dans les paragraphes qui suivent, on a un apercu des possibilites offertes par R et Python, pour des mises en forme generales ou plus specialisees comme les cartes de chaleur.
library("reactable")
library("glue")
library("heatmaply")
library("RColorBrewer")
# jeux de données
= mtcars
donnees $mpg = donnees$mpg - mean(donnees$mpg)
donnees$drat = donnees$drat - mean(donnees$drat)
donnees
= "https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv"
url = read.csv(url, sep = ";") wine_quality
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.cluster.hierarchy import linkage
from scipy.spatial.distance import pdist
set()
sns.
= r.donnees
donnees = r.wine_quality
wine_quality = r.mtcars mtcars
Tables numeriques generales
dans Python avec pandas
On a une syntaxe tres compacte et efficace sous pandas.
= (donnees[['mpg', 'drat', 'disp', 'cyl', 'hp']].iloc[:10].style
html 'selector':"tr:hover", 'props':[("background-color", "#ffff99")]}])
.set_table_styles([{**{'font-size': '9pt', 'font-family': 'Calibri','padding-right': '5px',\
.set_properties('border': '1px solid grey'})
2)
.set_precision(= 'mpg', func = lambda x: f"color: {'red' if x < 0 else 'blue'}")
.applymap(subset = 'drat', color = ['coral', 'lightblue'], align = 'zero')
.bar(subset = 'cyl', color = 'lightgreen')
.highlight_max(subset = 'cyl', color = 'orange')
.highlight_min(subset = 'hp', cmap = 'Blues')
.background_gradient(subset
.render()
)
# with open('datatable.html','w') as f:
# f.write(html)
mpg | drat | disp | cyl | hp | |
---|---|---|---|---|---|
Mazda RX4 | 0.91 | 0.30 | 160.00 | 6.00 | 110.00 |
Mazda RX4 Wag | 0.91 | 0.30 | 160.00 | 6.00 | 110.00 |
Datsun 710 | 2.71 | 0.25 | 108.00 | 4.00 | 93.00 |
Hornet 4 Drive | 1.31 | -0.52 | 258.00 | 6.00 | 110.00 |
Hornet Sportabout | -1.39 | -0.45 | 360.00 | 8.00 | 175.00 |
Valiant | -1.99 | -0.84 | 225.00 | 6.00 | 105.00 |
Duster 360 | -5.79 | -0.39 | 360.00 | 8.00 | 245.00 |
Merc 240D | 4.31 | 0.09 | 146.70 | 4.00 | 62.00 |
Merc 230 | 2.71 | 0.32 | 140.80 | 4.00 | 95.00 |
Merc 280 | -0.89 | 0.32 | 167.60 | 6.00 | 123.00 |
dans R avec reactable
En utilisant le package formattable le code serait beaucoup plus court, mais il ne permettrait pas de faire des barres de couleurs differentes pour les valeurs positives ou negatives. Le package reactable offre beaucoup plus de possibilites au prix d’un code plus long, cf quelques hebdomadR precedents sur le format des tables.
= donnees[1:10, c('mpg', 'drat', 'disp', 'cyl', 'hp')]
ma_table = 100
largeur_colonnes
# fonction pour avoir des barres positives et negatives
<- function(width, height = "60%") {
bar_style = round(50 * (width + 1))
new_width if (width > 0) {
= glue("linear-gradient(90deg, transparent 0%, 50%, lightblue 50%, {new_width}%,
image transparent {new_width}%)")
else {
} = glue("linear-gradient(90deg, transparent 0%, {new_width}%, coral {new_width}%,
image 50%, transparent 50%")
}list(backgroundImage = image,
backgroundSize = paste("100%", height),
backgroundRepeat = "no-repeat",
backgroundPosition = "center",
color = "black")
}
# fonction pour la palette de couleur Blues
<- function(x) rgb(colorRamp(brewer.pal(9,"Blues"))(x),
blue_pal maxColorValue = 255)
reactable(
ma_table,bordered = TRUE,
highlight = TRUE,
columns = list(
disp = colDef(width = largeur_colonnes),
mpg = colDef(style = function(value) {
if (value < 0) {color = "red"} else {color = "blue"}
list(color = color)},
format = colFormat(digits = 2),
width = largeur_colonnes),
cyl = colDef(style = function(value) {
= "none"
color if (value == max(ma_table$cyl)) {color = "lightgreen"}
if (value == min(ma_table$cyl)) {color = "orange"}
list(background = color)},
width = largeur_colonnes),
hp = colDef(style = function(value) {
<- (value - min(ma_table$hp)) / (max(ma_table$hp) - min(ma_table$hp))
normalized list(background = blue_pal(normalized))},
width = largeur_colonnes),
drat = colDef(style = function(value) {bar_style(width = value / max(abs(ma_table$drat)))},
align = "center",
format = colFormat(digits = 2),
width = largeur_colonnes))
)
Cartes de chaleur
Que ce soit sous R ou Python, les cartes de chaleur operent par defaut un tri intelligent par CAH sur les lignes et colonnes. Et les 2 packages choisis utilisent ici la palette viridis.
dans Python avec seaborn
= sns.clustermap(mtcars, figsize=(5, 5), z_score = 1, cmap = "viridis")
g plt.show()
dans R avec heatmaply
heatmaply(mtcars, scale = "column", plot_method ="plotly")
Matrices de correlation
On veut que 2 colonnes tres correlees ou anti-correlees soient proches, on utilise pour cela la mesure de similarite \(1 - \text{abs}(\text{cor}(X,Y))\).
dans Python avec seaborn
On utilise le clustering par CAH pour trier intelligemment les colonnes de la matrice de correlation, puis on la visualise par carte de chaleur.
# tri intelligent des colonnes
= linkage(1 - np.abs(1 - pdist(wine_quality.T, 'correlation')), 'ward')
link = sns.clustermap(wine_quality, col_linkage = link, row_cluster = False, figsize=(5, 5))
clustergrid plt.show()
# on applique le nouvel ordre
= list(wine_quality.iloc[:,clustergrid.dendrogram_col.reordered_ind].columns)
ordre_col = wine_quality[ordre_col].corr()
mat_corr
= (11,11))
plt.figure(figsize = -1, vmax = 1, center= 0, annot = True, cmap = "RdBu")
sns.heatmap(mat_corr, vmin plt.show()
dans R avec heatmaply
C’est la carte de chaleur qui effectue la CAH, et on retrouve les memes groupes de variables que sous Python.
= function(x) {as.dist(1 - abs(cor(t(x))))}
ma_dist
= cor(wine_quality)
mat_corr
heatmaply(mat_corr,
distfun = ma_dist, hclust_method = "ward.D",
colors = c("red", "white", "blue"), limits = c(-1, 1),
revC = FALSE, symm = TRUE,
cellnote = round(mat_corr, 2), cellnote_textposition = "middle center",
plot_method = "plotly") %>% plotly::layout(width=900)