L’objectif de cette étude est de regrouper les communes françaises en un certain nombre de clusters (qui sera défini pendant l’étude), selon quatre critères pour chaque commune :
Les données proviennent de l’INSEE (pour les données économiques, démographiques et de logement), de la DREES (pour les données de santé) et de La Poste (coordonnées GPS pour visualisation). Elles sont toutes issues d’un découpage communal.
Toutes les données concernent ainsi à l’origine :
Enfin, pour les villes de Paris, Lyon et Marseille, les données seront étudiées au niveau de chaque arrondissement.
Chargement des libraries utilisées par la suite.
# libraries nécessaires
library(tidyverse) # manipulation de données
library(readxl) # importer des fichers XLS
library(kableExtra) # affichage soigné des tables de résultats
# thème utilisé pour les graphes
ggthemr::ggthemr("fresh")Données : Distribution des revenus déclarés par unité de consommation et composition du revenu déclaré par commune (hors Mayotte).
Source : INSEE
Fichier : https://insee.fr/fr/statistiques/fichier/3560118/indic-struct-distrib-revenu-2015-COMMUNES.zip
Le fichier “FiLoSoFi” utilisé détaille les communes ainsi que les arrondissements des grandes villes.
salaire <- read_xls("FILO_DEC_COM.xls", sheet = 2, skip = 5) %>%
# garder uniquement les variables d'intérêt
select(1:2, 8)salaire %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| CODGEO | LIBGEO | Q215 |
|---|---|---|
| 01001 | L’Abergement-Clémenciat | 21776 |
| 01002 | L’Abergement-de-Varey | 23300 |
| 01004 | Ambérieu-en-Bugey | 19420 |
| 01005 | Ambérieux-en-Dombes | 23254 |
| 01007 | Ambronay | 21946 |
| 01008 | Ambutrix | 24324 |
| 01009 | Andert-et-Condon | 23022 |
| 01010 | Anglefort | 22462 |
| 01011 | Apremont | 22138 |
| 01012 | Aranc | 21448 |
Renommer les colonnes pour plus de clarté.
Distribution des salaires médians par commune.
ggplot(salaire, aes(x = salaire_median)) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution du salaire médian",
caption = "Source : INSEE",
x = "Salaire Médian Annuel",
y = "Densité")La courbe étant légèrement asymétrique, on peut appliquer une transformation logarithmique pour la corriger.
ggplot(salaire, aes(x = log(salaire_median))) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution du salaire médian",
subtitle = "(transformation logarithmique)",
caption = "Source : INSEE",
x = "Salaire Médian Annuel (transformation logarithmique)",
y = "Densité")Données : Structure de la population par commune (hors Mayotte).
Source : INSEE
Fichier : https://www.insee.fr/fr/statistiques/fichier/3564100/base-cc-evol-struct-pop-2015.zip
Le fichier nécessite l’exploitation de 2 onglets : 1 onglet pour les communes et 1 onglet pour les arrondissements de Paris, Lyon et Marseille.
pop_commune <- read_xls("base-cc-evol-struct-pop-2015.xls", sheet = 1, skip = 5) %>%
select(1, 4:5)
# onglet ne regroupant que les arrondissements
pop_arrond <- read_xls("base-cc-evol-struct-pop-2015.xls", sheet = 3, skip = 5) %>%
select(1, 4:5)pop_commune %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| CODGEO | LIBGEO | P15_POP |
|---|---|---|
| 01001 | L’Abergement-Clémenciat | 767 |
| 01002 | L’Abergement-de-Varey | 241 |
| 01004 | Ambérieu-en-Bugey | 14127 |
| 01005 | Ambérieux-en-Dombes | 1619 |
| 01006 | Ambléon | 109 |
| 01007 | Ambronay | 2615 |
| 01008 | Ambutrix | 747 |
| 01009 | Andert-et-Condon | 342 |
| 01010 | Anglefort | 1133 |
| 01011 | Apremont | 390 |
Avant de regrouper les 2 dataframes, vérifions les données des communes pour Paris, Lyon et Marseille.
# pop_commune contenant 'Paris'
pop_commune %>%
filter(str_detect(string = LIBGEO, pattern = "Paris")) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
row_spec(4, bold = T, color = "white", background = "#65ADC2")| CODGEO | LIBGEO | P15_POP |
|---|---|---|
| 38485 | Seyssinet-Pariset | 12264 |
| 62826 | Le Touquet-Paris-Plage | 4285 |
| 71343 | Paris-l’Hôpital | 296 |
| 75056 | Paris | 2206488 |
| 81202 | Parisot | 959 |
| 82137 | Parisot | 591 |
| 95176 | Cormeilles-en-Parisis | 23661 |
| 95241 | Fontenay-en-Parisis | 1949 |
# pop_arrond contenant 'Paris' : population totale de tous les arrondissements
pop_arrond %>%
filter(str_detect(string = LIBGEO, pattern = "Paris")) %>%
summarise(sum(P15_POP)) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| sum(P15_POP) |
|---|
| 2206488 |
# pop_commune contenant 'Lyon'
pop_commune %>%
filter(str_detect(string = LIBGEO, pattern = "Lyon")) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
row_spec(5, bold = T, color = "white", background = "#65ADC2")| CODGEO | LIBGEO | P15_POP |
|---|---|---|
| 03080 | Cognat-Lyonne | 716 |
| 27048 | Beauficel-en-Lyons | 192 |
| 27377 | Lyons-la-Forêt | 735 |
| 42059 | Chazelles-sur-Lyon | 5219 |
| 69123 | Lyon | 513275 |
| 69202 | Sainte-Foy-lès-Lyon | 21978 |
| 76067 | Beauvoir-en-Lyons | 637 |
# pop_arrond contenant 'Lyon' : population totale de tous les arrondissements
pop_arrond %>%
filter(str_detect(string = LIBGEO, pattern = "Lyon")) %>%
summarise(sum(P15_POP)) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| sum(P15_POP) |
|---|
| 513275 |
# pop_commune contenant 'Marseille'
pop_commune %>%
filter(str_detect(string = LIBGEO, pattern = "Marseille")) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
row_spec(2, bold = T, color = "white", background = "#65ADC2")| CODGEO | LIBGEO | P15_POP |
|---|---|---|
| 11220 | Marseillette | 713 |
| 13055 | Marseille | 861635 |
| 18139 | Marseilles-lès-Aubigny | 660 |
| 60387 | Marseille-en-Beauvaisis | 1466 |
# pop_arrond contenant 'Marseille' : population totale de tous les arrondissements
pop_arrond %>%
filter(str_detect(string = LIBGEO, pattern = "Marseille")) %>%
summarise(sum(P15_POP)) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| sum(P15_POP) |
|---|
| 861635 |
Les populations totales des arrondissements correspondent aux populations du fichier des communes.
Il faut donc supprimer les 3 villes pour ne pas cumuler les données entre les villes et les arrondissements.
# regrouper les 2 dataframes communes + arrondissements
pop_complet <- pop_commune %>%
filter(!LIBGEO %in% c("Paris", "Lyon", "Marseille")) %>%
bind_rows(pop_arrond)Renommer les colonnes pour plus de clarté.
pop_complet %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| code | commune | population |
|---|---|---|
| 01001 | L’Abergement-Clémenciat | 767 |
| 01002 | L’Abergement-de-Varey | 241 |
| 01004 | Ambérieu-en-Bugey | 14127 |
| 01005 | Ambérieux-en-Dombes | 1619 |
| 01006 | Ambléon | 109 |
| 01007 | Ambronay | 2615 |
| 01008 | Ambutrix | 747 |
| 01009 | Andert-et-Condon | 342 |
| 01010 | Anglefort | 1133 |
| 01011 | Apremont | 390 |
Distribution de la population par commune.
ggplot(pop_complet, aes(x = population)) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution de la population",
caption = "Source : INSEE",
x = "Population",
y = "Densité")L’asymétrie de la courbe est très positive. Une transformation logarithmique peut corriger celle-ci.
ggplot(pop_complet, aes(x = log(population))) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution de la population",
subtitle = "(transformation logarithmique)",
caption = "Source : INSEE",
x = "Population (transformation logarithmique)",
y = "Densité")## Warning: Removed 6 rows containing non-finite values (stat_density).
Lors de l’affichage du graphe, on peut voir un “warning” : 6 observations ont été supprimées.
En effet, on peut noter que certaines communes présentes dans le fichier n’ont pas d’habitant.
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0 198 451 1868 1135 471941
Ces communes n’ont pas d’utilité pour l’analyse en cluster, et on supprimera ces observations.
Enfin, le nombre d’observations concernant la population est plus important que celui des salaires, ce qui signifierait qu’il manquerait des données dans le tableau des salaires médians.
Ceci est confirmé par 2 notes, présentes dans le fichier “FiLoSoFi” :
Les données issues de Filosofi sont soumises au secret statistique. Aucune statistique n’est diffusée sur les très petites zones (moins de 50 ménages et moins de 100 personnes).
Les résultats sur les revenus déclarés portent sur la France métropolitaine, la Martinique et La Réunion.
writeLines(c(
paste("nb observations population :", nrow(pop_complet)),
paste("nb observations salaire :", nrow(salaire))
))## nb observations population : 35441
## nb observations salaire : 32248
Encore une fois, ces observations ayant des données manquantes seront supprimées (ce qui conduira à un clustering partiel de la France, ne prennant pas en compte les toutes petites communes et certains départements d’outre-mer).
Données : Résidences principales par type de logement, nombre de pièces et statut d’occupation par commune (hors Mayotte).
Source : INSEE
Fichier : https://insee.fr/fr/statistiques/fichier/3561683/BTX_TD_PRINC2_2015.zip
Comme pour les données de population, 2 onglets sont nécessaires à l’analyse.
logement_commune <- read_xls("BTX_TD_PRINC2_2015.xls", sheet = 1, skip = 10)
logement_arrond <- read_xls("BTX_TD_PRINC2_2015.xls", sheet = 2, skip = 10)Comme précédemment, les 3 villes Paris, Lyon et Marseille sont supprimées et remplacées par les données d’arrondissements.
# regrouper les 2 dataframes communes et arrondissements
logement_complet <- logement_commune %>%
filter(!LIBGEO %in% c("Paris", "Lyon", "Marseille")) %>%
bind_rows(logement_arrond)Comme précisé dans le préambule, on s’intéresse ici au nombre de pièces par logement, information qu’il faudra extraire à partir du nom des colonnes.
D’après la description du fichier, chaque colonne représente le nombre de logements correspondant à 3 critères : Type de logement, nombre de pièces et statut d’occupation.
logement_complet %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
scroll_box(width = "800px")| CODGEO | LIBGEO | NBPIR1_STOCD10_TYPLR1 | NBPIR1_STOCD10_TYPLR2 | NBPIR1_STOCD10_TYPLR3 | NBPIR1_STOCD21_TYPLR1 | NBPIR1_STOCD21_TYPLR2 | NBPIR1_STOCD21_TYPLR3 | NBPIR1_STOCD22_TYPLR1 | NBPIR1_STOCD22_TYPLR2 | NBPIR1_STOCD22_TYPLR3 | NBPIR1_STOCD23_TYPLR1 | NBPIR1_STOCD23_TYPLR2 | NBPIR1_STOCD23_TYPLR3 | NBPIR1_STOCD30_TYPLR1 | NBPIR1_STOCD30_TYPLR2 | NBPIR1_STOCD30_TYPLR3 | NBPIR2_STOCD10_TYPLR1 | NBPIR2_STOCD10_TYPLR2 | NBPIR2_STOCD10_TYPLR3 | NBPIR2_STOCD21_TYPLR1 | NBPIR2_STOCD21_TYPLR2 | NBPIR2_STOCD21_TYPLR3 | NBPIR2_STOCD22_TYPLR1 | NBPIR2_STOCD22_TYPLR2 | NBPIR2_STOCD22_TYPLR3 | NBPIR2_STOCD23_TYPLR1 | NBPIR2_STOCD23_TYPLR2 | NBPIR2_STOCD23_TYPLR3 | NBPIR2_STOCD30_TYPLR1 | NBPIR2_STOCD30_TYPLR2 | NBPIR2_STOCD30_TYPLR3 | NBPIR3_STOCD10_TYPLR1 | NBPIR3_STOCD10_TYPLR2 | NBPIR3_STOCD10_TYPLR3 | NBPIR3_STOCD21_TYPLR1 | NBPIR3_STOCD21_TYPLR2 | NBPIR3_STOCD21_TYPLR3 | NBPIR3_STOCD22_TYPLR1 | NBPIR3_STOCD22_TYPLR2 | NBPIR3_STOCD22_TYPLR3 | NBPIR3_STOCD23_TYPLR1 | NBPIR3_STOCD23_TYPLR2 | NBPIR3_STOCD23_TYPLR3 | NBPIR3_STOCD30_TYPLR1 | NBPIR3_STOCD30_TYPLR2 | NBPIR3_STOCD30_TYPLR3 | NBPIR4_STOCD10_TYPLR1 | NBPIR4_STOCD10_TYPLR2 | NBPIR4_STOCD10_TYPLR3 | NBPIR4_STOCD21_TYPLR1 | NBPIR4_STOCD21_TYPLR2 | NBPIR4_STOCD21_TYPLR3 | NBPIR4_STOCD22_TYPLR1 | NBPIR4_STOCD22_TYPLR2 | NBPIR4_STOCD22_TYPLR3 | NBPIR4_STOCD23_TYPLR1 | NBPIR4_STOCD23_TYPLR2 | NBPIR4_STOCD23_TYPLR3 | NBPIR4_STOCD30_TYPLR1 | NBPIR4_STOCD30_TYPLR2 | NBPIR4_STOCD30_TYPLR3 | NBPIR5_STOCD10_TYPLR1 | NBPIR5_STOCD10_TYPLR2 | NBPIR5_STOCD10_TYPLR3 | NBPIR5_STOCD21_TYPLR1 | NBPIR5_STOCD21_TYPLR2 | NBPIR5_STOCD21_TYPLR3 | NBPIR5_STOCD22_TYPLR1 | NBPIR5_STOCD22_TYPLR2 | NBPIR5_STOCD22_TYPLR3 | NBPIR5_STOCD23_TYPLR1 | NBPIR5_STOCD23_TYPLR2 | NBPIR5_STOCD23_TYPLR3 | NBPIR5_STOCD30_TYPLR1 | NBPIR5_STOCD30_TYPLR2 | NBPIR5_STOCD30_TYPLR3 | NBPIR6_STOCD10_TYPLR1 | NBPIR6_STOCD10_TYPLR2 | NBPIR6_STOCD10_TYPLR3 | NBPIR6_STOCD21_TYPLR1 | NBPIR6_STOCD21_TYPLR2 | NBPIR6_STOCD21_TYPLR3 | NBPIR6_STOCD22_TYPLR1 | NBPIR6_STOCD22_TYPLR2 | NBPIR6_STOCD22_TYPLR3 | NBPIR6_STOCD23_TYPLR1 | NBPIR6_STOCD23_TYPLR2 | NBPIR6_STOCD23_TYPLR3 | NBPIR6_STOCD30_TYPLR1 | NBPIR6_STOCD30_TYPLR2 | NBPIR6_STOCD30_TYPLR3 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 1.0000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 1.0000000 | 0.000000 | 0 | 0.0000000 | 2.000000 | 0 | 0.0000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0 | 0.000000 | 0 | 12.0000000 | 0.000000 | 0 | 4.000000 | 1.0000000 | 0.0000000 | 1.000000 | 1.000000 | 0.00000 | 1.000000 | 0.000000 | 0 | 1.000000 | 0.00000 | 0 | 81.000000 | 0.0000000 | 0 | 13.000000 | 0.0000000 | 0 | 5.000000 | 0.000000 | 0.000000 | 0.0000000 | 0 | 1 | 0.000000 | 0.000000 | 0 | 78.00000 | 0.0000000 | 0 | 8.000000 | 0.0000000 | 0.00000 | 1.000000 | 0.000000 | 0.00000 | 0 | 0.00000 | 0 | 0.000000 | 0.00000 | 0.000000 | 87.00000 | 0.000000 | 0 | 3.000000 | 0.0000000 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 4.000000 | 0.000000 | 0 |
| 01002 | L’Abergement-de-Varey | 0.9917695 | 0.000000 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.9917695 | 0.000000 | 0 | 0.9917695 | 0.000000 | 0 | 0.9917695 | 0.000000 | 0 | 0.0000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0 | 0.000000 | 0 | 8.9259259 | 0.000000 | 0 | 2.975309 | 0.0000000 | 0.0000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0 | 1.983539 | 0.00000 | 0 | 26.777778 | 0.0000000 | 0 | 2.975309 | 0.0000000 | 0 | 0.000000 | 0.000000 | 0.000000 | 0.0000000 | 0 | 0 | 0.000000 | 0.000000 | 0 | 17.85185 | 0.0000000 | 0 | 1.983539 | 0.0000000 | 0.00000 | 0.000000 | 0.000000 | 0.00000 | 0 | 0.00000 | 0 | 0.000000 | 0.00000 | 0.000000 | 29.75309 | 0.000000 | 0 | 2.975309 | 0.0000000 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 |
| 01004 | Ambérieu-en-Bugey | 0.0000000 | 7.799411 | 0 | 3.629871 | 48.021239 | 0.000000 | 0 | 41.924628 | 6.163389 | 0 | 61.63389 | 12.32678 | 0.0000000 | 0.000000 | 0 | 32.3185693 | 84.015143 | 0 | 18.9276487 | 345.479840 | 0 | 3.2405 | 176.221245 | 0 | 0.000000 | 4.174706 | 0 | 0 | 4.700004 | 0 | 227.4336724 | 234.489279 | 0 | 97.706249 | 679.9019978 | 0.8297069 | 11.221212 | 488.259468 | 1.00688 | 4.263550 | 14.473823 | 0 | 16.491343 | 45.08151 | 0 | 737.738070 | 159.4795995 | 0 | 172.463266 | 230.7610328 | 0 | 55.249405 | 323.477598 | 4.059661 | 4.7000038 | 0 | 0 | 26.821953 | 31.914108 | 0 | 701.20125 | 57.9025125 | 0 | 131.067630 | 28.5788643 | 1.00688 | 12.817450 | 100.601475 | 2.01376 | 0 | 1.00688 | 0 | 13.147587 | 20.48387 | 1.000002 | 644.46895 | 12.128550 | 0 | 52.579363 | 15.8710708 | 0 | 10.60128 | 14.77484 | 0.000000 | 0 | 0 | 0.000000 | 9.077170 | 2.070135 | 0 |
| 01005 | Ambérieux-en-Dombes | 0.0000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 | 2.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 2.0000000 | 7.000000 | 0 | 1.0000000 | 19.000000 | 0 | 0.0000 | 6.000000 | 0 | 0.000000 | 1.000000 | 0 | 0 | 0.000000 | 0 | 26.0000000 | 9.000000 | 0 | 7.000000 | 19.0000000 | 0.0000000 | 0.000000 | 6.000000 | 0.00000 | 0.000000 | 1.000000 | 0 | 2.000000 | 0.00000 | 0 | 124.000000 | 9.0000000 | 1 | 18.000000 | 16.0000000 | 0 | 3.000000 | 9.000000 | 0.000000 | 0.0000000 | 0 | 0 | 1.000000 | 0.000000 | 0 | 132.00000 | 1.0000000 | 0 | 16.000000 | 3.0000000 | 0.00000 | 0.000000 | 4.000000 | 0.00000 | 0 | 0.00000 | 0 | 1.000000 | 2.00000 | 0.000000 | 157.00000 | 3.000000 | 0 | 9.000000 | 1.0000000 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 |
| 01006 | Ambléon | 0.0000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 1.9818182 | 0.000000 | 0 | 0.9909091 | 0.000000 | 0 | 0.0000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0 | 0.000000 | 0 | 0.9909091 | 0.000000 | 0 | 4.954546 | 0.9909091 | 0.0000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0 | 0.000000 | 0.00000 | 0 | 4.954546 | 0.9909091 | 0 | 1.981818 | 0.9909091 | 0 | 0.000000 | 0.000000 | 0.000000 | 0.9909091 | 0 | 0 | 0.000000 | 0.000000 | 0 | 15.85455 | 0.9909091 | 0 | 2.972727 | 0.9909091 | 0.00000 | 0.000000 | 0.000000 | 0.00000 | 0 | 0.00000 | 0 | 0.000000 | 0.00000 | 0.000000 | 11.89091 | 0.000000 | 0 | 0.000000 | 0.0000000 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 |
| 01007 | Ambronay | 3.0523513 | 1.017433 | 0 | 1.017433 | 2.034867 | 1.017433 | 0 | 1.017433 | 0.000000 | 0 | 0.00000 | 0.00000 | 1.0174334 | 1.017433 | 0 | 4.0698357 | 1.017484 | 0 | 2.0348668 | 24.418606 | 0 | 0.0000 | 14.244068 | 0 | 0.000000 | 0.000000 | 0 | 0 | 3.052351 | 0 | 55.9608280 | 5.087218 | 0 | 19.332307 | 20.3492806 | 0.0000000 | 0.000000 | 22.384148 | 0.00000 | 1.017433 | 0.000000 | 0 | 3.052453 | 0.00000 | 0 | 209.603839 | 3.0523513 | 0 | 42.735674 | 11.1926863 | 0 | 0.000000 | 20.350506 | 0.000000 | 0.0000000 | 0 | 0 | 3.052351 | 0.000000 | 0 | 268.62478 | 1.0175355 | 0 | 25.438439 | 7.1227485 | 0.00000 | 1.017535 | 9.158381 | 0.00000 | 0 | 0.00000 | 0 | 2.035071 | 0.00000 | 0.000000 | 240.13874 | 0.000000 | 0 | 13.228931 | 0.0000000 | 0 | 0.00000 | 1.01774 | 0.000000 | 0 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 |
| 01008 | Ambutrix | 2.0639771 | 0.000000 | 0 | 1.031989 | 0.000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 4.1279543 | 1.031989 | 0 | 3.0824042 | 6.178370 | 0 | 0.0000 | 6.151425 | 0 | 1.031989 | 2.063977 | 0 | 0 | 0.000000 | 0 | 14.3398822 | 1.018427 | 0 | 12.302672 | 2.0368540 | 0.0000000 | 0.000000 | 4.060503 | 0.00000 | 0.000000 | 0.000000 | 0 | 1.031989 | 0.00000 | 0 | 78.024460 | 0.0000000 | 0 | 15.157011 | 2.0100874 | 0 | 1.018427 | 1.970638 | 0.000000 | 0.0000000 | 0 | 0 | 1.005044 | 1.018427 | 0 | 74.94152 | 0.0000000 | 0 | 14.058105 | 0.0000000 | 0.00000 | 0.000000 | 0.000000 | 0.00000 | 0 | 0.00000 | 0 | 0.000000 | 0.00000 | 0.000000 | 52.27208 | 0.000000 | 0 | 6.998125 | 0.9532461 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 1.018427 | 0.000000 | 0 |
| 01009 | Andert-et-Condon | 1.0122656 | 0.000000 | 0 | 0.000000 | 1.014914 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 1.0122656 | 0.000000 | 0 | 1.0135890 | 0.000000 | 0 | 0.0000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0 | 0.000000 | 0 | 8.1047434 | 0.000000 | 0 | 3.042094 | 3.0407669 | 0.0000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0 | 1.014914 | 0.00000 | 0 | 25.338413 | 1.0122656 | 0 | 1.012266 | 5.0679466 | 0 | 0.000000 | 0.000000 | 0.000000 | 1.0122656 | 0 | 0 | 1.012266 | 0.000000 | 0 | 27.40005 | 0.0000000 | 0 | 2.029830 | 1.0122656 | 0.00000 | 0.000000 | 0.000000 | 0.00000 | 0 | 0.00000 | 0 | 1.014914 | 0.00000 | 0.000000 | 54.76699 | 0.000000 | 0 | 3.050058 | 0.0000000 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 1.014914 | 0.000000 | 0 |
| 01010 | Anglefort | 1.0161435 | 0.000000 | 0 | 0.000000 | 1.016144 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 3.0484305 | 1.016144 | 0 | 3.0484305 | 3.048430 | 0 | 0.0000 | 3.048430 | 0 | 1.016144 | 1.016144 | 0 | 0 | 0.000000 | 0 | 38.6134529 | 5.080718 | 0 | 8.129148 | 3.0484305 | 0.0000000 | 2.032287 | 3.048430 | 0.00000 | 3.048430 | 0.000000 | 0 | 0.000000 | 0.00000 | 0 | 116.856502 | 3.0484305 | 0 | 16.258296 | 3.0484305 | 0 | 3.048430 | 11.177578 | 0.000000 | 0.0000000 | 0 | 0 | 1.016144 | 0.000000 | 0 | 106.69507 | 1.0161435 | 0 | 10.161435 | 4.0645740 | 0.00000 | 8.129148 | 6.096861 | 0.00000 | 0 | 0.00000 | 0 | 1.016144 | 0.00000 | 0.000000 | 87.38834 | 1.016144 | 0 | 5.080718 | 1.0161435 | 0 | 0.00000 | 3.04843 | 1.016144 | 0 | 0 | 1.016144 | 0.000000 | 0.000000 | 0 |
| 01011 | Apremont | 0.0000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0.00000 | 0.00000 | 0.0000000 | 0.000000 | 0 | 0.0000000 | 0.000000 | 0 | 0.0000000 | 3.111702 | 0 | 0.0000 | 0.000000 | 0 | 0.000000 | 0.000000 | 0 | 0 | 0.000000 | 0 | 3.1117021 | 0.000000 | 0 | 1.037234 | 4.1489362 | 0.0000000 | 1.037234 | 0.000000 | 0.00000 | 0.000000 | 2.074468 | 0 | 0.000000 | 0.00000 | 0 | 35.265957 | 2.0744681 | 0 | 2.074468 | 1.0372340 | 0 | 3.111702 | 2.074468 | 0.000000 | 0.0000000 | 0 | 0 | 1.037234 | 0.000000 | 0 | 37.34043 | 0.0000000 | 0 | 1.037234 | 0.0000000 | 0.00000 | 4.148936 | 1.037234 | 0.00000 | 0 | 0.00000 | 0 | 0.000000 | 0.00000 | 0.000000 | 47.71277 | 0.000000 | 0 | 0.000000 | 2.0744681 | 0 | 0.00000 | 0.00000 | 0.000000 | 0 | 0 | 0.000000 | 1.037234 | 0.000000 | 0 |
Dans un premier temps, on peut calculer le nombre total de logements par commune ET nombre de pièces par logement.
logement_nb_pieces <- logement_complet %>%
gather(key = "type", value = "value", NBPIR1_STOCD10_TYPLR1:NBPIR6_STOCD30_TYPLR3) %>%
mutate(nb_pieces = str_remove(string = type, pattern = "_\\w+")) %>%
group_by(CODGEO, LIBGEO, nb_pieces) %>%
summarise(nb_logement = sum(value)) %>%
ungroup() %>%
mutate(nb_pieces = parse_number(nb_pieces))
logement_nb_pieces %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| CODGEO | LIBGEO | nb_pieces | nb_logement |
|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 1 | 1.000000 |
| 01001 | L’Abergement-Clémenciat | 2 | 3.000000 |
| 01001 | L’Abergement-Clémenciat | 3 | 21.000000 |
| 01001 | L’Abergement-Clémenciat | 4 | 100.000000 |
| 01001 | L’Abergement-Clémenciat | 5 | 87.000000 |
| 01001 | L’Abergement-Clémenciat | 6 | 94.000000 |
| 01002 | L’Abergement-de-Varey | 1 | 1.983539 |
| 01002 | L’Abergement-de-Varey | 2 | 1.983539 |
| 01002 | L’Abergement-de-Varey | 3 | 13.884774 |
| 01002 | L’Abergement-de-Varey | 4 | 29.753086 |
Puis, calculer le nombre de pièces moyen par logement et par commune.
logement_ok <- logement_nb_pieces %>%
group_by(CODGEO, LIBGEO) %>%
summarise(nb_pieces_moyen = sum((nb_pieces * nb_logement)) / sum(nb_logement)) %>%
rename(code = CODGEO,
commune = LIBGEO)
logement_ok %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| code | commune | nb_pieces_moyen |
|---|---|---|
| 01001 | L’Abergement-Clémenciat | 4.800654 |
| 01002 | L’Abergement-de-Varey | 4.613861 |
| 01004 | Ambérieu-en-Bugey | 3.822448 |
| 01005 | Ambérieux-en-Dombes | 4.567961 |
| 01006 | Ambléon | 4.603774 |
| 01007 | Ambronay | 4.539916 |
| 01008 | Ambutrix | 4.384836 |
| 01009 | Andert-et-Condon | 4.859620 |
| 01010 | Anglefort | 4.502155 |
| 01011 | Apremont | 4.820000 |
Distribution du nombre de pièces moyen par logement par commune.
ggplot(logement_ok, aes(x = nb_pieces_moyen)) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution du nombre moyen de pièces par logement",
caption = "Source : INSEE",
x = "Nombre moyen de pièces par logement",
y = "Densité")## Warning: Removed 6 rows containing non-finite values (stat_density).
La courbe étant légèrement asymétrique négative, on peut appliquer une transformation cubique pour la corriger.
ggplot(logement_ok, aes(x = nb_pieces_moyen^3)) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution du nombre moyen de pièces par logement",
subtitle = "(transformation cubique)",
caption = "Source : INSEE",
x = "Nombre moyen de pièces par logement (transformation cubique)",
y = "Densité")## Warning: Removed 6 rows containing non-finite values (stat_density).
Données : Indicateur d’accessibilité potentielle localisée (APL) 2015 aux médecins généralistes par commune (hors Mayotte).
Source : DREES
Fichier : Indicateur d’accessibilité potentielle localisée (APL) 2015 aux médecins généralistes (rechercher “accessibilité potentielle localisée” sur le site de la DREES)
Le premier onglet détaille les communes ainsi que les arrondissements des grandes villes.
sante <- read_xls(path = "accessibilité_potentielle_localisée_2015.xls", sheet = 1, skip = 7) %>%
select(1:3)sante %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| Code commune INSEE | Commune | APL aux médecins généralistes |
|---|---|---|
| NA | NA | En nombre de consultations/visites accessibles par habitant standardisé |
| 01001 | L’ Abergement-Clémenciat | 2.3969999999999998 |
| 01002 | L’ Abergement-de-Varey | 2.8340000000000001 |
| 01004 | Ambérieu-en-Bugey | 4.5449999999999999 |
| 01005 | Ambérieux-en-Dombes | 4.5449999999999999 |
| 01006 | Ambléon | 1.0960000000000001 |
| 01007 | Ambronay | 4.968 |
| 01008 | Ambutrix | 4.2430000000000003 |
| 01009 | Andert-et-Condon | 4.4710000000000001 |
| 01010 | Anglefort | 1.9299999999999999 |
Renommer les colonnes pour plus de clarté, et supprimer la première ligne inutile.
sante <- sante %>%
filter(!is.na(Commune)) %>%
rename(code = `Code commune INSEE`,
commune = Commune,
apl_med_gener = `APL aux médecins généralistes`) %>%
mutate(apl_med_gener = as.numeric(apl_med_gener))Distribution de l’indicateur d’APL par commune.
ggplot(sante, aes(x = apl_med_gener)) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution de l'indicateur d'APL",
caption = "Source : DREES",
x = "Indicateur d'accessibilité potentielle localisée (APL)",
y = "Densité")La courbe étant très asymétrique positive, on peut appliquer une transformation par racine cubique pour la corriger.
ggplot(sante, aes(x = apl_med_gener^(1/3))) +
geom_density(fill = "#65ADC2", alpha = 0.7) +
labs(title = "Distribution de l'indicateur d'APL",
subtitle = "(transformation racine cubique)",
caption = "Source : DREES",
x = "Indicateur d'Accessibilité Potentielle Localisée (APL)\n(transformation racine cubique)",
y = "Densité")Les donnés précédentes peuvent maintenant être regroupées en un seul dataframe.
Comme évoqué précédemment, certaines communes seront supprimées par manque de données.
# regroupement de toutes les données
cluster_data <- list(salaire, pop_complet, logement_ok, sante) %>%
reduce(left_join, by = "code")cluster_data %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
scroll_box(width = "800px")| code | commune.x | salaire_median | commune.y | population | commune.x.x | nb_pieces_moyen | commune.y.y | apl_med_gener |
|---|---|---|---|---|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 21776 | L’Abergement-Clémenciat | 767 | L’Abergement-Clémenciat | 4.800654 | L’ Abergement-Clémenciat | 2.397 |
| 01002 | L’Abergement-de-Varey | 23300 | L’Abergement-de-Varey | 241 | L’Abergement-de-Varey | 4.613861 | L’ Abergement-de-Varey | 2.834 |
| 01004 | Ambérieu-en-Bugey | 19420 | Ambérieu-en-Bugey | 14127 | Ambérieu-en-Bugey | 3.822448 | Ambérieu-en-Bugey | 4.545 |
| 01005 | Ambérieux-en-Dombes | 23254 | Ambérieux-en-Dombes | 1619 | Ambérieux-en-Dombes | 4.567961 | Ambérieux-en-Dombes | 4.545 |
| 01007 | Ambronay | 21946 | Ambronay | 2615 | Ambronay | 4.539916 | Ambronay | 4.968 |
| 01008 | Ambutrix | 24324 | Ambutrix | 747 | Ambutrix | 4.384836 | Ambutrix | 4.243 |
| 01009 | Andert-et-Condon | 23022 | Andert-et-Condon | 342 | Andert-et-Condon | 4.859620 | Andert-et-Condon | 4.471 |
| 01010 | Anglefort | 22462 | Anglefort | 1133 | Anglefort | 4.502155 | Anglefort | 1.930 |
| 01011 | Apremont | 22138 | Apremont | 390 | Apremont | 4.820000 | Apremont | 1.745 |
| 01012 | Aranc | 21448 | Aranc | 327 | Aranc | 4.625850 | Aranc | 1.486 |
Quatre colonnes de noms de communes ont été créées : certaines communes n’ont donc pas un nom commun entre toutes les bases de données.
Ainsi, seul le premier nom issu d’une base de données INSEE sera conservé (colonne commune.x provenant du fichier “FiLoSoFi”).
# nettoyer le nom des communes
cluster_data <- cluster_data %>%
select(-commune.y, -commune.x.x, -commune.y.y) %>%
rename(commune = commune.x)
cluster_data %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| code | commune | salaire_median | population | nb_pieces_moyen | apl_med_gener |
|---|---|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 21776 | 767 | 4.800654 | 2.397 |
| 01002 | L’Abergement-de-Varey | 23300 | 241 | 4.613861 | 2.834 |
| 01004 | Ambérieu-en-Bugey | 19420 | 14127 | 3.822448 | 4.545 |
| 01005 | Ambérieux-en-Dombes | 23254 | 1619 | 4.567961 | 4.545 |
| 01007 | Ambronay | 21946 | 2615 | 4.539916 | 4.968 |
| 01008 | Ambutrix | 24324 | 747 | 4.384836 | 4.243 |
| 01009 | Andert-et-Condon | 23022 | 342 | 4.859620 | 4.471 |
| 01010 | Anglefort | 22462 | 1133 | 4.502155 | 1.930 |
| 01011 | Apremont | 22138 | 390 | 4.820000 | 1.745 |
| 01012 | Aranc | 21448 | 327 | 4.625850 | 1.486 |
Comme précisé précédemment, certaines observations sont supprimées car il manque des données.
## [1] 31828 6
L’étude de cluster sera donc faite sur un total de 31828 communes et arrondissements.
Données : Base officielle des codes postaux, incluant les coordonnées GPS pour chaque commune.
Source : La Poste
Fichier : https://datanova.legroupe.laposte.fr/explore/dataset/laposte_hexasmal/download/?format=csv&timezone=Europe/Berlin&use_labels_for_header=true
Ces coordonnées serviront à visualiser les communes et leur cluster associé sur une carte.
## Using ',' as decimal and '.' as grouping mark. Use read_delim() for more control.
## Parsed with column specification:
## cols(
## Code_commune_INSEE = col_character(),
## Nom_commune = col_character(),
## Code_postal = col_double(),
## Libelle_acheminement = col_character(),
## Ligne_5 = col_character(),
## coordonnees_gps = col_character()
## )
gps_coord %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| Code_commune_INSEE | Nom_commune | Code_postal | Libelle_acheminement | Ligne_5 | coordonnees_gps |
|---|---|---|---|---|---|
| 90078 | PETITEFONTAINE | 90360 | PETITEFONTAINE | NA | 47.7237763721, 7.00757336099 |
| 90089 | ROUGEMONT LE CHATEAU | 90110 | ROUGEMONT LE CHATEAU | NA | 47.7460113941, 6.95212889734 |
| 90091 | ST GERMAIN LE CHATELET | 90110 | ST GERMAIN LE CHATELET | NA | 47.7002701756, 6.96114583666 |
| 90093 | SERMAMAGNY | 90300 | SERMAMAGNY | NA | 47.687801557, 6.8309146345 |
| 90105 | VILLARS LE SEC | 90100 | VILLARS LE SEC | NA | 47.4554088507, 6.98803547043 |
| 91016 | ANGERVILLE | 91670 | ANGERVILLE | NA | 48.3095627706, 2.00619112268 |
| 91022 | ARRANCOURT | 91690 | ARRANCOURT | NA | 48.3267041104, 2.15155534916 |
| 91093 | BOULLAY LES TROUX | 91470 | BOULLAY LES TROUX | NA | 48.6753515056, 2.04828313772 |
| 91100 | BOUVILLE | 91880 | BOUVILLE | NA | 48.4326483441, 2.2783856422 |
| 91109 | BRIERES LES SCELLES | 91150 | BRIERES LES SCELLES | NA | 48.4636769085, 2.14290097216 |
Certaines coordonnées GPS sont manquantes, et peuvent être complétées manuellement.
gps_coord %>%
select(-Ligne_5) %>%
filter_all(any_vars(is.na(.))) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
scroll_box(height = "400px")| Code_commune_INSEE | Nom_commune | Code_postal | Libelle_acheminement | coordonnees_gps |
|---|---|---|---|---|
| 97701 | ST BARTHELEMY | 97133 | ST BARTHELEMY | NA |
| 98711 | ANAA | 98786 | HITIANAU | NA |
| 98713 | ARUTUA | 98761 | RAUTINI | NA |
| 98717 | FANGATAU | 98765 | TEANA | NA |
| 98720 | HAO | 98790 | AMANU | NA |
| 98720 | HAO | 98790 | TEANOGA | NA |
| 98722 | HITIAA O TE RA | 98706 | MAHAENA | NA |
| 98722 | HITIAA O TE RA | 98708 | TIAREI | NA |
| 98724 | HUAHINE | 98731 | MAEVA | NA |
| 98724 | HUAHINE | 98731 | PAREA | NA |
| 98726 | MAKEMO | 98790 | HITI | NA |
| 98728 | MAUPITI | 98732 | MOPELIA | NA |
| 98729 | MOOREA MAIAO | 98728 | TIAIA | NA |
| 98729 | MOOREA MAIAO | 98729 | PIHAENA | NA |
| 98731 | NUKU HIVA | 98742 | NUKUATAHA | NA |
| 98731 | NUKU HIVA | 98796 | EIAO | NA |
| 98732 | NUKUTAVAKE | 98788 | TEMANUFAARA | NA |
| 98740 | RANGIROA | 98777 | PAHUA | NA |
| 98741 | RAPA | 98751 | AHUREI | NA |
| 98743 | RIMATARA | 98752 | AMARU | NA |
| 98743 | RIMATARA | 98795 | MARIA ILOTS | NA |
| 98744 | RURUTU | 98753 | HAUTI | NA |
| 98745 | TAHAA | 98733 | PATIO | NA |
| 98745 | TAHAA | 98733 | RUUTIA | NA |
| 98745 | TAHAA | 98733 | TIVA | NA |
| 98745 | TAHAA | 98734 | POUTORU | NA |
| 98745 | TAHAA | 98734 | VAITOARE | NA |
| 98746 | TAHUATA | 98743 | VAITAHU | NA |
| 98747 | TAIARAPU EST | 98721 | PUEU | NA |
| 98749 | TAKAROA | 98790 | TIKEI | NA |
| 98750 | TAPUTAPUATEA | 98735 | OPOA | NA |
| 98752 | TEVA I UTA | 98726 | MATAIEA | NA |
| 98756 | UA HUKA | 98744 | VAIPAEE | NA |
| 98758 | UTUROA | 98735 | UTUROA | NA |
| 98802 | BOULOUPARI | 98812 | BOULOUPARIS | NA |
| 98808 | HOUAILOU | 98816 | HOUAILOU | NA |
| 98812 | KOUMAC | 98850 | KOUMAC | NA |
| 98813 | LA FOA | 98880 | LA FOA | NA |
| 98817 | LE MONT DORE | 98810 | MONT DORE | NA |
| 98819 | OUEGOA | 98821 | OUEGOA | NA |
| 98822 | POINDIMIE | 98822 | POINDIMIE | NA |
| 98824 | POUEBO | 98824 | POUEBO | NA |
| 98832 | YATE | 98834 | YATE | NA |
| 98833 | KOUAOUA | 98818 | KOUAOUA | NA |
| 97801 | ST MARTIN | 97150 | ST MARTIN | NA |
| 98713 | ARUTUA | 98762 | NIUTAHI | NA |
| 98716 | FAKARAVA | 98763 | ROTOAVA | NA |
| 98718 | FATU HIVA | 98740 | OMOA | NA |
| 98719 | GAMBIER | 98755 | ANGAKAUITAI | NA |
| 98719 | GAMBIER | 98755 | AUKENA | NA |
| 98719 | GAMBIER | 98755 | MANGAREVA | NA |
| 98719 | GAMBIER | 98755 | MANIUI | NA |
| 98719 | GAMBIER | 98792 | MORANE | NA |
| 98720 | HAO | 98790 | HEREHRETUE | NA |
| 98720 | HAO | 98790 | MANUHANGI | NA |
| 98720 | HAO | 98790 | AHUNUI | NA |
| 98721 | HIKUERU | 98768 | TUPAPATI | NA |
| 98721 | HIKUERU | 98790 | MOTUTAPU | NA |
| 98721 | HIKUERU | 98790 | TEPEPERU | NA |
| 98723 | HIVA OA | 98741 | HANAPAOA | NA |
| 98723 | HIVA OA | 98749 | PUAMAU | NA |
| 98723 | HIVA OA | 98796 | FATU HUKU | NA |
| 98724 | HUAHINE | 98732 | AVERA | NA |
| 98726 | MAKEMO | 98789 | HITIANAU | NA |
| 98729 | MOOREA MAIAO | 98728 | AFAREAITU | NA |
| 98729 | MOOREA MAIAO | 98728 | MAATEA | NA |
| 98730 | NAPUKA | 98772 | TEPUKAMARUIA | NA |
| 98731 | NUKU HIVA | 98742 | AAKAPA | NA |
| 98731 | NUKU HIVA | 98748 | HATIHEU | NA |
| 98735 | PAPEETE | 98714 | PAPEETE | NA |
| 98737 | PUKAPUKA | 98774 | TEONEMAHINA | NA |
| 98741 | RAPA | 98794 | MAROTIRI | NA |
| 98744 | RURUTU | 98753 | AVERA | NA |
| 98745 | TAHAA | 98733 | TAHAA | NA |
| 98745 | TAHAA | 98733 | HIPU | NA |
| 98745 | TAHAA | 98734 | HAAMENE | NA |
| 98745 | TAHAA | 98734 | FAAAHA | NA |
| 98746 | TAHUATA | 98743 | HAPATONI | NA |
| 98746 | TAHUATA | 98743 | HANATETENA | NA |
| 98754 | TUMARAA | 98735 | TEHURUI | NA |
| 98755 | TUREIA | 98784 | FAKAMARU | NA |
| 98757 | UA POU | 98745 | HAKAHETAU | NA |
| 98757 | UA POU | 98745 | HAKAHAU | NA |
| 98757 | UA POU | 98746 | HAKAMAII | NA |
| 98808 | HOUAILOU | 98838 | PORO | NA |
| 98811 | KONE | 98859 | KONE | NA |
| 98818 | NOUMEA | 98800 | NOUMEA | NA |
| 98827 | POYA | 98827 | POYA | NA |
| 98828 | SARRAMEA | 98882 | SARRAMEA | NA |
| 98831 | VOH | 98833 | VOH | NA |
| 97501 | MIQUELON LANGLADE | 97500 | ST PIERRE ET MIQUELON | NA |
| 98611 | ALO | 98610 | ALO | NA |
| 98712 | ARUE | 98701 | ARUE | NA |
| 98713 | ARUTUA | 98785 | RAITAHITI | NA |
| 98714 | BORA BORA | 98730 | ANAU | NA |
| 98714 | BORA BORA | 98730 | FAANUI | NA |
| 98714 | BORA BORA | 98730 | NUNUE | NA |
| 98716 | FAKARAVA | 98787 | TEARAVERO | NA |
| 98719 | GAMBIER | 98755 | MAKAROA | NA |
| 98719 | GAMBIER | 98792 | MOTUREIVAVAO | NA |
| 98719 | GAMBIER | 98792 | TEMOE | NA |
| 98719 | GAMBIER | 98792 | TENARARO | NA |
| 98719 | GAMBIER | 98793 | MARUTEA SUD | NA |
| 98720 | HAO | 98767 | OTEPA | NA |
| 98720 | HAO | 98790 | HIKITAKE | NA |
| 98720 | HAO | 98790 | OTETOU | NA |
| 98722 | HITIAA O TE RA | 98707 | PAPENOO | NA |
| 98723 | HIVA OA | 98741 | EIAONE | NA |
| 98723 | HIVA OA | 98741 | MOTU UA | NA |
| 98723 | HIVA OA | 98741 | NAHOE | NA |
| 98723 | HIVA OA | 98741 | PAUMAU | NA |
| 98724 | HUAHINE | 98731 | FAIE | NA |
| 98724 | HUAHINE | 98731 | FITII | NA |
| 98724 | HUAHINE | 98731 | HAAPU | NA |
| 98725 | MAHINA | 98709 | MAHINA | NA |
| 98725 | MAHINA | 98710 | OROFARA | NA |
| 98726 | MAKEMO | 98769 | POUHEVA | NA |
| 98726 | MAKEMO | 98790 | TUANAKE | NA |
| 98728 | MAUPITI | 98732 | SCILLY | NA |
| 98729 | MOOREA MAIAO | 98728 | MAHAREPA | NA |
| 98729 | MOOREA MAIAO | 98728 | TEAVARO | NA |
| 98729 | MOOREA MAIAO | 98728 | VAIARE | NA |
| 98729 | MOOREA MAIAO | 98729 | ATIHA | NA |
| 98729 | MOOREA MAIAO | 98729 | HAAPITI | NA |
| 98729 | MOOREA MAIAO | 98729 | PAOPAO | NA |
| 98731 | NUKU HIVA | 98742 | TAIOHAE | NA |
| 98731 | NUKU HIVA | 98796 | HATU ITI | NA |
| 98731 | NUKU HIVA | 98796 | HATUTAA | NA |
| 98733 | PAEA | 98711 | PAEA | NA |
| 98734 | PAPARA | 98712 | PAPARA | NA |
| 98738 | PUNAAUIA | 98718 | PUNAAUIA | NA |
| 98740 | RANGIROA | 98790 | VAITEPAUA | NA |
| 98742 | REAO | 98779 | TAPUARAVA | NA |
| 98743 | RIMATARA | 98752 | ANAPOTO | NA |
| 98743 | RIMATARA | 98752 | MUTUAURA | NA |
| 98745 | TAHAA | 98734 | NIUA | NA |
| 98747 | TAIARAPU EST | 98719 | TARAVAO | NA |
| 98748 | TAIARAPU OUEST | 98723 | TEAHUPOO | NA |
| 98750 | TAPUTAPUATEA | 98735 | AVERA | NA |
| 98751 | TATAKOTO | 98783 | TUMUKURU | NA |
| 98753 | TUBUAI | 98754 | TAAHUAIA | NA |
| 98754 | TUMARAA | 98735 | TUMARAA | NA |
| 98754 | TUMARAA | 98735 | FETUNA | NA |
| 98801 | BELEP | 98811 | BELEP | NA |
| 98803 | BOURAIL | 98870 | BOURAIL | NA |
| 98805 | DUMBEA | 98836 | DUMBEA GA | NA |
| 98806 | FARINO | 98881 | FARINO | NA |
| 98807 | HIENGHENE | 98815 | HIENGHENE | NA |
| 98809 | L ILE DES PINS | 98832 | VAO | NA |
| 98811 | KONE | 98860 | KONE | NA |
| 98817 | LE MONT DORE | 98875 | PLUM | NA |
| 98817 | LE MONT DORE | 98876 | LA COULEE | NA |
| 98821 | PAITA | 98840 | TONTOUTA | NA |
| 98829 | THIO | 98829 | THIO | NA |
| 98901 | ILE DE CLIPPERTON | 98799 | ILE DE CLIPPERTON | NA |
| 55138 | CULEY | 55000 | CULEY | NA |
| 76095 | BIHOREL | 76420 | BIHOREL | NA |
| 97501 | MIQUELON LANGLADE | 97500 | ST PIERRE ET MIQUELON | NA |
| 97502 | ST PIERRE | 97500 | ST PIERRE ET MIQUELON | NA |
| 98612 | SIGAVE | 98620 | SIGAVE | NA |
| 98613 | UVEA | 98600 | UVEA | NA |
| 98711 | ANAA | 98760 | TUUHORA | NA |
| 98714 | BORA BORA | 98730 | VAITAPE | NA |
| 98716 | FAKARAVA | 98790 | OFARE | NA |
| 98717 | FANGATAU | 98766 | TARIONE | NA |
| 98719 | GAMBIER | 98755 | KAMAKA | NA |
| 98719 | GAMBIER | 98755 | RIKITEA | NA |
| 98719 | GAMBIER | 98755 | TARAVAI | NA |
| 98719 | GAMBIER | 98792 | TENARUNGA | NA |
| 98720 | HAO | 98790 | NENGONENGO | NA |
| 98720 | HAO | 98790 | PARAOA | NA |
| 98722 | HITIAA O TE RA | 98705 | HITIAA | NA |
| 98723 | HIVA OA | 98796 | MOHOTANI | NA |
| 98724 | HUAHINE | 98731 | TEFARERII | NA |
| 98724 | HUAHINE | 98731 | FARE | NA |
| 98726 | MAKEMO | 98790 | MARUTEA NORD | NA |
| 98726 | MAKEMO | 98790 | TEPOTO SUD | NA |
| 98727 | MANIHI | 98770 | TENOKUPARA | NA |
| 98728 | MAUPITI | 98732 | MAUPITI | NA |
| 98728 | MAUPITI | 98732 | MOTU ONE | NA |
| 98729 | MOOREA MAIAO | 98728 | HAUMI | NA |
| 98729 | MOOREA MAIAO | 98728 | PAOPAO | NA |
| 98729 | MOOREA MAIAO | 98729 | TIAHURA | NA |
| 98729 | MOOREA MAIAO | 98729 | VARARI | NA |
| 98731 | NUKU HIVA | 98742 | TAIPIVAI | NA |
| 98739 | RAIVAVAE | 98750 | ANATONU | NA |
| 98740 | RANGIROA | 98775 | AVATORU | NA |
| 98740 | RANGIROA | 98776 | TIPUTA | NA |
| 98740 | RANGIROA | 98778 | TUHERAHERA | NA |
| 98742 | REAO | 98780 | MARAUTAGAROA | NA |
| 98743 | RIMATARA | 98752 | RIMATARA | NA |
| 98744 | RURUTU | 98753 | MOERAI | NA |
| 98745 | TAHAA | 98733 | IRIPAU | NA |
| 98746 | TAHUATA | 98743 | MOTOPU | NA |
| 98749 | TAKAROA | 98781 | TEAVAROA | NA |
| 98749 | TAKAROA | 98782 | FAKATOPATERE | NA |
| 98753 | TUBUAI | 98754 | MATAURA | NA |
| 98757 | UA POU | 98745 | HAKATAO | NA |
| 98805 | DUMBEA | 98839 | DUMBEA | NA |
| 98810 | KAALA GOMEN | 98817 | KAALA GOMEN | NA |
| 98814 | LIFOU | 98820 | WE | NA |
| 98814 | LIFOU | 98884 | CHEPENEHE | NA |
| 98815 | MARE | 98828 | TADINE | NA |
| 98815 | MARE | 98878 | LA ROCHE | NA |
| 98816 | MOINDOU | 98819 | MOINDOU | NA |
| 98817 | LE MONT DORE | 98809 | MONT DORE | NA |
| 98817 | LE MONT DORE | 98874 | PONT DES FRANCAIS | NA |
| 98821 | PAITA | 98890 | PAITA | NA |
| 98823 | PONERIHOUEN | 98823 | PONERIHOUEN | NA |
| 98825 | POUEMBOUT | 98825 | POUEMBOUT | NA |
| 98831 | VOH | 98883 | OUACO | NA |
| 99138 | MONACO | 98000 | MONACO | NA |
| 98711 | ANAA | 98790 | TEPUPAHEA | NA |
| 98715 | FAAA | 98704 | FAAA | NA |
| 98716 | FAKARAVA | 98764 | PAPARARA | NA |
| 98716 | FAKARAVA | 98790 | TOAU | NA |
| 98716 | FAKARAVA | 98790 | MOTU TAPU | NA |
| 98718 | FATU HIVA | 98740 | HANAVAVE | NA |
| 98719 | GAMBIER | 98755 | AKAMARU | NA |
| 98719 | GAMBIER | 98792 | VAHANGA | NA |
| 98719 | GAMBIER | 98792 | MARIA EST | NA |
| 98721 | HIKUERU | 98790 | RAVAHERE | NA |
| 98721 | HIKUERU | 98790 | MAHETIKA | NA |
| 98723 | HIVA OA | 98741 | HANAIAPA | NA |
| 98723 | HIVA OA | 98741 | ATUONA | NA |
| 98724 | HUAHINE | 98731 | HUAHINE | NA |
| 98724 | HUAHINE | 98731 | MAROE | NA |
| 98726 | MAKEMO | 98790 | GARUMAOA | NA |
| 98726 | MAKEMO | 98790 | HARAIKI | NA |
| 98726 | MAKEMO | 98790 | HENUAPAREA | NA |
| 98726 | MAKEMO | 98790 | OTATAKE | NA |
| 98727 | MANIHI | 98771 | TURIPAOA | NA |
| 98729 | MOOREA MAIAO | 98728 | TEMAE | NA |
| 98729 | MOOREA MAIAO | 98729 | MAIAO | NA |
| 98729 | MOOREA MAIAO | 98729 | HAURU | NA |
| 98729 | MOOREA MAIAO | 98729 | OPUNOHU | NA |
| 98729 | MOOREA MAIAO | 98729 | PAPETOAI | NA |
| 98729 | MOOREA MAIAO | 98729 | VAIANAE | NA |
| 98731 | NUKU HIVA | 98742 | TERRE DESERTE | NA |
| 98732 | NUKUTAVAKE | 98773 | TAVAVA | NA |
| 98736 | PIRAE | 98716 | PIRAE | NA |
| 98738 | PUNAAUIA | 98703 | PUNAAUIA | NA |
| 98739 | RAIVAVAE | 98750 | MAHANATOA | NA |
| 98739 | RAIVAVAE | 98750 | RAIRUA | NA |
| 98739 | RAIVAVAE | 98750 | VAIURU | NA |
| 98745 | TAHAA | 98733 | TAPUAMU | NA |
| 98747 | TAIARAPU EST | 98719 | AFAAHITI | NA |
| 98747 | TAIARAPU EST | 98720 | FAAONE | NA |
| 98747 | TAIARAPU EST | 98722 | TAUTIRA | NA |
| 98748 | TAIARAPU OUEST | 98724 | TOAHOTU | NA |
| 98748 | TAIARAPU OUEST | 98725 | VAIRAO | NA |
| 98750 | TAPUTAPUATEA | 98735 | TAPUTAPUATEA | NA |
| 98750 | TAPUTAPUATEA | 98735 | PUOHINE | NA |
| 98752 | TEVA I UTA | 98727 | PAPEARI | NA |
| 98753 | TUBUAI | 98754 | MAHU | NA |
| 98754 | TUMARAA | 98735 | TEVAITOA | NA |
| 98756 | UA HUKA | 98747 | HANE | NA |
| 98757 | UA POU | 98745 | HOHOI | NA |
| 98757 | UA POU | 98746 | HAAKUTI | NA |
| 98804 | CANALA | 98813 | CANALA | NA |
| 98805 | DUMBEA | 98830 | DUMBEA | NA |
| 98805 | DUMBEA | 98835 | DUMBEA | NA |
| 98805 | DUMBEA | 98837 | DUMBEA | NA |
| 98814 | LIFOU | 98885 | MOU | NA |
| 98820 | OUVEA | 98814 | FAYAOUE | NA |
| 98821 | PAITA | 98889 | PAITA | NA |
| 98826 | POUM | 98826 | POUM | NA |
| 98827 | POYA | 98877 | NEPOUI | NA |
| 98830 | TOUHO | 98831 | TOUHO | NA |
Dans le résultat précédent, on ne prend pas en compte les département 975 (Saint-Pierre-et-Miquelon), 977 (Saint-Barthélémy), 978 (Saint-Martin), 986 (Wallis-et-Futuna), 987 (Polynésie Française), 988 (Nouvelle-Calédonie), 989 (Île de Clipperton), 991 (Monaco, qui est également inclus dans cette liste).
gps_coord %>%
select(-Ligne_5) %>%
filter_all(any_vars(is.na(.))) %>%
filter(!str_sub(Code_commune_INSEE, start = 1, end = 3) %in% c(975:978, 986:991)) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| Code_commune_INSEE | Nom_commune | Code_postal | Libelle_acheminement | coordonnees_gps |
|---|---|---|---|---|
| 55138 | CULEY | 55000 | CULEY | NA |
| 76095 | BIHOREL | 76420 | BIHOREL | NA |
Finalement, il manque les coordonnées GPS pour uniquement 2 communes.
Par Wikipédia, on peut obtenir celles-ci.
gps_coord$coordonnees_gps[which(gps_coord$Code_commune_INSEE == 55138)] <- "48.7553,5.2664"
gps_coord$coordonnees_gps[which(gps_coord$Code_commune_INSEE == 76095)] <- "49.4552777778,1.11694444444"De plus, une erreur est présente dans le fichier de La Poste (code INSEE pour la commune de Cans et Cévennes).
# code INSEE du fichier de cluster
cluster_data %>%
filter(commune == "Cans et Cévennes") %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| code | commune | salaire_median | population | nb_pieces_moyen | apl_med_gener |
|---|---|---|---|---|---|
| 48166 | Cans et Cévennes | 16302 | 280 | 4.048119 | 0.733 |
# code INSEE du fichier gps
gps_coord %>%
filter(Nom_commune == "CANS ET CEVENNES") %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| Code_commune_INSEE | Nom_commune | Code_postal | Libelle_acheminement | Ligne_5 | coordonnees_gps |
|---|---|---|---|---|---|
| 48162 | CANS ET CEVENNES | 48400 | CANS ET CEVENNES | ST JULIEN D ARPAON | 44.301436191, 3.68067181243 |
| 48162 | CANS ET CEVENNES | 48400 | CANS ET CEVENNES | ST LAURENT DE TREVES | 44.301436191, 3.68067181243 |
# corriger le code INSEE
gps_coord$Code_commune_INSEE[which(gps_coord$Code_commune_INSEE == 48162)] <- "48166"Les erreurs étant corrigées, on peut maintenant garder uniquement le code INSEE, et séparer longitude et latitude.
gps_coord_ok <- gps_coord %>%
separate(col = coordonnees_gps, into = c("latitude", "longitude"), sep = ",", convert = TRUE) %>%
select(code = Code_commune_INSEE, latitude, longitude) %>%
# supprimer les lignes identiques
distinct()gps_coord_ok %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| code | latitude | longitude |
|---|---|---|
| 90078 | 47.72378 | 7.007573 |
| 90089 | 47.74601 | 6.952129 |
| 90091 | 47.70027 | 6.961146 |
| 90093 | 47.68780 | 6.830915 |
| 90105 | 47.45541 | 6.988035 |
| 91016 | 48.30956 | 2.006191 |
| 91022 | 48.32670 | 2.151555 |
| 91093 | 48.67535 | 2.048283 |
| 91100 | 48.43265 | 2.278386 |
| 91109 | 48.46368 | 2.142901 |
Ajouter ces données aux données de cluster.
cluster_data <- left_join(cluster_data, gps_coord_ok, by = "code")
cluster_data %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| code | commune | salaire_median | population | nb_pieces_moyen | apl_med_gener | latitude | longitude |
|---|---|---|---|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 21776 | 767 | 4.800654 | 2.397 | 46.15343 | 4.926113 |
| 01002 | L’Abergement-de-Varey | 23300 | 241 | 4.613861 | 2.834 | 46.00919 | 5.428017 |
| 01004 | Ambérieu-en-Bugey | 19420 | 14127 | 3.822448 | 4.545 | 45.96085 | 5.372926 |
| 01005 | Ambérieux-en-Dombes | 23254 | 1619 | 4.567961 | 4.545 | 45.99618 | 4.912273 |
| 01007 | Ambronay | 21946 | 2615 | 4.539916 | 4.968 | 46.00559 | 5.357607 |
| 01008 | Ambutrix | 24324 | 747 | 4.384836 | 4.243 | 45.93671 | 5.332809 |
| 01009 | Andert-et-Condon | 23022 | 342 | 4.859620 | 4.471 | 45.78736 | 5.657883 |
| 01010 | Anglefort | 22462 | 1133 | 4.502155 | 1.930 | 45.90937 | 5.795160 |
| 01011 | Apremont | 22138 | 390 | 4.820000 | 1.745 | 46.20550 | 5.657815 |
| 01012 | Aranc | 21448 | 327 | 4.625850 | 1.486 | 46.00153 | 5.511306 |
Dans une analyse en clusters, les données étudiées doivent être dans un même ordre de grandeur (pour éviter les effets d’échelle).
De plus, on peut maintenant appliquer les transformations évoquées précédemment pour éviter l’asymétrie des données.
cluster_data <- cluster_data %>%
# transformer les variables d'intérêt et les mettre à l'échelle
mutate(salaire_trans = log(salaire_median) %>% scale(),
population_trans = log(population) %>% scale(),
nb_pieces_moyen_trans = nb_pieces_moyen^3 %>% scale(),
apl_med_gener_trans = apl_med_gener^(1/3) %>% scale())
cluster_data %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
scroll_box(width = "800px")| code | commune | salaire_median | population | nb_pieces_moyen | apl_med_gener | latitude | longitude | salaire_trans | population_trans | nb_pieces_moyen_trans | apl_med_gener_trans |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 21776 | 767 | 4.800654 | 2.397 | 46.15343 | 4.926113 | 0.4561985 | 0.1413015 | 0.75882080 | -0.6400148 |
| 01002 | L’Abergement-de-Varey | 23300 | 241 | 4.613861 | 2.834 | 46.00919 | 5.428017 | 0.8684241 | -0.7985801 | 0.15715596 | -0.2799087 |
| 01004 | Ambérieu-en-Bugey | 19420 | 14127 | 3.822448 | 4.545 | 45.96085 | 5.372926 | -0.2415906 | 2.5065377 | -1.89553424 | 0.8510503 |
| 01005 | Ambérieux-en-Dombes | 23254 | 1619 | 4.567961 | 4.545 | 45.99618 | 4.912273 | 0.8563812 | 0.7478232 | 0.01654500 | 0.8510503 |
| 01007 | Ambronay | 21946 | 2615 | 4.539916 | 4.968 | 46.00559 | 5.357607 | 0.5035879 | 1.1370737 | -0.06799112 | 1.0847889 |
| 01008 | Ambutrix | 24324 | 747 | 4.384836 | 4.243 | 45.93671 | 5.332809 | 1.1305263 | 0.1198508 | -0.51687367 | 0.6751427 |
| 01009 | Andert-et-Condon | 23022 | 342 | 4.859620 | 4.471 | 45.78736 | 5.657883 | 0.7952778 | -0.5144181 | 0.95877424 | 0.8086856 |
| 01010 | Anglefort | 22462 | 1133 | 4.502155 | 1.930 | 45.90937 | 5.795160 | 0.6452122 | 0.4580383 | -0.18017195 | -1.0771100 |
| 01011 | Apremont | 22138 | 390 | 4.820000 | 1.745 | 46.20550 | 5.657815 | 0.5566705 | -0.4077917 | 0.82388663 | -1.2698537 |
| 01012 | Aranc | 21448 | 327 | 4.625850 | 1.486 | 46.00153 | 5.511306 | 0.3637102 | -0.5508304 | 0.19434726 | -1.5640943 |
Pour l’étude, on peut garder uniquement les dernières variables créées.
cluster_data_trans <- cluster_data %>%
select(ends_with("trans")) %>%
# arrondir les données à 6 chiffres après la virgule (facilite le calcul par la suite)
mutate_all(.funs = round, 6)
cluster_data_trans %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| salaire_trans | population_trans | nb_pieces_moyen_trans | apl_med_gener_trans |
|---|---|---|---|
| 0.456199 | 0.141301 | 0.758821 | -0.640015 |
| 0.868424 | -0.798580 | 0.157156 | -0.279909 |
| -0.241591 | 2.506538 | -1.895534 | 0.851050 |
| 0.856381 | 0.747823 | 0.016545 | 0.851050 |
| 0.503588 | 1.137074 | -0.067991 | 1.084789 |
| 1.130526 | 0.119851 | -0.516874 | 0.675143 |
| 0.795278 | -0.514418 | 0.958774 | 0.808686 |
| 0.645212 | 0.458038 | -0.180172 | -1.077110 |
| 0.556671 | -0.407792 | 0.823887 | -1.269854 |
| 0.363710 | -0.550830 | 0.194347 | -1.564094 |
A noter que ces variables sont faiblement corrélées entre elles.
cor(cluster_data_trans) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") | salaire_trans | population_trans | nb_pieces_moyen_trans | apl_med_gener_trans | |
|---|---|---|---|---|
| salaire_trans | 1.0000000 | 0.1631673 | 0.2656236 | 0.1018078 |
| population_trans | 0.1631673 | 1.0000000 | -0.4630667 | 0.2869713 |
| nb_pieces_moyen_trans | 0.2656236 | -0.4630667 | 1.0000000 | -0.0106943 |
| apl_med_gener_trans | 0.1018078 | 0.2869713 | -0.0106943 | 1.0000000 |
A partir de ces données, l’analyse en clusters va permettre de regrouper certaines observations “similaires” entre elles.
library(cluster) # 'clusGap' : optimal nb of clusters
library(mclust) # 'Mclust' : optimal nb of clustersDans cette étude, le nombre de cluster est inconnu. Il faut donc déterminer celui-ci.
Une première méthode pour définir le nombre de clusters est une méhode graphique.
En utilisant l’algoroithme “k-means”, on peut calculer la variabilité intra-classe pour différentes valeurs du nombre de clusters, et trouver la valeur optimale.
# calculer la variabilité intra-classe pour différentes valeurs du nombre de clusters
total_wss <- map_dbl(1:15, function(k) {
set.seed(42)
# utiliser l'algorithme "MacQueen" pour ne pas avoir d'erreur 'Quick-TRANSfer'
# cf 'https://stackoverflow.com/questions/21382681/kmeans-quick-transfer-stage-steps-exceeded-maximum'
model <- kmeans(x = cluster_data_trans, centers = k, nstart = 25, iter.max = 1000, algorithm = "MacQueen")
model$tot.withinss
})A partir du résultat précédent, on peut construire un graphe de la variabilité.
# dataframe pour le 'scree plot'
scree_df <- tibble(k = 1:15,
total_wss = total_wss)
# graphe
ggplot(scree_df, aes(x = k, y = total_wss)) +
geom_line() +
scale_x_continuous(breaks = 1:15) +
labs(title = "Nombre optimal de cluster : Scree Plot",
y = "Variabilité intra-classe",
x = "k : nombre de clusters")Il n’y a pas de coupure nette dans le graphe précédent. Il est donc difficile de déterminer clairement un nombre de clusters optimal.
(3 clusters pourraient être envisagés).
Une seconde méthode analytique permet de définir le nombre optimal de cluster, celle-ci étant basée sur le “Model-Based Clustering”".
# Run the function to see how many clusters
# it finds to be optimal, set it to search for
# at least 1 model and up 15
d_clust <- Mclust(data = as.matrix(cluster_data_trans), G = 1:15)On peut extraire le nombre optimal de clusters.
## [1] 11
Graphiquement.
La valeur optimale grâce à cette méthode est 11 clusters.
Enfin, une autre méthode analytique permet de définir le nombre optimal de cluster grâce au “Gap Statistic”.
set.seed(42)
# Calculer le "gap statistic"
# /!\ prend beaucoup de temps
gap_stat <- clusGap(x = cluster_data_trans,
FUN = kmeans, nstart = 25, iter.max = 1000, algorithm = "MacQueen",
K.max = 15,
# l'aide de la fonction suggère 'd.power = 2'
# pour coller à l'algorithme original
d.power = 2)Le nombre de clusters optimal est obtenu par la valeur ayant le “gap” le plus élevé.
## Clustering Gap statistic ["clusGap"] from call:
## clusGap(x = cluster_data_trans, FUNcluster = kmeans, K.max = 15, d.power = 2, nstart = 25, iter.max = 1000, algorithm = "MacQueen")
## B=100 simulated reference sets, k = 1..15; spaceH0="scaledPCA"
## --> Number of clusters (method 'firstSEmax', SE.factor=1): 1
## logW E.logW gap SE.sim
## [1,] 11.061217 13.37242 2.311206 0.002744345
## [2,] 10.792294 13.07419 2.281900 0.002768225
## [3,] 10.576905 12.87178 2.294872 0.002782200
## [4,] 10.449506 12.70729 2.257785 0.003033572
## [5,] 10.340185 12.57504 2.234852 0.002777165
## [6,] 10.248864 12.44556 2.196691 0.002490338
## [7,] 10.169177 12.35429 2.185112 0.002464986
## [8,] 10.108539 12.26010 2.151565 0.002608635
## [9,] 10.049673 12.21554 2.165870 0.002636028
## [10,] 9.992070 12.17266 2.180595 0.002622199
## [11,] 9.946553 12.13505 2.188498 0.002620389
## [12,] 9.901682 12.09659 2.194911 0.002617518
## [13,] 9.859172 12.06154 2.202364 0.002565799
## [14,] 9.825021 12.02651 2.201486 0.003044200
## [15,] 9.793214 11.99413 2.200918 0.002369348
Graphiquement.
gap_stat$Tab %>%
as_tibble() %>%
ggplot(aes(x = 1:15, y = gap)) +
geom_line() +
geom_point() +
geom_errorbar(aes(ymin = gap - SE.sim, ymax = gap + SE.sim), width = 0.3) +
scale_x_continuous(breaks = 1:15) +
labs(title = "Nombre optimal de cluster : Gap Statistic",
y = "Gap Statistic",
x = "Nombre de clusters")Ainsi, la valeur optimale est de 1 cluster ; ceci signifierait que les données telles que présentées ne sont pas réellement adaptées à une étude de clusters.
Passons outre ; si on considère qu’avoir un seul et unique cluster n’est pas très utile, il apparaît que 3 clusters semble la valeur optimale.
Les données vont donc être étudiées pour être classées en 3 différents clusters.
# appliquer l'algorithme de clustering en utilisant 3 clusters
set.seed(42)
kmeans_model <- kmeans(x = cluster_data_trans, centers = 3, nstart = 20)On peut ajouter le numéro de cluster au dataframe des données non-transformées.
# extraire le numéro de cluster et l'ajouter aux données non transformées
cluster_data <- cluster_data %>%
mutate(cluster = kmeans_model$cluster)
cluster_data %>%
count(cluster) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| cluster | n |
|---|---|
| 1 | 6980 |
| 2 | 12082 |
| 3 | 12766 |
Le nombre d’observations est similaire dans 2 clusters, mais le premier cluster présente largement moins de communes similaires.
Les communes de chaque cluster peuvent être isolées et chaque cluster peut ainsi être caractérisé.
cluster_data %>%
group_by(cluster) %>%
summarise(mean_median_salary = mean(salaire_median),
mean_pop = mean(population),
mean_pieces = mean(nb_pieces_moyen),
mean_apl = mean(apl_med_gener)) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left")| cluster | mean_median_salary | mean_pop | mean_pieces | mean_apl |
|---|---|---|---|---|
| 1 | 20320.45 | 7325.5254 | 4.151719 | 4.147221 |
| 2 | 22913.06 | 736.8629 | 4.795276 | 3.585307 |
| 3 | 18284.08 | 411.6623 | 4.498963 | 2.793204 |
Le premier cluster semble représenter les métropoles ayant un nombre important d’habitants. Ils ont également accès plus facilement aux soins.
Le second cluster regroupe les communes où les salaires sont les plus élevés ; cela correspont également à un nombre de pièces par logement supérieur aux 2 autres clusters.
Enfin, le dernier cluster regroupe les petites communes où l’accès aux soins semble plus compliqué et où les salaires semblent moins élevés.
Ces clusters peuvent également être cartographiés.
Il faut préalablement transformer les données dans un objet sf.
library(sf) # manipulation de données géographiques
library(tmap) # affichage des cartes
library(grid) # rearrangment des cartes
# réinitialiser le thème utilisé pour les graphes
ggthemr::ggthemr_reset()Le système de coordonnées est “WGS84”, afin de correspondre au système de cordonnées des cartes qui seront importées ultérieurement.
# transformer les données en format 'sf'
cluster_sf <- st_as_sf(x = cluster_data,
coords = c("longitude", "latitude"),
crs = 4326) # projections de coordonnées WGS84Une colonne geometry a été créée, à la place des colonnes longitude et latitude.
cluster_sf %>%
head(10) %>%
kable() %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left") %>%
scroll_box(width = "800px")| code | commune | salaire_median | population | nb_pieces_moyen | apl_med_gener | salaire_trans | population_trans | nb_pieces_moyen_trans | apl_med_gener_trans | cluster | geometry |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 01001 | L’Abergement-Clémenciat | 21776 | 767 | 4.800654 | 2.397 | 0.4561985 | 0.1413015 | 0.75882080 | -0.6400148 | 2 | c(4.92611354223, 46.1534255214) |
| 01002 | L’Abergement-de-Varey | 23300 | 241 | 4.613861 | 2.834 | 0.8684241 | -0.7985801 | 0.15715596 | -0.2799087 | 2 | c(5.42801696363, 46.0091878776) |
| 01004 | Ambérieu-en-Bugey | 19420 | 14127 | 3.822448 | 4.545 | -0.2415906 | 2.5065377 | -1.89553424 | 0.8510503 | 1 | c(5.3729257777, 45.9608475114) |
| 01005 | Ambérieux-en-Dombes | 23254 | 1619 | 4.567961 | 4.545 | 0.8563812 | 0.7478232 | 0.01654500 | 0.8510503 | 2 | c(4.91227250796, 45.9961799872) |
| 01007 | Ambronay | 21946 | 2615 | 4.539916 | 4.968 | 0.5035879 | 1.1370737 | -0.06799112 | 1.0847889 | 1 | c(5.35760660735, 46.0055913782) |
| 01008 | Ambutrix | 24324 | 747 | 4.384836 | 4.243 | 1.1305263 | 0.1198508 | -0.51687367 | 0.6751427 | 2 | c(5.3328092349, 45.9367134524) |
| 01009 | Andert-et-Condon | 23022 | 342 | 4.859620 | 4.471 | 0.7952778 | -0.5144181 | 0.95877424 | 0.8086856 | 2 | c(5.65788307924, 45.7873565333) |
| 01010 | Anglefort | 22462 | 1133 | 4.502155 | 1.930 | 0.6452122 | 0.4580383 | -0.18017195 | -1.0771100 | 2 | c(5.79516005674, 45.9093715116) |
| 01011 | Apremont | 22138 | 390 | 4.820000 | 1.745 | 0.5566705 | -0.4077917 | 0.82388663 | -1.2698537 | 2 | c(5.65781475272, 46.2054981558) |
| 01012 | Aranc | 21448 | 327 | 4.625850 | 1.486 | 0.3637102 | -0.5508304 | 0.19434726 | -1.5640943 | 3 | c(5.51130637511, 46.0015344029) |
Par défaut, les coordonnées géographiques vont faire que la carte va être très espacée : La Réunion sera positionnée à ses coordonnées d’origine et très éloignée de la métropole.
Ainsi, on va séparer les données de cluster en 3 parties : métropole, Martinique, La Réunion.
Puis, on réarrangera la disposition des 3 cartes, de sorte l’on puisse visualiser facilement toutes les données.
Importer les 3 cartes de la métropole, Martinique et La Réunion (les cartes sont disponibles ici).
metropole <- readRDS("gadm36_FRA_0_sf.rds")
martinique <- readRDS("gadm36_MTQ_0_sf.rds")
reunion <- readRDS("gadm36_REU_0_sf.rds")Séparer les données de clusters originales en 3 dataframes.
# ajouter une colonne précisant les DOM
cluster_sf <- cluster_sf %>%
mutate(
position = case_when(
str_sub(code, start = 1, end = 3) == 974 ~ "reunion",
str_sub(code, start = 1, end = 3) == 972 ~ "martinique",
TRUE ~ "metropole"
),
# transformer en 'factor' pour faciliter la cartographie
cluster = as.factor(cluster))# séparer en 3 dataframes
cluster_sf_metrop <- filter(cluster_sf, position == "metropole")
cluster_sf_reunion <- filter(cluster_sf, position == "reunion")
cluster_sf_marti <- filter(cluster_sf, position == "martinique")Exemple de carte avec les données de cluster de La Réunion.
# carte principale
tm_shape(reunion) +
tm_polygons() +
# ajouter les données de cluster
tm_shape(cluster_sf_reunion) +
tm_symbols(col = "cluster", size = 0.3, palette = viridis::viridis(n = 3, direction = -1, option = "D")) +
tm_layout(frame = FALSE,
main.title = "La Réunion",
main.title.position = "center")Création des 3 cartes avec les données de cluster.
metro_map <- tm_shape(metropole) +
tm_polygons() +
# ajouter les données de cluster
tm_shape(cluster_sf_metrop) +
tm_symbols(col = "cluster", size = 0.2, alpha = 0.7,
palette = viridis::viridis(n = 3, direction = -1, option = "D")) +
tm_layout(frame = FALSE,
main.title = "Cartographie des clusters",
main.title.position = "left",
legend.position = c("right", "top"))
marti_map <- tm_shape(martinique) +
tm_polygons() +
# ajouter les données de cluster
tm_shape(cluster_sf_marti) +
tm_symbols(col = "cluster", size = 0.2, alpha = 0.7,
palette = viridis::viridis(n = 3, direction = -1, option = "D")) +
tm_layout(frame = FALSE,
main.title = "Martinique",
main.title.size = 0.8,
main.title.position = "center",
legend.show = FALSE)
reunion_map <- tm_shape(reunion) +
tm_polygons() +
# ajouter les données de cluster
tm_shape(cluster_sf_reunion) +
tm_symbols(col = "cluster", size = 0.2, alpha = 0.7,
palette = viridis::viridis(n = 3, direction = -1, option = "D")) +
tm_layout(frame = FALSE,
main.title = "La Réunion",
main.title.size = 0.8,
main.title.position = "center",
legend.show = FALSE)Réarrangement des cartes (voir ici).
grid.newpage()
page.layout <- grid.layout(nrow = 10, ncol = 10)
pushViewport(viewport(layout = page.layout))
print(metro_map, vp = viewport(layout.pos.row = 1:10, layout.pos.col = 3:10))
print(reunion_map, vp = viewport(layout.pos.row = 5:7, layout.pos.col = 2))
print(marti_map, vp = viewport(layout.pos.row = 8:10, layout.pos.col = 2))On peut voir que le premier cluster regroupe les grandes villes, ainsi que les communes côtières (Méditerranée et Atlantique).
Le second cluster est principalement situé dans un grand quart nord-est ainsi qu’au sud-ouest.
Ces caractéristiques sont plus facilement visibles sur l’application Shiny ci-dessous.
Toutes ces données peuvent être visualisées en utilisant une application Shiny, qui permettra également de rechercher une commune en particulier et d’afficher les informations la concernant, ou d’afficher uniquement un seul cluster.
Pour cela, il faut sauvegarder toutes les informations nécessaires.
save(cluster_data, cluster_sf_marti, cluster_sf_metrop, cluster_sf_reunion, # donnees clusters
metropole, reunion, martinique, # cartes
file = "clusters.Rdata")Lien de l’application : https://ator.shinyapps.io/Clustering/