Introduction

Dans ce projet engageant de 7 à 9 heures, nous allons endosser le rôle d’analystes de données de santé débutants au sein d’une organisation de premier plan. Notre mission consiste à développer et déployer un modèle de prédiction d’accident vasculaire cérébral (AVC) en utilisant le langage de programmation R. Les résultats de notre travail seront présentés sur notre profil Coursera, offrant ainsi aux potentiels employeurs un aperçu de nos compétences en action.

Objectif du Projet :

L’objectif principal de ce projet est d’explorer un ensemble de données riche en informations sur les patients, en mettant l’accent sur l’identification des caractéristiques cliniques les plus cruciales. En suivant une approche méthodique, nous allons ensuite développer un modèle de prédiction d’AVC, rigoureusement validé pour une utilisation clinique efficace. Enfin, le déploiement du modèle vise à améliorer la prise de décision clinique au sein de notre organisation de santé.

Aperçu des Étapes et Compétences Mises en Valeur :

  • Exploration des Données : Nous débuterons par une exploration approfondie du jeu de données, incluant le chargement, le nettoyage, la transformation, l’ingénierie des fonctionnalités, et l’imputation des données manquantes.

  • Construction du Modèle : Nous mettrons en œuvre des modèles de prédiction tels que la régression logistique, la machine à vecteurs de support, les arbres de décision, la forêt aléatoire, et XGBoost. Nous prendrons en considération des aspects tels que le déséquilibre des classes, la normalisation des données et la sélection des hyperparamètres.

  • Évaluation et Déploiement : Nous évaluerons les modèles en utilisant diverses mesures (précision, sensibilité, rappel, score F, ASC) et déploierons le modèle choisi, que ce soit en tant que point de terminaison d’API ou en tant que page Web.

Ce projet représente une opportunité unique pour nous de démontrer nos compétences dans l’importation, le traitement et l’analyse de données de santé, ainsi que dans la construction et le déploiement de modèles prédictifs avancés.

Alors, sommes-nous prêts à relever le défi et à laisser notre empreinte dans le domaine de l’analyse de données de santé ? Suivons les étapes fournies et démarquons-nous avec notre approche unique dans ce projet passionnant !

  • À propos du rapport d’analyse des données:

Ce fichier RMarkdown contient le rapport de l’analyse des données effectuée pour le projet de création et de déploiement d’un modèle de prédiction des accidents vasculaires cérébraux dans R. Il contient des analyses telles que l’exploration des données, les statistiques récapitulatives et la construction des modèles de prédiction. Le rapport final a été achevé le Sun Feb 25 14:31:51 2024.

  • Description des données:

Selon l’Organisation mondiale de la santé (OMS), l’accident vasculaire cérébral est la deuxième cause de décès dans le monde, responsable d’environ 11 % du total des décès.

Cet ensemble de données est utilisé pour prédire si un patient est susceptible de subir un accident vasculaire cérébral en fonction de paramètres d’entrée tels que le sexe, l’âge, diverses maladies et le statut tabagique. Chaque ligne des données fournit des informations pertinentes sur le patient.

Charger les données et installer les packages

# charger les packages
library(rmarkdown)
library(readr)
library(dplyr)
library(tidyverse)
library(ggplot2)
library(plotly)
library(hrbrthemes)
library(viridis)
# pour la corrélation
library(heatmaply)
library(ggcorrplot)
# pour le réchantillonnage
library(recipes)
library(themis)
# pour la construction des modèles 
library(caret)
library(e1071)
library(glmnet)
library(rpart)
library(ISLR)
library(skimr)
# charger les données
strock = read.csv("/cloud/project/healthcare-dataset-stroke-data.csv")

En appliquant head() sur notre base de données des patients, nous visualisons les premières lignes, nous offrant ainsi un aperçu immédiat des enregistrements initiaux. C’est une manière rapide de comprendre la structure des données et d’identifier les types d’informations disponibles.

## visualiser les 5 premières lignes 
head(strock)
##      id gender age hypertension heart_disease ever_married     work_type
## 1  9046   Male  67            0             1          Yes       Private
## 2 51676 Female  61            0             0          Yes Self-employed
## 3 31112   Male  80            0             1          Yes       Private
## 4 60182 Female  49            0             0          Yes       Private
## 5  1665 Female  79            1             0          Yes Self-employed
## 6 56669   Male  81            0             0          Yes       Private
##   Residence_type avg_glucose_level  bmi  smoking_status stroke
## 1          Urban            228.69 36.6 formerly smoked      1
## 2          Rural            202.21  N/A    never smoked      1
## 3          Rural            105.92 32.5    never smoked      1
## 4          Urban            171.23 34.4          smokes      1
## 5          Rural            174.12   24    never smoked      1
## 6          Urban            186.21   29 formerly smoked      1

L’utilisation de tail() sur notre base de données des patients nous montre les dernières lignes, ce qui peut être utile pour vérifier la cohérence des données vers la fin de l’ensemble.

## visualiser les 5 derniières lignes 
tail(strock)
##         id gender age hypertension heart_disease ever_married     work_type
## 5105 14180 Female  13            0             0           No      children
## 5106 18234 Female  80            1             0          Yes       Private
## 5107 44873 Female  81            0             0          Yes Self-employed
## 5108 19723 Female  35            0             0          Yes Self-employed
## 5109 37544   Male  51            0             0          Yes       Private
## 5110 44679 Female  44            0             0          Yes      Govt_job
##      Residence_type avg_glucose_level  bmi  smoking_status stroke
## 5105          Rural            103.08 18.6         Unknown      0
## 5106          Urban             83.75  N/A    never smoked      0
## 5107          Urban            125.20   40    never smoked      0
## 5108          Rural             82.99 30.6    never smoked      0
## 5109          Rural            166.29 25.6 formerly smoked      0
## 5110          Urban             85.28 26.2         Unknown      0

