Martin Cubaud
LASTIG-UGE-IGN/ENSG
2024-2025
Décrire et mesurer la répartition des valeurs que peut prendre une variable : sa distribution (≈ “histogramme en continu”)
Parfois certaines distributions ressemblent à des distributions bien connues : on parle de lois.
e.g. loi normale/gaussienne, loi de Poisson, géométrique, exponentielle…
xx = np.random.normal(size=2600)
plt.figure(figsize=(12, 5))
plt.hist(xx, bins=50, edgecolor="#aaaaaa", color="#44DD99")
plt.xlabel("value")
plt.ylabel("count")
plt.grid(True)
plt.show()
xx = pd.DataFrame(np.random.normal(size=2600))
xx.hist(bins=50, figsize=(12, 5), edgecolor="#aaaaaa", color="#44DD99", grid=True)
plt.xlabel("value")
plt.ylabel("count")
plt.show()
xx <- data.frame(value=rnorm(2600))
plot1 <- ggplot(xx)+
geom_histogram(aes(x = value),bins = 50, color="#aaaaaa", fill="#44DD99" )+
theme_light()
plot1
Données : arbres de la ville de Paris [https://opendata.paris.fr/]
Données : arbres de la ville de Paris [https://opendata.paris.fr/]
Objectif : Décrire la répartition des valeurs d’une variable
mode, moyenne, médiane
étendue, écart-type, variance, quantiles, coefficient de variation
symétrie (Skewness) et aplatissement (Kurtosis)
Moyenne(s), mode, médiane
\(\displaystyle \bar{x} = \frac{1}{n}\sum_{i=0}^{n} x_i\)
Lorsque les valeurs n'ont pas le même poids
Par exemple : poids = effectif de la valeur dans la population.
\(\displaystyle \bar{x} = \frac{1}{\sum_{i=0}^{n} p_i}\sum_{i=0}^{n} p_i x_i\)
Chaque valeur compte
\(\displaystyle \bar{x} = \sqrt[n]{\prod _{i=0}^{n} x_i}\)
Moins sensible à la présence de valeurs extrêmes
\(\displaystyle \bar{x} = \sqrt{\frac{1}{n}\sum_{i=0}^{n} x_i^2}\)
Moyenne calculée sur une fenètre de n valeurs consécutives.
e.g. on reçoit une mesure chaque seconde, très bruitée, et on désire afficher 10 minutes de signal lissé dans le temps
→ on calcule pour chaque point du signal, la moyenne sur 10 valeurs consécutives (5 en avant , 5 en arrière)
Mode : valeur la plus fréquente (effectif max.) de la série de valeurs que prend une variable.
⚠ si variable quantitative continue : faire une classification . Dans ce cas, le mode est la moyenne des valeurs min et max des bornes de la classe de plus grand effectif.
Peu sensible aux valeurs extrêmes (moins sensible que la moyenne)
Signification concrète : la situation la plus fréquente
Ne dépends pas de toutes les observations : la modification d’une seule valeur n’entraîne pas une modification du mode
Médiane : valeur qui partage une série de valeurs en deux sous-ensembles d'égal effectif.
Comme en géométrie, la médiane est la valeur de la variable qui est la plus proche de toutes les autres.
Ordonner les valeurs selon un ordre croissant.
Calculer le rang $i=\frac{n+1}{2}$.
Si n impair, la valeur médiane existe dans la série statistique.
Si n pair, la valeur médiane est entre deux valeurs, et est égale à la moyenne de ces 2 valeurs.
Souvent plus pertinente que la moyenne
Peu sensible aux valeurs extrêmes (moins sensible que la moyenne)
Signification concrète : divise en deux la distribution : un individu sur deux a une valeur inférieure ou supérieure à celle-ci
Ne dépends pas de toutes les observations : la modification d’une seule valeur n’entraîne pas une modification de la médiane
Tout dépend de la distribution !
→ Toujours afficher l'histogramme ou la distribution de densité !
Le Mode est privilégié pour les valeurs nominales et si on désire consider "le cas le plus fréquent".
Distribution sans longue traîne ?
→ moyenne et médiane
Plusieurs modes dans la distribution ?
→ classification puis médiane / moyenne par classe
Que choisir : moyenne ou médiane ?
from scipy.stats import gaussian_kde
xx = np.random.normal(loc=5, scale=1, size=2900)
density = gaussian_kde(xx) #kernel density estimator
x = np.linspace(min(xx), max(xx), 100)
y = density(x) #On estime la densité entre pour 100 valeurs entre xx_min et xx_max
plt.figure(figsize=(12, 5))
plt.plot(x, y, color="#44DD99", lw=1.3)
plt.axvline(x=np.mean(xx), color="red")
plt.axvline(x=np.median(xx) + 0.02, color="blue")
plt.text(4.5, 0.2, "mean", color="red")
plt.text(5.5, 0.2, "median", color="blue")
plt.xlabel("value")
plt.ylabel("density")
plt.grid(True)
plt.show()
xx = pd.Series(np.random.normal(loc=5, scale=1, size=2900))
ax = xx.plot(
kind="density", ind=np.linspace(min(xx), max(xx), 100),
figsize=(12, 5), color="#44DD99", lw=1.3, grid=True,
xlabel="value", ylabel="density")
ax.axvline(x=xx.mean(), color="red")
ax.axvline(x=xx.median() + 0.02, color="blue")
ax.text(4.5, 0.2, "mean", color="red")
ax.text(5.5, 0.2, "median", color="blue")
ax.set_xlabel("value")
xx <- data.frame(value=rnorm(2900,mean = 5, sd = 1))
plot1 <- ggplot(xx)+
geom_line(aes(x = value),stat = "density", color="#44DD99", lwd= 1.3)+
geom_vline(xintercept = mean(xx$value), color="red")+
geom_vline(xintercept = median(xx$value) + 0.02,color="blue")+
annotate("text", x=c(4.5,5.5), y=c(0.2,0.2), colour=c("red","blue"),label=c("mean", "median"))+
theme_light()
plot1
Histogramme pour un vecteur numérique :
plt.figure(figsize=(12, 3))
x = np.random.geometric(p=0.5, size=2500) #eg: Combien de fois lancer une pièce avant de tomber sur face
plt.hist(x, bins=10)
plt.title("Histogram of x")
plt.xlabel("x")
plt.ylabel("Frequency")
plt.show()
Un histogramme n’a pas de sens pour une variable qualitative.
On peut utiliser plt.bar, ⚠ mais ce n’est plus une distribution !
colors = sorted(["blue", "yellow", "red", "green", "purple", "orange", "black"])
samples = np.random.choice(colors, size=2500, replace=True)#['black', 'red', 'orange', ..., 'purple', 'green', 'purple']
plt.figure(figsize=(12, 3))
plt.bar(colors, np.unique(samples, return_counts=True)[1], color=colors)
plt.show()
Variance, écart-type, Coeff. de variation.
xy = np.random.normal(size=(900, 900))
plt.figure(figsize=(5, 5))
plt.scatter(xy[:, 0], xy[:, 1], s=21, color="#44DD99", edgecolor="#666666")
plt.xlabel("X")
plt.ylabel("Y")
plt.grid(True)
plt.axis("equal")
plt.show()
xy = pd.DataFrame(np.random.normal(size=(900, 900)))
xy.plot(kind="scatter", x=0, y=1, s=[21], color="#44DD99", edgecolor="#666666", figsize=(5, 5), grid=True)
plt.xlabel("X")
plt.ylabel("Y")
plt.axis("equal")
plt.show()
mydataset <- data.frame(X=rnorm(900), Y=rnorm(900))
plot1 <- ggplot(mydataset)+
geom_point(aes(x=X, y=Y), fill="#44DD99", color="#666666", shape=21)+
coord_equal()+theme_light()
plot1
La variance est la somme des écarts carrés à la moyenne rapporté à l’effectif.
\(\displaystyle var_x = \frac{1}{n}\sum_{i=0}^{n} (x_i -\bar{x})^2\)
Avec $X$ une variable, $x_i$ les valeurs de la variable, $\bar{x}$ la moyenne de $X$, et $n$ l'effectif.
$\sigma_x = \sqrt{var_x}$ : l'écart type est la racine carrée de la variance.
Variance et écart-type rendent compte de la dispersion de la variable autour de sa moyenne.
Ils sont sensibles aux valeurs extrêmes et toujours positifs.
Si $var_X=0$ ou $\sigma_x=0$ , alors X est constante.
Un écart-type faible indique que les valeurs sont réparties de façon homogène autour de la moyenne.
$[\mu - \sigma ; \mu+\sigma] \approx \frac{2}{3}$ de l'effectif.
$[\mu - 2\sigma ; \mu+2\sigma] \approx 95\%$ de l'effectif.
$[\mu - 3\sigma ; \mu+3\sigma] \approx 99\%$ de l'effectif.
La médiane sépare une population en deux classes d'égal effectif selon la valeur d'une variable (quantitative).
Les quantiles séparent une population en n classes d'égal effectif.
Les quartiles d'une population selon une variable $X$ sont trois valeurs $Q_1, Q_2, Q_3$,qui séparent une population en quatres classes d'égal effectif.
De même, déciles et centiles.
Deux mesures de la dispersion d’une distribution :
Écart inter-quartile: $Q_3-Q_1$, capture 50% des valeurs de la population les plus proches de la médiane.
Écart inter-décile: $Q_9-Q_1$, capture 80% des valeurs de la population les plus proches de la médiane.
Représentation courante de la dispersion d’une variable à l’aide de quartiles
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['Species'] = iris.target_names[iris.target]
df.boxplot(by='Species', column='sepal width (cm)', vert=False, figsize=(9, 5))
plt.show()
from sklearn.datasets import load_iris
iris = load_iris()
#We create a list by species of sepal widths.
x = [iris.data[iris.target==i, 1] for i in np.unique(iris.target)]
plt.figure(figsize=(9, 5))
plt.boxplot(x, labels=iris.target_names, vert=False)
plt.grid()
plt.xlabel("sepal width (cm)")
plt.ylabel("Species")
plt.show()
plot1 <- ggplot(iris)+
geom_boxplot(aes(y=Sepal.Width,x= Species) ) + coord_flip()
plot1
Peu sensibles aux distributions aplaties et aux valeurs extrêmes
L’écart inter-quantile est plus robuste que l’écart-type
Parfois délicat pour les variables quantitatives discrètes
Les écarts inter-quantiles négligent l’influence des valeurs extrêmes sur la distribution
Le coefficient de variation (CV) est une autre mesure de dispersion.
C'est le ratio entre l'écart-type $\sigma_x$ et la moyenne $\bar{x}$ d'une variable quantitative X.
$CV(X)=\frac{\sigma_x}{\bar{x}}$
Plus il est important, plus la dispersion est grande.
Plus il est proche de 0, plus les données sont homogènes.
Il souffre des mêmes inconvénients que la moyenne et l'écart-type : sensibilité aux valeurs extrêmes.
Exemple : deux communes versent des aides aux entreprises locales.
Commune A : moyenne = 390€, $\sigma$ = 30€
Commune B : moyenne = 152€, $\sigma$ = 8€
Pour quelle commune les aides sont les plus homogènes ?
On pourrait aussi comparer des distribution de valeurs exprimées dans des unités différentes !
A = np.random.normal(size=10000, loc=390, scale=30)
B = np.random.normal(size=10000, loc=152, scale=8)
plt.figure(figsize=(20, 3))
ax = plt.subplot(1, 2, 1)
plt.hist(A, bins=10, color="white", edgecolor="black", density=True)
ax.set_xlabel("A")
ax.set_ylabel("Density")
ax.set_title("Histogram of A")
ax = plt.subplot(1, 2, 2)
plt.hist(B, bins=10, color="white", edgecolor="black", density=True)
ax.set_xlabel("B")
ax.set_ylabel("Density")
ax.set_title("Histogram of B")
plt.show()
A <- rnorm(n = 10000, mean = 390, sd = 30)
B <- rnorm(n = 10000, mean = 152, sd = 8)
par(mfrow=c(1, 2)) #2 graphes en colonnes
hist(A, probability = T)
lines(density(A), col="red")
hist(B, probability = T)
lines(density(B), col="red")
Qu'est-ce qui ne va pas ?
Il faut une échelle commune !
A = np.random.normal(size=10000, loc=390, scale=30)
B = np.random.normal(size=10000, loc=152, scale=8)
plt.figure(figsize=(20, 3))
ax1 = plt.subplot(1, 2, 1)
plt.hist(A, bins=10, color="white", edgecolor="black", density=True)
ax1.set_xlabel("A")
ax1.set_ylabel("Density")
ax1.set_title("Histogram of A")
ax2 = plt.subplot(1, 2, 2, sharex=ax1, sharey=ax2)
plt.hist(B, bins=10, color="white", edgecolor="black", density=True)
ax.set_xlabel("B")
ax.set_ylabel("Density")
ax.set_title("Histogram of B")
plt.show()
A <- rnorm(n = 10000, mean = 390, sd = 30)
B <- rnorm(n = 10000, mean = 152, sd = 8)
par(mfrow=c(1, 2))
hist(A, probability = T, xlim = c(50,600), ylim = c(0,0.05))
lines(density(A), col="red")
hist(B, probability = T,xlim = c(50,600), ylim = c(0,0.05))
lines(density(B), col="red")
Symétrie, applatissement
Deux moyens simples d'estimer l'asymétrie
$C_1 = \frac{\bar{x} - mode(X)}{\sigma_x}$
$C_2 = \frac{3(\bar{x} - mediane(X))}{\sigma_x}$
Ce coefficient est le moment d’ordre 3 de la variable $X$ ( de moyenne $\mu$ et d’écart-type $\sigma$) centrée réduite
$skewness = \mathbb{E} \left[ \left( \frac{X - \mu}{\sigma} \right)^3 \right] = \frac{\Sigma_{i=0}^n(x_i - \bar{x})^3}{n\sigma^3}$
Courbe piquée: Peu de variation, distribution relativement homogène, beaucoup de valeurs égales ou proches de la moyenne.
Courbe applatie: Variations importantes, distribution relativement hétérogène, beaucoup de valeurs s’éloignent de la moyenne.
Coefficient non normalisé :
$K=\frac{\Sigma_{i=0}^n(x_i - \bar{x})^4}{n\sigma^4}$
Si la distribution est normale, $K=3$
Si $K>3$, la distribution est plus applatie.
Si $K<3$, la distribution est moins applatie.
On normalise parfois en considérant $K′=K−3$ (excès d’applatissement)
Pour une variable quantitative continue qu’on souhaite colorer, il n’est pas toujours possible de graduer une échelle de couleur continue.
Il faut (souvent) classer les valeurs en catégories. Le nombre de classes et les méthodes de classification varient.
En général : 5, 7 ou 9 classes
Méthodes de classifications de Qgis
import geopandas as gpd
quartier = gpd.read_file("quartier_paris.shp")
quartier.plot(figsize=(15, 5), edgecolor="black")
quartiers <- st_read("quartier_paris.shp")
plot(quartiers$geometry)
quartier["surface"].plot(
kind="hist", bins=15, xlabel="surface [m²]", ylabel="count",
figsize=(15, 5), title="Histogram of surface")
hist(quartiers$surface,breaks = 15)
quartier.plot(column="surface", legend=True, figsize=(15, 5), edgecolor="black").set_title("Surface")
par(mar=c(0,0,0,0))
plot(quartiers["surface"])
Par défaut la fonction plot de sf utilise la méthode “pretty” avec 10 ruptures (9±1 classes) => ce sont des intervalles égaux.
Par défaut la fonction plot de géopandas utilise une échelle continue.
Code R correspondant :
Code Python correspondant :
import mapclassify
quartier.plot(
column="surface", scheme="naturalbreaks", k=5, legend=True, figsize=(15, 3), edgecolor="black",
legend_kwds={"title": "Surface", "loc": (1.01, 0), "fmt": "{:.1e}"}).set_title("Jenks (5)")
quartier.plot(
column="surface", scheme="naturalbreaks", k=7, legend=True, figsize=(15, 3), edgecolor="black",
legend_kwds={"title": "Surface", "loc": (1.01, 0), "fmt": "{:.1e}"}).set_title("Jenks (7)")
quartier.plot(
column="surface", scheme="naturalbreaks", k=9, legend=True, figsize=(15, 3), edgecolor="black",
legend_kwds={"title": "Surface", "loc": (1.01, 0), "fmt": "{:.1e}"}).set_title("Jenks (9)")
par(mar=c(0,0,0,0))
plot(quartiers["surface"], breaks="jenks", nbreaks = 5, main = "5 breaks")
plot(quartiers["surface"], breaks="jenks", nbreaks = 7, main="7 breaks")
plot(quartiers["surface"], breaks="jenks", nbreaks = 9, main= "9 breaks")
ax = quartier.plot(
column="surface", scheme="quantiles", k=5, legend=True, figsize=(15, 5), edgecolor="black",
legend_kwds={"title": "Surface", "loc": (1.01, 0), "fmt": "{:.1e}"}
)
ax.set_title("Effectifs égaux")
quartier.plot(
column="surface", scheme="equal_interval", k=7, legend=True,
legend_kwds={"title": "Surface", "loc": (1.01, 0), "fmt": "{:.2e}"}, figsize=(15, 5), edgecolor="black"
).set_title("Intervalles égaux (7)")
par(mar=c(0,0,0,0))
plot(quartiers["surface"], breaks="equal", nbreaks = 7, main = "Intervalles égaux")
quartier.plot(
column="surface", scheme="stdmean", classification_kwds={"anchor":True}, legend=True, figsize=(15, 5),
edgecolor="black", legend_kwds={"title": "Surface", "loc": (1.01, 0), "fmt": "{:.1e}"}
).set_title("écart-types")
par(mar=c(0,0,0,0))
plot(quartiers["surface"], breaks="sd",main = "Écart-type")
≈méthode des jolies ruptures sur variable centrée réduite
Pour les classification manuelles :
Consultez la documentation de la fonction classInt du package du même nom
Consultez la documentation du package mapclassify.
⚠ D'abord effectuer une transformation linéaire pour ajuster le domaine de la variable afin que la transformation suivante soit définie et injective, = elle associe des valeurs distinctes à des résultats distincts
(⚠ toujours vérifier l'allure de la distribution transformée)
⚠ En principe, uniquement lorsque la distribution d’une variable est proche d’une gaussienne ⚠
Centrer : soustraire la moyenne.
Réduire : diviser par l'écart-type
Une variable centrée réduite est exprimée en «écarts-types à la moyenne»
→ permet de repérer les valeurs extrèmes (<-2σ ou >2σ)
→ utile pour comparer des individus selon un grand nombre de variables (tableaux de synthèse)
from palmerpenguins import load_penguins
penguins = load_penguins()
penguins["body_mass_g"].dropna().plot(
kind="hist", bins=50, xlabel="body mass [g]", ylabel="count",
figsize=(15, 5), title="Penguins body mass\nhistogram", edgecolor="darkgray", color="darkorchid"
)
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
histo_mass <- ggplot(mydata)+
geom_histogram(aes(x=body_mass_g), fill="darkorchid4", color="darkgray", bins=50)+
labs(title = "Penguins Body Mass", subtitle = "Histogram")+
ylab("Count")+theme_light()
histo_mass
⚠ ce n'est pas une probabilité, mais une densité de probabilité. Pour obtenir la probabilité, utiliser la formule $\mathbb{P}(a\leqslant X\leqslant b) = \int_a^b f(t)\,\mathrm{d}t$
ax = penguins["body_mass_g"].dropna().plot(
kind="density", ylabel="count",
figsize=(15, 5), title="Penguins body mass\nProbability density and mean", color="darkorchid"
)
ax.axvline(x=penguins["body_mass_g"].dropna().mean(), color="black", linestyle="--")
ax.set_xlabel("body mass [g]")
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
distrib_mass <- ggplot(mydata)+
geom_density(aes(x=body_mass_g), fill="darkorchid4", color="darkgray")+
geom_vline(aes(xintercept=mean(body_mass_g, na.rm = T)), color="black", size=0.4, linetype="dashed" )+
labs(title = "Penguins Body Mass", subtitle = "Probability density and mean")+
ylab("Count")+theme_light()
distrib_mass
penguins.boxplot(
column="body_mass_g", by="species", vert=False, figsize=(15, 5)
).set_xlabel("body mass [g]")
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
boxplot_mass <- ggplot(mydata)+
geom_boxplot(aes(x=body_mass_g, y=species, color=species))+
labs(title = "Penguins Body Mass", subtitle = "BoxPlot by Species")+
ylab("Count")+theme_light()
boxplot_mass
Distribution + miroir. Utile pour des distributions complexes, mal résumées par la moyenne et la dispersion.
list_species = penguins["species"].unique()
plt.figure(figsize=(15, 5))
plt.violinplot(
[penguins[penguins["species"]==species]["body_mass_g"].dropna() for species in list_species],
)
plt.xticks(range(1, len(list_species)+1), list_species)
plt.xlabel("species", fontweight='bold')
plt.ylabel("body mass [g]")
plt.title("Penguins body mass\nviolin plot")
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
violin_mass <- ggplot(mydata)+
geom_violin(aes(y=body_mass_g, x=species, fill=species), color="gray", trim=F)+
labs(title = "Penguins Body Mass", subtitle = "ViolinPlot by Species")+
ylab("Count")+theme_light()
violin_mass
list_species = penguins["species"].unique()
plt.figure(figsize=(15, 5))
mass_groupby_species = [
penguins[penguins["species"]==species]["body_mass_g"].dropna() for species in list_species
]
plt.violinplot(mass_groupby_species, showextrema=False)
plt.boxplot(mass_groupby_species, widths=0.1)
plt.xticks(range(1, len(list_species)+1), list_species)
plt.xlabel("species", fontweight='bold')
plt.ylabel("body mass [g]")
plt.title("Penguins body mass\nviolin plot and boxplot")
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
violin_mass <- ggplot(mydata)+
geom_violin(aes(y=body_mass_g, x=species, fill=species), color="lightgray", trim=F)+
geom_boxplot(aes(y=body_mass_g, x=species, fill=species), color="black", fill="#eeeeee" ,width=0.1)+
labs(title = "Penguins Body Mass", subtitle = "ViolinPlot and Boxplot by Species")+
ylab("Count")+theme_light()
violin_masss
Lorsqu'une des variables est qualitative à deux modalités :
female_data = penguins[penguins['sex'] == 'female']
male_data = penguins[penguins['sex'] == 'male']
female_count = np.histogram(female_data['body_mass_g'], bins=bins)[0]
male_count = np.histogram(male_data['body_mass_g'], bins=bins)[0]
bins = np.linspace(min(penguins['body_mass_g']), max(penguins['body_mass_g']), 50)
plt.barh(bins[:-1], male_count, height=np.diff(bins)[0], label='Male', edgecolor="grey")
plt.barh(bins[:-1], -female_count, height=np.diff(bins)[0], label='Female', edgecolor="grey")
ticks = np.arange(-max(female_count), max(male_count), 2)
plt.xticks(ticks=ticks, labels=np.abs(ticks))
plt.axvline(x=0, color='black'); plt.xlabel('Count'); plt.ylabel('Body Mass [g]')
plt.title('Penguins Body Mass\nPyramid Plot by Sex')
plt.legend()
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
pyramide_mass <- ggplot(mydata, aes(fill = sex)) +
geom_bar(data = subset(mydata, sex == "female"), stat = "bin", aes(x=body_mass_g, y=..count..*(-1)), color="grey") +
geom_bar(data = subset(mydata, sex == "male"), stat = "bin", aes(x=body_mass_g), color="grey") +
scale_y_continuous(labels = paste0(as.character(c(seq(20, 0, -10), seq(10, 20, 10))))) +
ylab("count")+ coord_flip()+
labs(title = "Penguins Body Mass", subtitle = "Pyramid Plot by sex")+
theme_light()
pyramide_mass
“Histogramme en courbe”
Utile pour comparer plusieurs distributions
bins = np.linspace(min(penguins['body_mass_g']), max(penguins['body_mass_g']), 50)
plt.figure(figsize=(15, 5))
for species in penguins["species"].unique():
hist = np.histogram(penguins[penguins["species"] == species]["body_mass_g"], bins=bins)[0]
plt.plot(bins[:-1]+np.diff(bins)/2, hist, label=species)
plt.legend(title="species")
plt.xlabel("body mass [g]")
plt.ylabel("count")
plt.grid(alpha=0.5)
plt.title("Penguins body mass\nFrequency polygons")
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
freqpoly_mass <- ggplot(mydata)+
geom_freqpoly(aes(x=body_mass_g, color=species), bins=50)+
labs(title = "Penguins Body Mass", subtitle = "Frequence Polygons")+
ylab("Count")+theme_light()
freqpoly_mass
Courbe $x, y$,
en $x$ la valeur de la variable $V$, en $y$ la probabilité empirique d'avoir dans la population un individu pour lequel $V \leqslant x$
i.e. c'est la fonction :
$F_V(x) = \mathbb{P}(V\leqslant x)$
Permet de superposer les CDF de sous groupes de la population. Ici : les espèces des manchots.
plt.figure(figsize=(15, 5))
ax=plt.subplot()
plt.xlim((penguins["body_mass_g"].min(), penguins["body_mass_g"].max()))
penguins.plot(kind="hist", ax=ax, column="body_mass_g", density=True, histtype="step", cumulative=True, bins=len(penguins),
title="Penguins Body Mass\nCumulative Distribution Function", ylabel="Probability", legend=False)
ax.set_xlabel("body mass [g]")
plt.grid(alpha=0.5)
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
plot_mass <- ggplot(mydata)+
stat_ecdf(aes(x= body_mass_g),color="darkorchid4")+
labs(title = "Penguins Body Mass", subtitle = "Cumulative Distribution Function")+
ylab("Probability")+theme_light()
plot_mass
plt.figure(figsize=(15, 5))
for species in penguins["species"].unique():
plt.ecdf(penguins[penguins["species"] == species]["body_mass_g"], label=species)
plt.legend(title="species")
plt.xlabel("body mass [g]")
plt.ylabel("count")
plt.title("Penguins Body Mass\nCumulative Distribution Function")
plt.grid(alpha=0.5)
def ecdf(x, vmin, vmax,**kwargs):
x = np.asarray(x)
argsort = np.argsort(x)
x = x[argsort]
cum_weights = (1 + np.arange(len(x))) / len(x)
line, = plt.plot([vmin, x[0], *x, vmax], [0, 0, *cum_weights, 1],
drawstyle="steps-post", **kwargs)
return line
plt.figure(figsize=(15, 5))
vmin = penguins["body_mass_g"].min()
vmax = penguins["body_mass_g"].max()
for species in penguins["species"].unique():
ecdf(penguins[penguins["species"] == species]["body_mass_g"], vmin=vmin, vmax=vmax, label=species)
plt.legend(title="species")
plt.xlabel("body mass [g]")
plt.ylabel("count")
plt.title("Penguins Body Mass\nCumulative Distribution Function")
plt.grid(alpha=0.5)
library(palmerpenguins)
data(package = 'palmerpenguins')
mydata <- penguins
plot_mass <- ggplot(mydata)+
stat_ecdf(aes(x= body_mass_g,color=species))+ #on affecte la couleur à la variable modale
labs(title = "Penguins Body Mass", subtitle = "Cumulative Distribution Function")+
ylab("Probability")+theme_light()
plot_mass
Les distributions très asymétriques et très étendues sont délicates à résumer.
Les indicateurs traditionnels sont plus efficaces lorsque la variabilité des valeurs est moindre, et leur distribution plus symétrique.
e.g. Considérer la population moyenne des villes de France a-t’elle du sens ?
Pour mieux voir la distribution et les écarts, on trace la taille des villes en fonction de leur rang
Appliquer une transformation monotone, bijective et inversible qui “applatisse” la distribution.
\(\implies\) mesure de façon plus robuste tendance, dispersion et forme
Ici : le logarithme décimal