On importe les données :
library(readxl)
data <- read_excel("data.xlsx",
sheet = "Feuil1")
data$Taille <- as.numeric(data$Taille)
data$BMI <- as.numeric(data$BMI)
str(data)
## tibble [144 × 14] (S3: tbl_df/tbl/data.frame)
## $ Age : num [1:144] 15 17 20 20 18 13 13 14 20 17 ...
## $ Nomination: chr [1:144] "GR" "GR" "GR" "GR" ...
## $ Taille : num [1:144] 1.56 1.63 1.67 1.67 1.69 1.64 1.63 1.56 1.67 1.72 ...
## $ Poids : num [1:144] 47 44 52 61 54 47 44 47 52 57 ...
## $ BMI : num [1:144] 19.3 16.5 18.6 21.8 18.9 17.4 16.5 19.3 18.6 19 ...
## $ ES : num [1:144] 28 21 32 32 31 31 28 28 30 30 ...
## $ BES : num [1:144] 46 40 56 43 51 60 63 63 69 53 ...
## $ BEApp : num [1:144] 23 19 24 19 24 26 29 26 33 27 ...
## $ BEPoi : num [1:144] 16 14 21 12 18 26 26 28 25 19 ...
## $ BEAtt : num [1:144] 7 7 11 12 9 8 8 9 11 7 ...
## $ EAT : num [1:144] 2 5 1 31 31 1 18 5 8 11 ...
## $ Diete : num [1:144] 2 4 1 23 23 1 17 1 7 4 ...
## $ Boulimie : num [1:144] 0 0 0 4 5 0 1 0 0 0 ...
## $ Control : num [1:144] 0 1 0 4 3 0 0 4 1 7 ...
head(data)
## # A tibble: 6 × 14
## Age Nomination Taille Poids BMI ES BES BEApp BEPoi BEAtt EAT Diete
## <dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 15 GR 1.56 47 19.3 28 46 23 16 7 2 2
## 2 17 GR 1.63 44 16.5 21 40 19 14 7 5 4
## 3 20 GR 1.67 52 18.6 32 56 24 21 11 1 1
## 4 20 GR 1.67 61 21.8 32 43 19 12 12 31 23
## 5 18 GR 1.69 54 18.9 31 51 24 18 9 31 23
## 6 13 GR 1.64 47 17.4 31 60 26 26 8 1 1
## # ℹ 2 more variables: Boulimie <dbl>, Control <dbl>
On remarque qu’il y a 144 lignes et 14 variables dans le tableau.
On fait un tableau récapitulatif des variables :
tableau_coches <- data.frame(
Variable = c("Age", "Nomination", "Taille", "Poids", "BMI", "ES", "BES", "BEApp", "BEPoi", "BEAtt", "EAT", "Diete", "Boulimie", "Control"),
Qual_Nom = c("", "X", "", "", "", "", "", "", "", "", "", "", "", ""),
Qual_Ord = c("", "", "", "", "", "", "", "", "", "", "", "", "", ""),
Quant_Disc = c("X", "", "", "", "", "X", "X", "X", "X", "X", "X", "X", "X", "X"),
Quant_Cont = c("", "", "X", "X", "X", "", "", "", "", "", "", "", "", ""),
Regroup = c("", "X", "", "", "", "", "", "", "", "", "", "", "", ""),
Explic = c("X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X"),
Reponse = c("", "", "", "", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X")
)
print(tableau_coches)
## Variable Qual_Nom Qual_Ord Quant_Disc Quant_Cont Regroup Explic Reponse
## 1 Age X X
## 2 Nomination X X X
## 3 Taille X X
## 4 Poids X X
## 5 BMI X X X
## 6 ES X X X
## 7 BES X X X
## 8 BEApp X X X
## 9 BEPoi X X X
## 10 BEAtt X X X
## 11 EAT X X X
## 12 Diete X X X
## 13 Boulimie X X X
## 14 Control X X X
On transforme la variable “Nomination” en variable qualitative :
library(dplyr)
data <- data %>%
mutate(Nomination = factor(Nomination))
summary(data)
## Age Nomination Taille Poids BMI
## Min. :13.00 GR:61 Min. :1.480 Min. :38.00 Min. :16.20
## 1st Qu.:15.00 GT:41 1st Qu.:1.610 1st Qu.:47.00 1st Qu.:17.88
## Median :16.00 NS:42 Median :1.650 Median :52.00 Median :18.90
## Mean :16.17 Mean :1.647 Mean :51.89 Mean :19.07
## 3rd Qu.:17.00 3rd Qu.:1.690 3rd Qu.:56.00 3rd Qu.:19.80
## Max. :22.00 Max. :1.790 Max. :70.00 Max. :24.20
## ES BES BEApp BEPoi
## Min. :16.00 Min. :12.00 Min. : 3.00 Min. : 1.00
## 1st Qu.:26.00 1st Qu.:35.75 1st Qu.:13.00 1st Qu.: 9.00
## Median :29.00 Median :46.00 Median :17.00 Median :15.50
## Mean :28.57 Mean :45.90 Mean :18.17 Mean :15.03
## 3rd Qu.:32.00 3rd Qu.:56.00 3rd Qu.:24.25 3rd Qu.:21.00
## Max. :39.00 Max. :79.00 Max. :40.00 Max. :30.00
## BEAtt EAT Diete Boulimie
## Min. : 3.00 Min. : 1.00 Min. : 1.000 Min. : 0.000
## 1st Qu.: 8.75 1st Qu.: 5.00 1st Qu.: 2.000 1st Qu.: 0.000
## Median :11.00 Median :10.00 Median : 6.000 Median : 1.000
## Mean :12.70 Mean :12.73 Mean : 7.875 Mean : 2.167
## 3rd Qu.:18.00 3rd Qu.:17.00 3rd Qu.:11.000 3rd Qu.: 4.000
## Max. :20.00 Max. :45.00 Max. :33.000 Max. :11.000
## Control
## Min. : 0.000
## 1st Qu.: 0.000
## Median : 2.000
## Mean : 2.694
## 3rd Qu.: 4.000
## Max. :13.000
colSums(is.na(data))
## Age Nomination Taille Poids BMI ES BES
## 0 0 0 0 0 0 0
## BEApp BEPoi BEAtt EAT Diete Boulimie Control
## 0 0 0 0 0 0 0
Il ne manque aucune valeur dans le tableau transformé mais s’il y en avait il faudrait calculer/déduire les valeurs manquantes à partir des autres. Par exemple si il manquait une valeur mais que nous avions la moyenne finale, nous pourrions, grâce aux autres valeurs, calculer celle qui manque.
On construit un tableau d’effectifs et de fréquences pour la variable Nomination en identifiant le mode de cette dernière :
effectifs <- table(data$Nomination)
frequences <- round(100 * effectifs / sum(effectifs), 2)
tableau_nom <- data.frame(
Nomination = names(effectifs),
Effectif = as.vector(effectifs),
Frequence_percent = as.vector(frequences)
)
mode_nom <- names(effectifs)[which.max(effectifs)]
tableau_nom$Mode <- ""
tableau_nom$Mode[tableau_nom$Nomination == mode_nom] <- "X"
print(tableau_nom)
## Nomination Effectif Frequence_percent Mode
## 1 GR 61 42.36 X
## 2 GT 41 28.47
## 3 NS 42 29.17
On représente graphiquement la distribution de Nomination avec un diagramme en barres :
library(ggplot2)
ggplot(data, aes(x = Nomination)) +
geom_bar(fill = "#2171b5") +
labs(title = "Distribution de la variable Nomination",
x = "Nomination",
y = "Effectif") +
theme_minimal()
On représente graphiquement la distribution de Nomination avec un diagramme en camembert en indiquant les pourcentages pour chaque nomination :
library(scales)
data_pie <- data %>%
count(Nomination) %>%
mutate(
prop = n / sum(n),
labels = scales::percent(prop, 0.1)
)
ggplot(data_pie, aes(x = "", y = prop, fill = Nomination)) +
geom_col(width = 1) +
geom_text(
aes(label = labels),
position = position_stack(vjust = 0.5),
size = 4
) +
coord_polar("y", start = 0) +
labs(
title = "Répartition des nominations",
fill = "Nomination"
) +
theme_void() +
scale_fill_brewer(palette = "Set2")
On crée une variable qualitative BMI_class à partir de BMI selon les classes suivantes :
data <- data %>%
mutate(
BMI_classe = cut(
BMI,
breaks = c(-Inf, 18.5, 22, Inf),
labels = c("Insuffisance pondérale",
"Corpulence normale",
"Surpoids/obésité")
)
)
str(data$BMI_classe)
## Factor w/ 3 levels "Insuffisance pondérale",..: 2 1 2 2 2 1 1 2 2 2 ...
table(data$BMI_classe)
##
## Insuffisance pondérale Corpulence normale Surpoids/obésité
## 53 80 11
On crée de manière similaire la variable qualitative Age_classe à partir de âge selon les critères suivants :
data <- data %>%
mutate(
Age_classe = cut(
Age,
breaks = c(13, 16, 19, 23),
labels = c("13 - 15 ans", "16 - 18 ans", "19 - 22 ans"),
right = FALSE
)
)
str(data$Age_classe)
## Factor w/ 3 levels "13 - 15 ans",..: 1 2 3 3 2 1 1 1 3 2 ...
table(data$Age_classe)
##
## 13 - 15 ans 16 - 18 ans 19 - 22 ans
## 57 76 11
On crée similairement EAT_cat à partir de EAT selon les critères :
data <- data %>%
mutate(
EAT_cat = cut(
EAT,
breaks = c(-Inf, 10, 20, Inf),
labels = c("Score bas", "Score modéré", "Score élevé")
)
)
table(data$EAT_cat)
##
## Score bas Score modéré Score élevé
## 73 45 26
prop.table(table(data$EAT_cat))
##
## Score bas Score modéré Score élevé
## 0.5069444 0.3125000 0.1805556
On réalise pour chaque variable qualitative :
eff_BMI <- table(data$BMI_classe)
freq_BMI <- round(100 * eff_BMI / sum(eff_BMI), 2)
tab_BMI <- data.frame(
BMI_classe = names(eff_BMI),
Effectif = as.vector(eff_BMI),
Frequence_percent = as.vector(freq_BMI)
)
mode_BMI <- names(eff_BMI)[which.max(eff_BMI)]
tab_BMI$Mode <- ""
tab_BMI$Mode[tab_BMI$BMI_classe == mode_BMI] <- "X"
print(tab_BMI)
## BMI_classe Effectif Frequence_percent Mode
## 1 Insuffisance pondérale 53 36.81
## 2 Corpulence normale 80 55.56 X
## 3 Surpoids/obésité 11 7.64
ggplot(data, aes(x = BMI_classe)) +
geom_bar(fill = "#2171b5") +
labs(title = "Classe d'IMC", x = "Classe", y = "Effectif") +
theme_minimal()
data_pie_BMI <- data %>%
count(BMI_classe) %>%
mutate(
prop = n / sum(n),
labels = percent(prop, 0.1)
)
ggplot(data_pie_BMI, aes(x = "", y = prop, fill = BMI_classe)) +
geom_col(width = 1) +
geom_text(aes(label = labels),
position = position_stack(vjust = 0.5),
size = 4) +
coord_polar("y", start = 0) +
labs(title = "Répartition des classes d'IMC",
fill = "Classe d'IMC") +
theme_void() +
scale_fill_brewer(palette = "Set2")
eff_Age <- table(data$Age_classe)
freq_Age <- round(100 * eff_Age / sum(eff_Age), 2)
tab_Age <- data.frame(
Age_classe = names(eff_Age),
Effectif = as.vector(eff_Age),
Frequence_percent = as.vector(freq_Age)
)
mode_Age <- names(eff_Age)[which.max(eff_Age)]
tab_Age$Mode <- ""
tab_Age$Mode[tab_Age$Age_classe == mode_Age] <- "X"
print(tab_Age)
## Age_classe Effectif Frequence_percent Mode
## 1 13 - 15 ans 57 39.58
## 2 16 - 18 ans 76 52.78 X
## 3 19 - 22 ans 11 7.64
ggplot(data, aes(x = Age_classe)) +
geom_bar(fill = "#2171b5") +
labs(title = "Classe d'âge", x = "Classe", y = "Effectif") +
theme_minimal()
data_pie_Age <- data %>%
count(Age_classe) %>%
mutate(
prop = n / sum(n),
labels = percent(prop, 0.1)
)
ggplot(data_pie_Age, aes(x = "", y = prop, fill = Age_classe)) +
geom_col(width = 1) +
geom_text(aes(label = labels),
position = position_stack(vjust = 0.5),
size = 4) +
coord_polar("y", start = 0) +
labs(title = "Répartition des classes d'âge",
fill = "Classe d'âge") +
theme_void() +
scale_fill_brewer(palette = "Set2")
eff_EAT <- table(data$EAT_cat)
freq_EAT <- round(100 * eff_EAT / sum(eff_EAT), 2)
tab_EAT <- data.frame(
EAT_cat = names(eff_EAT),
Effectif = as.vector(eff_EAT),
Frequence_percent = as.vector(freq_EAT)
)
mode_EAT <- names(eff_EAT)[which.max(eff_EAT)]
tab_EAT$Mode <- ""
tab_EAT$Mode[tab_EAT$EAT_cat == mode_EAT] <- "X"
print(tab_EAT)
## EAT_cat Effectif Frequence_percent Mode
## 1 Score bas 73 50.69 X
## 2 Score modéré 45 31.25
## 3 Score élevé 26 18.06
ggplot(data, aes(x = EAT_cat)) +
geom_bar(fill = "#2171b5") +
labs(title = "Score EAT (categories)", x = "Catégorie", y = "Effectif") +
theme_minimal()
data_pie_EAT <- data %>%
count(EAT_cat) %>%
mutate(
prop = n / sum(n),
labels = percent(prop, 0.1)
)
ggplot(data_pie_EAT, aes(x = "", y = prop, fill = EAT_cat)) +
geom_col(width = 1) +
geom_text(aes(label = labels),
position = position_stack(vjust = 0.5),
size = 4) +
coord_polar("y", start = 0) +
labs(title = "Répartition des catégories de score EAT",
fill = "Score EAT") +
theme_void() +
scale_fill_brewer(palette = "Set2")
On construit les tableaux croisés suivants :
Pour chaque tableau, on :
tab_BMI_Nom <- table(data$BMI_classe, data$Nomination)
tab_BMI_Nom
##
## GR GT NS
## Insuffisance pondérale 26 13 14
## Corpulence normale 35 20 25
## Surpoids/obésité 0 8 3
prop.table(tab_BMI_Nom, margin = 1)
##
## GR GT NS
## Insuffisance pondérale 0.4905660 0.2452830 0.2641509
## Corpulence normale 0.4375000 0.2500000 0.3125000
## Surpoids/obésité 0.0000000 0.7272727 0.2727273
chisq_BMI_Nom <- chisq.test(tab_BMI_Nom)
chisq_BMI_Nom$p.value
## [1] 0.008237198
p.value < 0.05 donc on rejette H0 et on conclut que les variables ne sont pas indépendantes. Cela signifie que la répartition des classes d’IMC n’est pas la même selon les groupes de Nomination, certains groupes comportant proportionnellement plus d’élèves en insuffisance pondérale ou en surpoids que d’autres.
tab_EAT_Nom <- table(data$EAT_cat, data$Nomination)
tab_EAT_Nom
##
## GR GT NS
## Score bas 22 36 15
## Score modéré 16 5 24
## Score élevé 23 0 3
prop.table(tab_EAT_Nom, margin = 1)
##
## GR GT NS
## Score bas 0.3013699 0.4931507 0.2054795
## Score modéré 0.3555556 0.1111111 0.5333333
## Score élevé 0.8846154 0.0000000 0.1153846
chisq_EAT_Nom <- chisq.test(tab_EAT_Nom)
chisq_EAT_Nom$p.value
## [1] 8.294902e-11
p.value < 0.05 donc on rejette H0 et on conclut que les variables ne sont pas indépendantes. On met donc en évidence des différences de profils de score EAT entre les groupes de Nomination, certains groupes présentant davantage de scores élevés ou modérés que d’autres.
tab_EAT_BMI <- table(data$EAT_cat, data$BMI_classe)
tab_EAT_BMI
##
## Insuffisance pondérale Corpulence normale Surpoids/obésité
## Score bas 26 39 8
## Score modéré 14 28 3
## Score élevé 13 13 0
prop.table(tab_EAT_BMI, margin = 1)
##
## Insuffisance pondérale Corpulence normale Surpoids/obésité
## Score bas 0.35616438 0.53424658 0.10958904
## Score modéré 0.31111111 0.62222222 0.06666667
## Score élevé 0.50000000 0.50000000 0.00000000
chisq_EAT_BMI <- chisq.test(tab_EAT_BMI)
chisq_EAT_BMI$p.value
## [1] 0.2566082
p.value >= 0.05 donc on ne rejette pas H0 et les variables sont donc indépendantes. Dans cet échantillon, les catégories de BMI et les catégories de score EAT apparaissent donc indépendantes, ce qui suggère qu’un BMI plus élevé n’est pas forcément associé à un score EAT plus élevé.
Pour chacune des variables Age, Taille, Poids, BMI, EAT, on calcule :
vars_quanti <- c("Age", "Taille", "Poids", "BMI", "EAT")
resume_quanti <- data %>%
select(all_of(vars_quanti)) %>%
summarise(
across(
everything(),
list(
moy = ~mean(. , na.rm = TRUE),
med = ~median(. , na.rm = TRUE),
var = ~var(. , na.rm = TRUE),
sd = ~sd(. , na.rm = TRUE),
q1 = ~quantile(., 0.25, na.rm = TRUE),
q3 = ~quantile(., 0.75, na.rm = TRUE),
min = ~min(. , na.rm = TRUE),
max = ~max(. , na.rm = TRUE)
)
)
)
t(resume_quanti)
## [,1]
## Age_moy 16.173611111
## Age_med 16.000000000
## Age_var 3.640977078
## Age_sd 1.908134450
## Age_q1 15.000000000
## Age_q3 17.000000000
## Age_min 13.000000000
## Age_max 22.000000000
## Taille_moy 1.647152778
## Taille_med 1.650000000
## Taille_var 0.003461067
## Taille_sd 0.058830837
## Taille_q1 1.610000000
## Taille_q3 1.690000000
## Taille_min 1.480000000
## Taille_max 1.790000000
## Poids_moy 51.888888889
## Poids_med 52.000000000
## Poids_var 35.260295260
## Poids_sd 5.938037998
## Poids_q1 47.000000000
## Poids_q3 56.000000000
## Poids_min 38.000000000
## Poids_max 70.000000000
## BMI_moy 19.075000000
## BMI_med 18.900000000
## BMI_var 2.795874126
## BMI_sd 1.672086758
## BMI_q1 17.875000000
## BMI_q3 19.800000000
## BMI_min 16.200000000
## BMI_max 24.200000000
## EAT_moy 12.729166667
## EAT_med 10.000000000
## EAT_var 97.877185315
## EAT_sd 9.893289914
## EAT_q1 5.000000000
## EAT_q3 17.000000000
## EAT_min 1.000000000
## EAT_max 45.000000000
Globalement, les indicateurs de position et de dispersion obtenus sont cohérents avec le contexte de l’étude (adolescents) et ne mettent pas en évidence de valeurs complètement aberrantes.
Pour Age, BMI et EAT, on trace les histogrammes adaptés (nombre de classes raisonnable). Pour chaque histogramme, on commente :
ggplot(data, aes(x = Age)) +
geom_histogram(color = "black", fill = "#2171b5", bins = 10) +
labs(title = "Histogramme de l'âge", x = "Age", y = "Effectif") +
theme_minimal()
ggplot(data, aes(x = BMI)) +
geom_histogram(color = "black", fill = "#fb9a99", bins = 10) +
labs(title = "Histogramme du BMI", x = "BMI", y = "Effectif") +
theme_minimal()
ggplot(data, aes(x = EAT)) +
geom_histogram(color = "black", fill = "#6a3d9a", bins = 10) +
labs(title = "Histogramme du score EAT", x = "EAT", y = "Effectif") +
theme_minimal()
Les histogrammes permettent de visualiser la forme des distributions de Age, BMI et EAT et de repérer d’éventuelles asymétries ou valeurs extrêmes, en cohérence avec les indicateurs calculés à la question précédente.
On trace des boîtes à moustaches pour BMI et EAT (boxplots simples, sans groupe). Puis on rappelle ce que représentent :
ggplot(data, aes(y = BMI)) +
geom_boxplot(fill = "#2171b5") +
labs(title = "Boxplot du BMI", y = "BMI") +
theme_minimal()
ggplot(data, aes(y = EAT)) +
geom_boxplot(fill = "#fb9a99") +
labs(title = "Boxplot du score EAT", y = "EAT") +
theme_minimal()
Les boxplots montrent que la dispersion de BMI reste modérée autour de la médiane, tandis que les scores EAT peuvent présenter une variabilité plus importante et quelques valeurs atypiques.
x <- data$BMI
x <- x[!is.na(x)]
n <- length(x)
xmin <- min(x)
xmax <- max(x)
k_yule <- 2.5 * n^(1/4)
k_sturges <- 1 + 3.3 * log10(n)
k_yule
## [1] 8.660254
k_sturges
## [1] 8.122596
Ces deux règles donnent des valeurs proches pour le nombre de classes ; on retient un nombre entier de classes k en s’appuyant sur ces approximations.
k <- round(k_sturges)
L <- xmax - xmin
h <- L / k
bornes <- seq(from = xmin, to = xmax, length.out = k + 1)
bornes
## [1] 16.2 17.2 18.2 19.2 20.2 21.2 22.2 23.2 24.2
On obtient ainsi une largeur de classe constante et un système de bornes qui couvre l’ensemble des valeurs observées de BMI.
classes <- cut(x, breaks = bornes, right = FALSE, include.lowest = TRUE)
tab_eff <- table(classes)
tab_freq <- prop.table(tab_eff)
tab_freq_cum <- cumsum(tab_freq)
tab_classes <- data.frame(
Classe = names(tab_eff),
Effectif = as.vector(tab_eff),
Frequence = round(100 * as.vector(tab_freq), 2),
Frequence_cumulee = round(100 * as.vector(tab_freq_cum), 2)
)
tab_classes
## Classe Effectif Frequence Frequence_cumulee
## 1 [16.2,17.2) 13 9.03 9.03
## 2 [17.2,18.2) 33 22.92 31.94
## 3 [18.2,19.2) 37 25.69 57.64
## 4 [19.2,20.2) 33 22.92 80.56
## 5 [20.2,21.2) 10 6.94 87.50
## 6 [21.2,22.2) 9 6.25 93.75
## 7 [22.2,23.2) 6 4.17 97.92
## 8 [23.2,24.2] 3 2.08 100.00
Le tableau de fréquences par classes permet de voir dans quelles classes de BMI se concentrent la majorité des sujets et comment se répartissent les fréquences cumulées.
df_bmi <- data.frame(BMI = x)
ggplot(df_bmi, aes(x = BMI)) +
geom_histogram(
breaks = bornes,
color = "black",
fill = "#2171b5",
closed = "left"
) +
labs(title = "Histogramme du BMI (classes Yule/Sturges)",
x = "BMI", y = "Effectif") +
theme_minimal()
L’histogramme basé sur ces classes spécifiques de BMI est globalement cohérent avec l’histogramme “par défaut” mais rend explicite le choix du nombre de classes et de leurs bornes.
On représente graphiquement la distribution de BMI et de EAT en fonction de Nomination à l’aide de boîtes à moustaches, afin de comparer les médianes, la dispersion et les valeurs extrêmes entre groupes.
ggplot(data, aes(x = Nomination, y = BMI)) +
geom_boxplot(fill = "#2171b5") +
labs(title = "BMI selon la nomination",
x = "Nomination", y = "BMI") +
theme_minimal()
ggplot(data, aes(x = Nomination, y = EAT)) +
geom_boxplot(fill = "#fb9a99") +
labs(title = "EAT selon la nomination",
x = "Nomination", y = "Score EAT") +
theme_minimal()
descr_nom <- data %>%
group_by(Nomination) %>%
summarise(
moy_BMI = mean(BMI, na.rm = TRUE),
sd_BMI = sd(BMI, na.rm = TRUE),
moy_EAT = mean(EAT, na.rm = TRUE),
sd_EAT = sd(EAT, na.rm = TRUE),
.groups = "drop"
)
descr_nom
## # A tibble: 3 × 5
## Nomination moy_BMI sd_BMI moy_EAT sd_EAT
## <fct> <dbl> <dbl> <dbl> <dbl>
## 1 GR 18.5 1.25 17.2 12.4
## 2 GT 19.7 2.04 5.95 4.29
## 3 NS 19.2 1.58 12.9 4.71
Ce tableau récapitule, pour chaque groupe de Nomination, les moyennes et écarts‑types de BMI et de EAT, ce qui permet de comparer les niveaux moyens et la variabilité des scores entre groupes.
On étudie la relation entre BMI et EAT à l’aide d’un nuage de points et du coefficient de corrélation de Pearson.
ggplot(data, aes(x = BMI, y = EAT)) +
geom_point(color = "#2171b5") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
labs(title = "Relation entre BMI et EAT",
x = "BMI", y = "Score EAT") +
theme_minimal()
cor_BMI_EAT <- cor(data$BMI, data$EAT, use = "complete.obs")
cor_BMI_EAT
## [1] -0.1394908
vars_corr <- data %>%
select(BMI, EAT, Diete, Boulimie, Control)
cor_matrix <- cor(vars_corr, use = "complete.obs")
cor_matrix
## BMI EAT Diete Boulimie Control
## BMI 1.00000000 -0.1394908 -0.0585915 -0.05368277 -0.2931693
## EAT -0.13949077 1.0000000 0.9201260 0.71505627 0.6260825
## Diete -0.05859150 0.9201260 1.0000000 0.51038527 0.3359026
## Boulimie -0.05368277 0.7150563 0.5103853 1.00000000 0.3956766
## Control -0.29316931 0.6260825 0.3359026 0.39567657 1.0000000
La matrice de corrélation permet d’identifier les paires de variables les plus associées (positivement ou négativement) parmi BMI, EAT, Diete, Boulimie et Control. On observe notamment une corrélation positive marquée entre EAT et Diete, ainsi qu’entre EAT et Boulimie, ce qui reflète la proximité de ces dimensions de comportement alimentaire.
On ajuste un modèle de régression linéaire simple de EAT en fonction de BMI et on interprète les paramètres estimés et le R².
mod1 <- lm(EAT ~ BMI, data = data)
summary(mod1)
##
## Call:
## lm(formula = EAT ~ BMI, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -13.937 -7.590 -1.667 4.531 31.053
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 28.4723 9.4143 3.024 0.00296 **
## BMI -0.8253 0.4917 -1.679 0.09542 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 9.831 on 142 degrees of freedom
## Multiple R-squared: 0.01946, Adjusted R-squared: 0.01255
## F-statistic: 2.818 on 1 and 142 DF, p-value: 0.09542
Ce modèle permet juste de voir s’il y a une tendance linéaire entre BMI et EAT et combien de variabilité de EAT est expliquée par BMI.
Ce modèle ajoute Diete, Boulimie et Control à BMI pour mieux prendre en compte les différents aspects du comportement alimentaire.
mod2 <- lm(EAT ~ BMI + Diete + Boulimie + Control, data = data)
summary(mod2)
##
## Call:
## lm(formula = EAT ~ BMI + Diete + Boulimie + Control, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.96351 -0.00396 0.00804 0.01687 0.03902
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.164255 0.085660 -1.918 0.0572 .
## BMI 0.007595 0.004367 1.739 0.0842 .
## Diete 1.000676 0.001192 839.361 <2e-16 ***
## Boulimie 1.001083 0.003529 283.703 <2e-16 ***
## Control 1.001769 0.002749 364.446 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.08326 on 139 degrees of freedom
## Multiple R-squared: 0.9999, Adjusted R-squared: 0.9999
## F-statistic: 5.048e+05 on 4 and 139 DF, p-value: < 2.2e-16
Le modèle multiple prend en compte simultanément plusieurs dimensions du comportement alimentaire et améliore généralement l’ajustement par rapport au modèle simple. Dans ce cadre, les variables Diete et Boulimie ressortent comme les prédicteurs les plus fortement associés au score EAT, tandis que l’effet de BMI devient plus faible une fois ces dimensions contrôlées.
par(mfrow = c(2, 2))
plot(mod2)
par(mfrow = c(1, 1))
shapiro.test(residuals(mod2))
##
## Shapiro-Wilk normality test
##
## data: residuals(mod2)
## W = 0.16103, p-value < 2.2e-16
Les graphiques de diagnostic et le test de Shapiro-Wilk permettent de vérifier que les hypothèses du modèle linéaire multiple sont raisonnablement satisfaites.
On réalise une ANOVA à un facteur pour tester si le score EAT diffère selon les groupes de Nomination.
anova_mod <- aov(EAT ~ Nomination, data = data)
summary(anova_mod)
## Df Sum Sq Mean Sq F value Pr(>F)
## Nomination 2 3102 1550.9 20.07 2.14e-08 ***
## Residuals 141 10895 77.3
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
TukeyHSD(anova_mod)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = EAT ~ Nomination, data = data)
##
## $Nomination
## diff lwr upr p adj
## GT-GR -11.245502 -15.450399 -7.0406047 0.0000000
## NS-GR -4.339578 -8.514431 -0.1647256 0.0395993
## NS-GT 6.905923 2.334677 11.4771694 0.0013703
Le test de Tukey précise quelles paires de groupes de Nomination présentent des différences significatives de score EAT. On met ainsi en évidence que certains groupes de Nomination ont un score EAT moyen significativement plus élevé ou plus faible que d’autres, ce qui confirme l’existence de différences de comportements alimentaires entre groupes.
vars_acp <- data %>%
select(BMI, EAT, Diete, Boulimie, Control) %>%
na.omit()
X <- scale(vars_acp)
cor(vars_acp)
## BMI EAT Diete Boulimie Control
## BMI 1.00000000 -0.1394908 -0.0585915 -0.05368277 -0.2931693
## EAT -0.13949077 1.0000000 0.9201260 0.71505627 0.6260825
## Diete -0.05859150 0.9201260 1.0000000 0.51038527 0.3359026
## Boulimie -0.05368277 0.7150563 0.5103853 1.00000000 0.3956766
## Control -0.29316931 0.6260825 0.3359026 0.39567657 1.0000000
On prépare ainsi une matrice de travail standardisée contenant uniquement les variables quantitatives retenues pour l’ACP.
acp <- prcomp(X, center = FALSE, scale. = FALSE)
summary(acp)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5
## Standard deviation 1.6830 1.0386 0.7684 0.7060 0.006494
## Proportion of Variance 0.5665 0.2157 0.1181 0.0997 0.000010
## Cumulative Proportion 0.5665 0.7822 0.9003 1.0000 1.000000
L’ACP sert ici à résumer les cinq variables (BMI, EAT, Diete, Boulimie, Control) sur quelques axes plus faciles à lire.
plot(acp, type = "l", main = "Scree plot ACP")
library(factoextra)
fviz_pca_var(acp, col.var = "contrib")
fviz_pca_ind(acp, geom.ind = "point")
Le scree plot, le cercle des corrélations et la carte des individus permettent de voir quels axes sont importants, comment les variables se regroupent et comment les élèves se distribuent sur ces axes.
coords <- acp$x[, 1:3]
d <- dist(coords)
cah <- hclust(d, method = "ward.D2")
plot(cah, labels = FALSE, main = "Dendrogramme (CAH, Ward)")
K <- 3
cluster_CAH <- cutree(cah, k = K)
data_clust <- data %>%
filter(complete.cases(BMI, EAT, Diete, Boulimie, Control)) %>%
mutate(cluster_CAH = factor(cluster_CAH))
descr_clusters <- data_clust %>%
group_by(cluster_CAH) %>%
summarise(
n = n(),
BMI_moy = mean(BMI),
EAT_moy = mean(EAT),
Diete_moy = mean(Diete),
Boulimie_moy = mean(Boulimie),
Control_moy = mean(Control),
.groups = "drop"
)
descr_clusters
## # A tibble: 3 × 7
## cluster_CAH n BMI_moy EAT_moy Diete_moy Boulimie_moy Control_moy
## <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 51 18.2 5.04 3.06 0.451 1.55
## 2 2 22 18.4 31.6 20.2 5.41 6
## 3 3 71 19.9 12.4 7.52 2.39 2.49
Ce tableau donne, pour chaque cluster, le nombre d’élèves et les moyennes des variables BMI, EAT, Diete, Boulimie et Control. On obtient ainsi des groupes avec des scores plutôt faibles ou plutôt élevés sur ces variables.
table(data_clust$cluster_CAH, data_clust$Nomination)
##
## GR GT NS
## 1 23 21 7
## 2 21 0 1
## 3 17 20 34
chisq.test(table(data_clust$cluster_CAH, data_clust$Nomination))
##
## Pearson's Chi-squared test
##
## data: table(data_clust$cluster_CAH, data_clust$Nomination)
## X-squared = 46.845, df = 4, p-value = 1.642e-09
table(data_clust$cluster_CAH, data_clust$BMI_classe)
##
## Insuffisance pondérale Corpulence normale Surpoids/obésité
## 1 29 22 0
## 2 11 11 0
## 3 13 47 11
chisq.test(table(data_clust$cluster_CAH, data_clust$BMI_classe))
##
## Pearson's Chi-squared test
##
## data: table(data_clust$cluster_CAH, data_clust$BMI_classe)
## X-squared = 27.509, df = 4, p-value = 1.568e-05
table(data_clust$cluster_CAH, data_clust$EAT_cat)
##
## Score bas Score modéré Score élevé
## 1 46 5 0
## 2 0 0 22
## 3 27 40 4
chisq.test(table(data_clust$cluster_CAH, data_clust$EAT_cat))
##
## Pearson's Chi-squared test
##
## data: table(data_clust$cluster_CAH, data_clust$EAT_cat)
## X-squared = 154.87, df = 4, p-value < 2.2e-16
Les tableaux croisés et tests du χ² permettent d’étudier le lien entre les clusters obtenus et les variables qualitatives Nomination, BMI_classe et EAT_cat.
set.seed(123)
km <- kmeans(coords, centers = K, nstart = 20)
km$cluster
## [1] 3 3 3 2 2 3 3 3 3 3 3 3 2 2 1 3 3 3 3 3 2 3 3 1 1 2 3 3 3 1 3 3 3 3 3 3 2
## [38] 2 2 2 2 2 2 2 2 2 3 3 3 2 2 2 2 2 1 2 2 2 2 2 2 3 3 1 3 1 3 1 1 2 1 3 3 1
## [75] 3 1 1 2 1 3 3 3 3 3 2 3 3 2 1 3 3 3 3 3 2 1 2 2 1 3 1 2 3 3 3 3 3 1 3 3 1
## [112] 1 3 1 3 3 1 1 1 3 3 1 3 1 3 3 3 3 1 1 3 1 3 3 1 3 3 3 1 1 3 3 1 3
Globalement, les élèves ont un BMI dans la zone de corpulence normale, avec peu de surpoids. Les scores EAT, Diete, Boulimie et Control sont en revanche très variables d’un élève à l’autre. Les corrélations et les régressions montrent surtout un lien entre EAT, Diete et Boulimie, alors que BMI explique peu de choses à lui seul. L’ANOVA suggère des différences de score EAT entre certains groupes de Nomination. Enfin, l’ACP et la classification regroupent les élèves en quelques groupes ayant des profils de scores plutôt faibles ou plutôt élevés.