En appliquant str() directement sur notre base de données des patients, nous obtenons une vue structurée montrant le type de chaque variable ainsi que les premières valeurs. Cette commande est précieuse pour comprendre la nature des données et détecter d’éventuels problèmes de type.

# Structure des données 
str(strock)
## 'data.frame':    5110 obs. of  12 variables:
##  $ id               : int  9046 51676 31112 60182 1665 56669 53882 10434 27419 60491 ...
##  $ gender           : chr  "Male" "Female" "Male" "Female" ...
##  $ age              : num  67 61 80 49 79 81 74 69 59 78 ...
##  $ hypertension     : int  0 0 0 0 1 0 1 0 0 0 ...
##  $ heart_disease    : int  1 0 1 0 0 0 1 0 0 0 ...
##  $ ever_married     : chr  "Yes" "Yes" "Yes" "Yes" ...
##  $ work_type        : chr  "Private" "Self-employed" "Private" "Private" ...
##  $ Residence_type   : chr  "Urban" "Rural" "Rural" "Urban" ...
##  $ avg_glucose_level: num  229 202 106 171 174 ...
##  $ bmi              : chr  "36.6" "N/A" "32.5" "34.4" ...
##  $ smoking_status   : chr  "formerly smoked" "never smoked" "never smoked" "smokes" ...
##  $ stroke           : int  1 1 1 1 1 1 1 1 1 1 ...

En appliquant length() sur une colonne spécifique ou sur notre base de données des patients, nous obtenons le nombre d’observations dans cette colonne.

length(strock)
## [1] 12

Lorsque nous utilisons summary() sur notre base de données des patients, nous obtenons des statistiques sommaires pour les variables numériques. Cela inclut des informations telles que la moyenne, la médiane, les valeurs minimales et maximales, et les quartiles.

summary(strock)
##        id           gender               age         hypertension    
##  Min.   :   67   Length:5110        Min.   : 0.08   Min.   :0.00000  
##  1st Qu.:17741   Class :character   1st Qu.:25.00   1st Qu.:0.00000  
##  Median :36932   Mode  :character   Median :45.00   Median :0.00000  
##  Mean   :36518                      Mean   :43.23   Mean   :0.09746  
##  3rd Qu.:54682                      3rd Qu.:61.00   3rd Qu.:0.00000  
##  Max.   :72940                      Max.   :82.00   Max.   :1.00000  
##  heart_disease     ever_married        work_type         Residence_type    
##  Min.   :0.00000   Length:5110        Length:5110        Length:5110       
##  1st Qu.:0.00000   Class :character   Class :character   Class :character  
##  Median :0.00000   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :0.05401                                                           
##  3rd Qu.:0.00000                                                           
##  Max.   :1.00000                                                           
##  avg_glucose_level     bmi            smoking_status         stroke       
##  Min.   : 55.12    Length:5110        Length:5110        Min.   :0.00000  
##  1st Qu.: 77.25    Class :character   Class :character   1st Qu.:0.00000  
##  Median : 91.89    Mode  :character   Mode  :character   Median :0.00000  
##  Mean   :106.15                                          Mean   :0.04873  
##  3rd Qu.:114.09                                          3rd Qu.:0.00000  
##  Max.   :271.74                                          Max.   :1.00000

Lorsque nous utilisons dim() directement sur notre base de données des patients, nous obtenons les dimensions, c’est-à-dire le nombre d’observations (lignes) et de variables (colonnes).

dim(strock)
## [1] 5110   12
print(paste("Ainsi, on a dans notre base de données,", (nrow(strock)), "et", (ncol(strock)), "caractéristiques pouvant causées des accidends vasculaires cérébraux"))
## [1] "Ainsi, on a dans notre base de données, 5110 et 12 caractéristiques pouvant causées des accidends vasculaires cérébraux"

Description des variables ou des caractéristiques des patients

La commande names() appliquée à notre base de données des patients nous donne les noms des colonnes.

names(strock)
##  [1] "id"                "gender"            "age"              
##  [4] "hypertension"      "heart_disease"     "ever_married"     
##  [7] "work_type"         "Residence_type"    "avg_glucose_level"
## [10] "bmi"               "smoking_status"    "stroke"

id : Identifiant unique attribué à chaque patient. Il s’agit probablement d’une clé primaire permettant d’identifier de manière unique chaque enregistrement dans la base de données.

gender : Genre du patient, indiquant s’il s’agit d’un homme, d’une femme ou d’une autre catégorie de genre.

age : L’âge du patient, exprimé en années. Cette variable donne une indication sur la tranche d’âge à laquelle appartient chaque individu.

hypertension : Indique la présence (1) ou l’absence (0) d’hypertension chez le patient. L’hypertension est une condition médicale caractérisée par une pression artérielle élevée.

heart_disease :

Indique la présence (1) ou l’absence (0) de maladies cardiaques chez le patient.

ever_married :

Indique si le patient a déjà été marié (Yes) ou non (No). Cette variable offre des informations sur l’état matrimonial du patient.

work_type :

Type d’emploi du patient, fournissant des détails sur le secteur ou la nature de l’activité professionnelle du patient.

Residence_type :

Indique si le patient habite en zone urbaine (Urban) ou rurale (Rural).

avg_glucose_level :

Niveau moyen de glucose dans le sang du patient, mesuré en unités spécifiques. Cette variable peut être importante pour évaluer le risque de certaines conditions médicales.

bmi :

Indice de masse corporelle (BMI) du patient, fournissant des informations sur la composition corporelle en fonction du poids et de la taille.

smoking_status :

Indique le statut tabagique du patient, avec des catégories telles que “formerly smoked,” “never smoked,” “smokes,” ou “Unknown.”

stroke :

Variable cible indiquant la survenue (1) ou non (0) d’un accident vasculaire cérébral chez le patient. C’est probablement la variable que nous cherchons à prédire dans le cadre du projet de prédiction d’AVC.

Exploration et préparation des Données

Analyse univariée

###Distribution des variables catégorielles

Le genre des patients

# Table de fréquence des genres
eff = table(strock$gender)

# Diagramme à barres
g_genre = ggplot(data = strock, aes(x=strock$gender, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("Le genre des patients") + ylab("Effectif des patients par sexe") + ggtitle("La distribution des patients par genres") + guides(fill=guide_legend(title = "Les victimes d'AVC par sexe"))

ggplotly(g_genre)
## Warning: Use of `strock$gender` is discouraged.
## ℹ Use `gender` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.

La majorité des ptients qui foont l’objet de notre étude sont du sexe feminin soit 2994 clients et 2115 sont du sexe masculin. Seul 141 femmes sont victimes d’AVC contre 108 hommes pour l’ensemble de l’échantillon.

# Test du chi-deux pour la distribution des genres
chi_genre <- chisq.test(table(strock$gender))
print(chi_genre)
## 
##  Chi-squared test for given probabilities
## 
## data:  table(strock$gender)
## X-squared = 2778.8, df = 2, p-value < 2.2e-16

La p-valeur très faible indique que vous pouvez rejeter l’hypothèse nulle selon laquelle il n’y a aucune relation entre les variables (ici, le genre). Il y a des différences significatives entre les fréquences observées et attendues, ce qui suggère une association entre le genre et une autre variable dans votre ensemble de données.

hypertension

# Diagramme à barres pour la variable hypertension 
table(strock$hypertension)
## 
##    0    1 
## 4612  498
g_genre = ggplot(data = strock, aes(x=strock$hypertension, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("L'hypertention") + ylab("Effectif des patients par hypertension") + ggtitle("La distribution de l'hypertension des patients") + guides(fill=guide_legend(title = "Présence ou absence d'AVC chez le patient"))
ggplotly(g_genre)
## Warning: Use of `strock$hypertension` is discouraged.
## ℹ Use `hypertension` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.

La majorité des patients de l’échantillon ne sont pas victimes d’hypertension artérille. De plus, sur les 4612 qui ne sont pas victime seulement 183 ont l’AVC et sur les 498 qui ont l’hypertension seul 66 ont l’AVC.

# Test du chi-deux pour la distribution des genres
chi_hyp <- chisq.test(table(strock$hypertension))
print(chi_hyp)
## 
##  Chi-squared test for given probabilities
## 
## data:  table(strock$hypertension)
## X-squared = 3312.1, df = 1, p-value < 2.2e-16

heart_disease

# Diagramme à barres pour la variable heart_disease
table(strock$heart_disease)
## 
##    0    1 
## 4834  276
g_heart = ggplot(data = strock, aes(x=strock$heart_disease, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("L'hypertention") + ylab("Effectif des patients par maladie cardiaque") + ggtitle("La distribution des patients par maladie cardiaque") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_heart)
## Warning: Use of `strock$heart_disease` is discouraged.
## ℹ Use `heart_disease` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.

4834 patients n’ont pas de maladie cardique contre 276 qui en sont victimes. Parmi ceux qui sont victimes de maladie cardiaque, seul 47 ont l’AVC. Et pour ceux qui n’ont pas de maladie vasculaire seul 202 patients ont l’AVC.

# Test du chi-deux pour la distribution des genres
chi_heart <- chisq.test(table(strock$heart_disease))
print(chi_hyp)
## 
##  Chi-squared test for given probabilities
## 
## data:  table(strock$hypertension)
## X-squared = 3312.1, df = 1, p-value < 2.2e-16

ever_married

# Diagramme à barres pour la variable maried
table(strock$ever_married)
## 
##   No  Yes 
## 1757 3353
g_maried = ggplot(data = strock, aes(x=strock$ever_married, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("situation") + ylab("Effectif des patients par situation matrimoniale") + ggtitle("La distribution des patients par stuation matrimoniale") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_maried)
## Warning: Use of `strock$ever_married` is discouraged.
## ℹ Use `ever_married` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.
chi_maried = chisq.test(table(strock$ever_married))
print(chi_maried)
## 
##  Chi-squared test for given probabilities
## 
## data:  table(strock$ever_married)
## X-squared = 498.48, df = 1, p-value < 2.2e-16

work_type

# Diagramme à barres pour la variable type de job
table(strock$work_type)
## 
##      children      Govt_job  Never_worked       Private Self-employed 
##           687           657            22          2925           819
g_work = ggplot(data = strock, aes(x=strock$work_type, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("Type d'emploi") + ylab("Effectif des patients par type d'emploi") + ggtitle("La distribution des patients par type d'emploi") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_work)
## Warning: Use of `strock$work_type` is discouraged.
## ℹ Use `work_type` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.

Residence_type

# Diagramme à barres pour la variable residence_type
table(strock$Residence_type)
## 
## Rural Urban 
##  2514  2596
g_residence = ggplot(data = strock, aes(x=strock$Residence_type, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("Type de résidence") + ylab("Effectif des patients par type de résidence") + ggtitle("La distribution des patients par type de résidence") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_residence)
## Warning: Use of `strock$Residence_type` is discouraged.
## ℹ Use `Residence_type` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.

smoking_status

# Diagramme à barres pour la variable smoking
table(strock$smoking_status)
## 
## formerly smoked    never smoked          smokes         Unknown 
##             885            1892             789            1544
g_smok = ggplot(data = strock, aes(x=strock$smoking_status, fill = factor(strock$stroke))) + geom_bar() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + coord_flip() + xlab("Statut tabagique") + ylab("Effectif des patients par statut tabagique") + ggtitle("La distribution des patients par profil") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_smok)
## Warning: Use of `strock$smoking_status` is discouraged.
## ℹ Use `smoking_status` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.

Distribution des variables numériques

age

g_age <- strock %>% ggplot(aes(y=age), fill="age") + geom_boxplot() + ylab("L'age des patients")+ ggtitle("Distribution de l'age des patients")
ggplotly(g_age)

On observe quelque chose de très pertinent, l’AVC augmente avec l’age. Plus les patients prennent de l’age plus la probabilié d’avoir un AVC est élevée.

De plus, 50% des patients ont moins de 45 ans et 50% on plus de 45 ans. Cependant, il y a aussi des enfants dans notre base des données.

avg_glucose_level

g_glucose = ggplot(data = strock, aes(x=strock$avg_glucose_level, fill = factor(strock$stroke))) + geom_histogram() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("Niveau moyen de glucose dans le sang des patients") + ylab("Effectif des patients") + ggtitle("La distribution des patients par niveau moyen de glucose dans le sang") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_glucose)
## Warning: Use of `strock$avg_glucose_level` is discouraged.
## ℹ Use `avg_glucose_level` instead.
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

avg_glucose_level

strock$bmi <- as.numeric(strock$bmi)
g_bmi = ggplot(data = strock, aes(strock$bmi, fill = factor(strock$stroke))) + geom_histogram() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("Indice de masse corporelle") + ylab("Effectif des patients") + ggtitle("La distribution des patients par indice de masse corporelle") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_bmi) 

Analyse bivariée

Visualisation des relations entre les variables

Genre des patients et leur age

g_age_genre = ggplot(data = strock, aes(x=strock$gender, y=strock$age, fill=strock$gender)) + geom_boxplot() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("Genre des patients") + ylab("L'age des patients") + ggtitle("La distribution de l'age des patients par sexe") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_age_genre)
## Warning: Use of `strock$gender` is discouraged.
## ℹ Use `gender` instead.
## Warning: Use of `strock$age` is discouraged.
## ℹ Use `age` instead.
## Warning: Use of `strock$gender` is discouraged.
## ℹ Use `gender` instead.

Les hommes sont moins jeunes que les femmes.

Relation entre le niveau moyen de glucose et l’AVC

g_avgglu_strocke = strock %>% ggplot(aes(y=avg_glucose_level, x=stroke, fill = factor(stroke))) + geom_boxplot() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("AVC") + ylab("Niveau moyen de glucose dans le sang du patient") + ggtitle("La distribution ddu ") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_avgglu_strocke)

La majorité de ceux qui sont victimes d’AVC ont un niveau moyenne de glucose plus élévé que ceux qui n’ont pas d’AVC, il y a des exeptions.

Relation entre l’indice de masse corporelle et l’AVC

g_bmi_strocke = strock %>% ggplot(aes(y=bmi, x=stroke, fill = factor(strock$stroke))) + geom_boxplot() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("AVC") + ylab("BMI du patient") + ggtitle("La distribution du BMI du patient") + guides(fill=guide_legend(title = "Présence d'AVC chez le patient"))
ggplotly(g_bmi_strocke)
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.
## Warning: Removed 201 rows containing non-finite values (`stat_boxplot()`).

Graphique de dispersion entre l’âge et l’indice de masse corporelle (BMI)

ggplot(data = strock, aes(y=age, x=bmi, fill = (strock$stroke))) + geom_point()
## Warning: Use of `strock$stroke` is discouraged.
## ℹ Use `stroke` instead.
## Warning: Removed 201 rows containing missing values (`geom_point()`).

strock %>%
  ggplot(aes(x = avg_glucose_level, y = bmi, fill = stroke)) +
  geom_point() +
  labs(title = "Relation entre le niveau de glucose dans le sang et BMI", x = "Niveau moyen de glucose", y = "Indice de masse corporelle") +
  theme_minimal()
## Warning: Removed 201 rows containing missing values (`geom_point()`).

Relation entre Indice de masse corporelle et le type de boulot

g_bmi_job = ggplot(data = strock, aes(x=strock$work_type, y=strock$bmi, fill=factor(strock$work_type))) + geom_violin() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("Type de boulot") + ylab("La distribution des patients par indice de masse corporelle") + ggtitle("Distribution de l'indice de masse corporelle par type de boulot ") + guides(fill=guide_legend(title = "Type de boulot"))
ggplotly(g_bmi_job)
## Warning: Use of `strock$work_type` is discouraged.
## ℹ Use `work_type` instead.
## Warning: Use of `strock$bmi` is discouraged.
## ℹ Use `bmi` instead.
## Warning: Use of `strock$work_type` is discouraged.
## ℹ Use `work_type` instead.
## Warning: Removed 201 rows containing non-finite values (`stat_ydensity()`).

Relation entre Indice de masse corporelle et statut de fumeur

g_bmi_job = ggplot(data = strock, aes(x=strock$smoking_status, y=strock$bmi, fill=factor(strock$smoking_status))) + geom_violin() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + xlab("Statut de fumeur") + ylab("La distribution de l'indice de masse corporelle des patients") + ggtitle("Répartition de l'indice de masse corporelle par type de fumeur ") + guides(fill=guide_legend(title = "Type de fumeur"))
ggplotly(g_bmi_job)
## Warning: Use of `strock$smoking_status` is discouraged.
## ℹ Use `smoking_status` instead.
## Warning: Use of `strock$bmi` is discouraged.
## ℹ Use `bmi` instead.
## Warning: Use of `strock$smoking_status` is discouraged.
## ℹ Use `smoking_status` instead.
## Warning: Removed 201 rows containing non-finite values (`stat_ydensity()`).

Tableau des fréquences

**Le genre

strock %>% count(strock$gender, name = 'nb') %>% mutate(freq=prop.table(table(strock$gender)))
##   strock$gender   nb         freq
## 1        Female 2994 0.5859099804
## 2          Male 2115 0.4138943249
## 3         Other    1 0.0001956947

Hypertension

strock %>% count(strock$hypertension, name = 'nb') %>% mutate(freq=prop.table(prop.table(table(strock$hypertension))))
##   strock$hypertension   nb       freq
## 1                   0 4612 0.90254403
## 2                   1  498 0.09745597

Maladie de coeur

strock %>% count(strock$heart_disease, name = "nb") %>% mutate(freq=prop.table(table(strock$heart_disease)))
##   strock$heart_disease   nb       freq
## 1                    0 4834 0.94598826
## 2                    1  276 0.05401174

Marié

strock %>% count(strock$ever_married, name = "nb") %>% mutate(freq=prop.table(prop.table(table(strock$ever_married))))
##   strock$ever_married   nb      freq
## 1                  No 1757 0.3438356
## 2                 Yes 3353 0.6561644

Type de boulot

(strock %>% count(strock$work_type, name = "nb") %>% mutate(freq= prop.table(table(strock$work_type)))
)
##   strock$work_type   nb        freq
## 1         Govt_job  657 0.134442270
## 2     Never_worked   22 0.128571429
## 3          Private 2925 0.004305284
## 4    Self-employed  819 0.572407045
## 5         children  687 0.160273973

Type de Résidence

strock %>% count(strock$Residence_type, name = "nb") %>% mutate(freq=prop.table(table(strock$Residence_type)))
##   strock$Residence_type   nb      freq
## 1                 Rural 2514 0.4919765
## 2                 Urban 2596 0.5080235

Statut de fumeur

strock %>% count(strock$smoking_status, name = "nb") %>% mutate(freq= prop.table(table(strock$smoking_status)))
##   strock$smoking_status   nb      freq
## 1               Unknown 1544 0.1731898
## 2       formerly smoked  885 0.3702544
## 3          never smoked 1892 0.1544031
## 4                smokes  789 0.3021526

La variable cyble: stroke ou AVC

strock %>% count(strock$stroke, name = "nb") %>% mutate(freq=prop.table(table(strock$stroke)))
##   strock$stroke   nb       freq
## 1             0 4861 0.95127202
## 2             1  249 0.04872798

On observe que les patients victimes d’AVC ne font que 4% de l’échantillon.

Corrélations entre les Variables Numériques

Matrice de corrélation entre l’âge, la glycémie moyenne et l’indice de masse corporelle (BMI)

num_var <- strock[ ,c("age", "avg_glucose_level", "bmi" )]
bmi_median <- 
  median(num_var$bmi, na.rm = TRUE)
num_var$bmi[is.na(num_var$bmi)] <- bmi_median

heatmaply_cor(cor(num_var),
              xlab="", ylab="", 
              k_col = 3,
              K_row=3)

A trvaers ce graphique on onbserve une corrélation positive faible entre les varibles age, niveau moyen de glucose et le BMI. Il reste à tester si cette corrélation est significative ou pas. Une corrélation parfaite n’implique pas forcement une causalité. Pour déduire une relation de cause à effet entre ces variables, il nous faut une analyse approfondie entre ces variables.

Préparation des données

remplaçons les NA de la variable bmi par la médiane de la variable BMI

strock_echantillon <- strock
strock_echantillon$bmi[is.na(strock_echantillon$bmi)] <- bmi_median
strock_echantillon$gender[strock_echantillon$gender=="Other"] = "Female"

Transformer les variavles qualitatives en variabe binaaire ou en varaible multinomiale

Transformons les variables gender, maried et résidence type en variable binaire

  • Le genre des patients
strock_echantillon$gender_bi <- ifelse(strock_echantillon$gender=="Male", 1, 0)
  • Statut marriatl des patients
strock_echantillon$ever_married_bi <- ifelse(strock_echantillon$ever_married=="Yes", 1, 0)
  • Le type de résidence
strock_echantillon$Residence_type_bi <- ifelse(strock_echantillon$Residence_type=="Urban", 1, 0)

Transformons les variables work_type et smoking_status en variable multinomiale

  • Type de boulot
strock_echantillon$work_type_bi = as.numeric(factor(strock_echantillon$work_type, levels = c("children",      "Govt_job",      "Never_worked", "Private",       "Self-employed")))-1
strock_echantillon$smoking_status_bi = as.numeric(factor(strock_echantillon$smoking_status, levels = c("formerly smoked", "never smoked",    "smokes",          "Unknown")))-1
strock_model <- select(strock_echantillon, -c(id, gender, hypertension, heart_disease, ever_married,      work_type, Residence_type, smoking_status))
head(strock_model, 3)
##   age avg_glucose_level  bmi stroke gender_bi ever_married_bi Residence_type_bi
## 1  67            228.69 36.6      1         1               1                 1
## 2  61            202.21 28.1      1         0               1                 0
## 3  80            105.92 32.5      1         1               1                 0
##   work_type_bi smoking_status_bi
## 1            3                 0
## 2            4                 1
## 3            3                 1

Après l’analyse univariée et bivariée on constate qu’il y a des variables qui n’ont aucun impact sur la varible cyble ou qui ne contribuent pas à expliquer la survenance d’AVC.

Les déséquilibre d’effectif qu’on a pour certaines modalités, nous conduit à réechantillonner notre base des données afin de résoudre les problèmes de araeté de certaines variables

Réechantillons les données à cause de la rareté de certaines modalitée des variables expliquatives et de la variable cible

Réchantillons les données rares

Augmentons la taille de la base des données fois 10

strock_model$stroke[strock_model$stroke==1] = "OUI"
strock_model$stroke[strock_model$stroke==0] = "NON"
head(strock_model)
##   age avg_glucose_level  bmi stroke gender_bi ever_married_bi Residence_type_bi
## 1  67            228.69 36.6    OUI         1               1                 1
## 2  61            202.21 28.1    OUI         0               1                 0
## 3  80            105.92 32.5    OUI         1               1                 0
## 4  49            171.23 34.4    OUI         0               1                 1
## 5  79            174.12 24.0    OUI         0               1                 0
## 6  81            186.21 29.0    OUI         1               1                 1
##   work_type_bi smoking_status_bi
## 1            3                 0
## 2            4                 1
## 3            3                 1
## 4            3                 2
## 5            4                 1
## 6            3                 0

On va sur-échantillonner les données pour équilibrer les données en utilisant la fonction upsample du package caret.

strock_model$stroke <- as.factor(strock_model$stroke)
strock_modell <- upSample(strock_model[, -4], y = strock_model$stroke)
strock_modell$Class= as.numeric(strock_modell$Class)-1
table(strock_modell$Class)
## 
##    0    1 
## 4861 4861

###Choix des variables dépendantes ou des variables qui contribuent à expliquer la survenance d’AVC ches un patnt

Pour cela on va utiliser l’ANOVA : l’analyse des variance qui permet de déterminer l’impact ou l’association entre les variables dépendantes et la variable cyble.

D’arès les resultats, la majorité des variables sont significatives au seuil de 5%. Ce qui veut dire qu’il y a une association entre l’AVC et l’ensemble des variables. Cela n’imlique pas une causalité.

anova = aov(cbind(strock_modell$age, strock_modell$avg_glucose_level, strock_modell$bmi, strock_modell$gender_bi, strock_modell$ever_married_bi,
          strock_modell$Residence_type_bi, strock_modell$work_type_bi, strock_modell$smoking_status_bi) ~ strock_modell$Class, data=strock_modell)
summary.aov(anova)
##  Response 1 :
##                       Df  Sum Sq Mean Sq F value    Pr(>F)    
## strock_modell$Class    1 1618759 1618759  4943.2 < 2.2e-16 ***
## Residuals           9720 3183056     327                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response 2 :
##                       Df   Sum Sq Mean Sq F value    Pr(>F)    
## strock_modell$Class    1  1723144 1723144  601.72 < 2.2e-16 ***
## Residuals           9720 27834979    2864                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response 3 :
##                       Df Sum Sq Mean Sq F value    Pr(>F)    
## strock_modell$Class    1   4074  4073.7  85.802 < 2.2e-16 ***
## Residuals           9720 461481    47.5                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response 4 :
##                       Df Sum Sq Mean Sq F value Pr(>F)
## strock_modell$Class    1    0.3 0.29994  1.2325  0.267
## Residuals           9720 2365.5 0.24337               
## 
##  Response 5 :
##                       Df  Sum Sq Mean Sq F value    Pr(>F)    
## strock_modell$Class    1  134.38 134.381  802.16 < 2.2e-16 ***
## Residuals           9720 1628.32   0.168                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response 6 :
##                       Df  Sum Sq Mean Sq F value   Pr(>F)    
## strock_modell$Class    1    2.83 2.83440  11.373 0.000748 ***
## Residuals           9720 2422.37 0.24921                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response 7 :
##                       Df  Sum Sq Mean Sq F value    Pr(>F)    
## strock_modell$Class    1   608.4  608.38  479.51 < 2.2e-16 ***
## Residuals           9720 12332.2    1.27                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response 8 :
##                       Df  Sum Sq Mean Sq F value    Pr(>F)    
## strock_modell$Class    1   246.8 246.801   211.1 < 2.2e-16 ***
## Residuals           9720 11363.7   1.169                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Standardisons les donnnées de la base

  • La normalisation échelonne les valeurs d’une variable dans une plage spécifique, généralement entre 0 et 1. C’est utile lorsqu’on veut ramener toutes les valeurs à une plage commune.

  • Standardisation (Z-score Scaling) : la standardisation met à l’échelle les valeurs de manière à ce qu’elles aient une moyenne nulle et un écart-type unitaire. Cela est souvent utilisé dans des algorithmes qui supposent une distribution normale des données.

Standardisons

standar_data = preProcess(strock_modell[, -9], method = c("center", "scale"))
strock_standardizer = predict(standar_data, newdata=strock_modell)
print(head(strock_standardizer))
##          age avg_glucose_level        bmi  gender_bi ever_married_bi
## 1 -2.3340636        -0.4169001 -1.6540173  1.1788678       -1.789656
## 2  0.1405960        -0.5467465  1.4093976  1.1788678        0.558709
## 3 -2.1090945        -0.1309115 -1.7118176 -0.8481843       -1.789656
## 4  0.6805217        -0.8898603  0.9325453 -0.8481843        0.558709
## 5 -1.8391317         0.7829101 -1.4950665  1.1788678       -1.789656
## 6 -0.3543359         1.6836745  2.9844553 -0.8481843        0.558709
##   Residence_type_bi work_type_bi smoking_status_bi Class
## 1        -1.0477875   -2.3585604         1.4250479     0
## 2         0.9542939    0.2415973        -0.4049918     0
## 3         0.9542939    0.2415973         1.4250479     0
## 4        -1.0477875    0.2415973        -1.3200116     0
## 5        -1.0477875   -0.6251219         1.4250479     0
## 6         0.9542939    0.2415973         1.4250479     0

Construction du Modèle

# pour la construction des modèles 
install.packages("kernlab")
library(kernlab)
install.packages("randomForest")
library(randomForest)
library(caret)
library(e1071)
library(glmnet)
library(rpart)
library(ISLR)
library(skimr)

Construction des modèles pour prédire la survenance ou non d’AVC chez un patient

on va construire les modèles suivants:

  • Regression logistique (RL)

  • Analyse discriminante linéaire (LDA)

  • Arbres de classification et de régression (CART)

  • k-Voisins les plus proches (kNN)

  • Machines à vecteurs de support (SVM) avec un noyau linéaire

  • Forêt aléatoire (RF)

Nous effectuerons une validation croisée 10 fois pour estimer la précision. Cela divisera notre ensemble de données en 10 parties, entraînera en 9 et testera sur 1 et publiera pour toutes les combinaisons de répartitions train-test. Nous répéterons également le processus 3 fois pour chaque algorithme avec différentes répartitions des données en 10 groupes, dans le but d’obtenir une estimation plus précise.

Préparons les données d’entrainement et de test soit 70% pour l’entrainement et 30% pour le test

Avec la fonction createDataPartition de caret

set.seed(123)
indice = createDataPartition(strock_standardizer$Class, p=0.7, list = FALSE)
data_train = strock_standardizer[indice, ]
data_test = strock_standardizer[-indice, ]
# type des données 
data_train$Class <- as.factor(data_train$Class)
class(data_train$Class)
## [1] "factor"

Définir le contrôle pour train :

Utilison la fonction trainControl pour définir les paramètres de contrôle pour l’entraînement des modèles. Nous pouvons spécifier la méthode de validation croisée et les métriques de performance.

# Définition du contrôle
control <- trainControl(method = "cv", number = 5)
metric <- c("Accuracy")

Modèle de régression logistique

# Modèle de régression logistique
set.seed(7)
fit.lm <- train(Class ~ ., data = data_train, method = "glm", 
                metric = "Accuracy",
                trControl = control)

Linear algorithms

set.seed(7)
fit.lda <- train(Class ~ ., data = data_train, method = "lda", metric = metric, trControl = control)

print(fit.lda)
## Linear Discriminant Analysis 
## 
## 6806 samples
##    8 predictor
##    2 classes: '0', '1' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 5445, 5445, 5444, 5445, 5445 
## Resampling results:
## 
##   Accuracy   Kappa    
##   0.7650594  0.5301199

Nonlinear algorithms

# CART
set.seed(7)
fit.cart <- train(Class ~ ., data = data_train, method = "rpart", metric = metric, trControl = control)
print(fit.cart)
## CART 
## 
## 6806 samples
##    8 predictor
##    2 classes: '0', '1' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 5445, 5445, 5444, 5445, 5445 
## Resampling results across tuning parameters:
## 
##   cp          Accuracy   Kappa    
##   0.01513371  0.7643223  0.5286924
##   0.01616221  0.7605040  0.5210381
##   0.50661181  0.5984570  0.1972667
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was cp = 0.01513371.

KNN modèle

# kNN
set.seed(7)
fit.knn <- train(Class ~ ., data = data_train, method = "knn", metric = metric, trControl = control)
print(fit.knn)
## k-Nearest Neighbors 
## 
## 6806 samples
##    8 predictor
##    2 classes: '0', '1' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 5445, 5445, 5444, 5445, 5445 
## Resampling results across tuning parameters:
## 
##   k  Accuracy   Kappa    
##   5  0.8657075  0.7314188
##   7  0.8379370  0.6758818
##   9  0.8173659  0.6347392
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was k = 5.

ASVM algorithms

# SVM
set.seed(7)
fit.svm <- train(Class ~ ., data = data_train, method = "svmRadial", metric = metric, trControl = control)
print(fit.svm)
## Support Vector Machines with Radial Basis Function Kernel 
## 
## 6806 samples
##    8 predictor
##    2 classes: '0', '1' 
## 
## No pre-processing
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 5445, 5445, 5444, 5445, 5445 
## Resampling results across tuning parameters:
## 
##   C     Accuracy   Kappa    
##   0.25  0.7853358  0.5706730
##   0.50  0.7891557  0.5783124
##   1.00  0.7960622  0.5921245
## 
## Tuning parameter 'sigma' was held constant at a value of 0.1003374
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were sigma = 0.1003374 and C = 1.

Random Forest

**{r} set.seed(7) fit.rf <- train(Class ~ ., data = data_train, method = "rf", metric = "Accuracy", trControl = control) print(fit.rf)

Evaluation: selectionnons le meilleur modèle

Nous disposons désormais de 6 modèles et d’estimations de précision pour chacun. Nous devons comparer les modèles entre eux et sélectionner le plus précis.

Nous pouvons rendre compte de l’exactitude de chaque modèle en créant d’abord une liste des modèles créés et en utilisant la fonction de résumé.

Nous disposons désormais de 6 modèles et d’estimations de précision pour chacun. Nous devons comparer les modèles entre eux et sélectionner le plus précis.

Nous pouvons rendre compte de l’exactitude de chaque modèle en créant d’abord une liste des modèles créés et en utilisant la fonction de résumé.

Nous pouvons voir la précision de chaque classificateur ainsi que d’autres métriques comme Kappa :

# summarize accuracy of models
results <- resamples(list(lda=fit.lda, cart=fit.cart, knn=fit.knn, svm=fit.svm))
summary(results)
## 
## Call:
## summary.resamples(object = results)
## 
## Models: lda, cart, knn, svm 
## Number of resamples: 5 
## 
## Accuracy 
##           Min.   1st Qu.    Median      Mean   3rd Qu.      Max. NA's
## lda  0.7545922 0.7641440 0.7656135 0.7650594 0.7700220 0.7709251    0
## cart 0.7457752 0.7472447 0.7648788 0.7643223 0.7766348 0.7870778    0
## knn  0.8545187 0.8604993 0.8655400 0.8657075 0.8692138 0.8787656    0
## svm  0.7883909 0.7927994 0.7966226 0.7960622 0.7994122 0.8030860    0
## 
## Kappa 
##           Min.   1st Qu.    Median      Mean   3rd Qu.      Max. NA's
## lda  0.5092318 0.5282455 0.5311908 0.5301199 0.5400811 0.5418502    0
## cart 0.4916939 0.4946397 0.5297227 0.5286924 0.5532501 0.5741557    0
## knn  0.7090995 0.7209985 0.7310303 0.7314188 0.7384777 0.7574879    0
## svm  0.5767331 0.5856496 0.5932452 0.5921245 0.5987735 0.6062210    0

Nous pouvons également créer un graphique des résultats de l’évaluation du modèle et comparer la propagation et la précision moyenne de chaque modèle. Il existe une population de mesures de précision pour chaque algorithme car chaque algorithme a été évalué 5 fois (validation croisée 5 fois).

comparons la précision de chaque modèle :

dotplot(results)

Nous pouvons constater que le meilleur modèle est: Random Forest. Nous pouvons résumer le résultat du modèle RF à :

**{r} print(fit.rf)

ous observons que pour différentes valeurs de l’hyperparamètre mtry (le nombre de variables aléatoires considérées à chaque division de l’arbre) lors de la validation croisée, le modèle Random Forest présente des performances variées. Les résultats montrent que la précision, mesurée par la proportion d’observations correctement classées, ainsi que le coefficient kappa, indiquant l’accord entre les prédictions du modèle et les classes réelles, varient selon la valeur de mtry. Nous constatons que la meilleure précision et le plus haut coefficient kappa sont obtenus lorsque mtry est égal à 5, avec des valeurs respectives de 97.99% et 95.97%.

Il est important de noter que l’évaluation du modèle a été réalisée sur différents plis de la validation croisée, fournissant des performances spécifiques pour chaque pli. Nous avons choisi le modèle optimal en se basant sur la précision, et la meilleure valeur de mtry sélectionnée était 5, comme indiqué par la ligne “Accuracy was used to select the optimal model using the largest value.”

En conclusion, nous retenons le modèle Random Forest avec mtry = 5 comme le meilleur modèle, présentant une précision de 97.99% et un coefficient kappa de 95.97% lors de la validation croisée.

Faisons la prédiction

Le RF était le modèle le plus précis. Nous voulons maintenant avoir une idée de la précision du modèle sur notre ensemble de test.

Cela nous donnera une vérification finale indépendante de l’exactitude du meilleur modèle. Il est utile de conserver un ensemble de validation au cas où vous feriez une erreur lors d’un surajustement de l’ensemble d’entraînement ou d’une fuite de données. Les deux aboutiront à un résultat trop optimiste.

Nous pouvons exécuter le modèle RF directement sur l’ensemble de validation et résumer les résultats dans une matrice de confusion.

**{r} prediction = predict(fit.rf, data_test) data_test$Class <- as.factor(data_test$Class) conf_matrix <- confusionMatrix(prediction, data_test$Class) print(conf_matrix) Au vu des resultats de la matrice de confusion on peut dire que :

La matrice de confusion nous fournit un aperçu détaillé des performances de notre modèle Random Forest sur les données de test. Voici notre analyse des différents aspects de la matrice de confusion et des statistiques associées :

Matrice de Confusion :

Vrais Positifs (0 prédit comme 0) : 1417 Faux Positifs (1 prédit comme 0) : 0 Faux Négatifs (0 prédit comme 1) : 41 Vrais Négatifs (1 prédit comme 1) : 1458

Statistiques de Performance :

Précision (Accuracy) : 98.59% Intervalle de Confiance (95%) : Entre 98.1% et 98.99% Taux d’Erreur (No Information Rate) : 50% (comparaison avec un modèle ignorant) Valeur p (P-Value [Acc > NIR]) : Inférieure à 2.2e-16 (indique une significative amélioration par rapport au taux d’erreur) Kappa : 97.19% (mesure de l’accord entre nos prédictions et les classes réelles) Autres Statistiques :

Test de Mcnemar : la valeur p est significative (4.185e-10), suggérant une différence significative entre les erreurs de type I et de type II.

  • Sensibilité (Sensitivity) : 97.19% (capacité à détecter les vrais positifs)

  • Spécificité (Specificity) : 100% (capacité à détecter les vrais négatifs)

  • Valeur Prédictive Positive (Pos Pred Value) : 100% (probabilité que notre prédiction positive soit correcte)

  • Valeur Prédictive Négative (Neg Pred Value) : 97.26% (probabilité que notre prédiction négative soit correcte)

  • Prévalence : 50% (proportion d’événements positifs dans la population)

  • Taux de Détection (Detection Rate) : 48.59% (proportion d’événements positifs détectés par notre modèle)

  • Prévalence de Détection (Detection Prevalence) : 48.59% (proportion d’événements positifs détectés par notre modèle parmi tous les cas positifs réels)

  • Précision Équilibrée (Balanced Accuracy) : 98.59% (moyenne de la sensibilité et de la spécificité)

En résumé, notre modèle Random Forest présente d’excellentes performances sur les données de test, démontrant ainsi notre capacité à bien généraliser sur de nouvelles données.

**{r} datatable(conf_matrix$table)

Dploiement du modèle

Cela fera l’objet d’autres projets.

Recommendations basées sur l’analyse des données

Après avoir analysé les données relatives à la prédiction de la survenance d’AVC chez les patients de l’hôpital, voici un exemple de recommandation :

À la lumière de notre analyse approfondie, plusieurs insights clés ont émergé, mettant en évidence des tendances et des facteurs significatifs liés à la survenance d’AVC chez les patients. Ces résultats peuvent orienter les interventions et les stratégies de prévention. Voici quelques recommandations :

Identification des Groupes à Risque :

Les patients présentant des antécédents d’hypertension et de maladies cardiaques sont particulièrement à risque. Les programmes de surveillance et d’éducation devraient cibler ces groupes spécifiques. Promotion du Mode de Vie Sain :

Encourager les patients à adopter un mode de vie sain, y compris une alimentation équilibrée, une activité physique régulière et l’arrêt du tabac, peut réduire significativement le risque d’AVC. Gestion de l’Hypertension et de la Glycémie :

Mettre en place des protocoles de suivi étroit pour les patients hypertendus et ceux présentant des niveaux de glucose élevés, en s’assurant qu’ils reçoivent les soins appropriés pour maintenir ces paramètres dans des plages sûres. Éducation sur les Facteurs de Risque Modifiables :

Sensibiliser les patients à l’importance de la gestion du poids, en particulier du BMI, peut avoir un impact positif sur la prévention des AVC. Surveillance Continue :

Établir un suivi régulier des patients à risque élevé, même s’ils n’ont pas encore présenté d’AVC. La détection précoce de signes précurseurs peut permettre une intervention rapide. Campagnes de Sensibilisation :

Organiser des campagnes de sensibilisation communautaire sur les facteurs de risque, les symptômes précoces et l’importance de la consultation médicale en cas de doute peut contribuer à une réduction globale des cas d’AVC. Ces recommandations, basées sur une analyse approfondie des données, visent à fournir des orientations stratégiques pour améliorer la prévention des AVC au sein de la population étudiée. Il est crucial de mettre en œuvre ces mesures de manière coordonnée avec les professionnels de la santé et les parties prenantes impliquées dans la gestion des soins de santé.

                                          **Thank you**