class: center, middle, inverse, title-slide # Forcats ## Une aventure dans le monde des données catégorielles ### Emmanuelle Pépin ### 30 novembre 2021 --- class: inverse, center, middle #Forcats ###Le package du Tidyverse pour le catégoriel ###(for... cats!) #### Aussi, un anagramme de factor: du pur génie! ######Aucun chat n'a été maltraité durant l'utilisation de forcats --- # Au menu 1. Variables catégorielles 2. Introduction à forcats 3. Commencer avec des factors 4. Exploration des données 5. Associations des données 6. Changement de l'ordre 7. Changement des valeurs 8. Ajout et élimination de classes 9. Conclusion --- # Variables catégorielles ## Survol rapide **Qu'est-ce qu'un facteur?** - Variable qualitative Variable ayant pour valeur un niveau,une catégorie, se trouvant dans une liste (pré)définie de possibilités. - Ordinale Peut être mise en ordre - Nominale N'a pas de hiérarchie - Binaire n'a que deux valeurs (excluant le NA) En statistique, cela inclu les variables booléennes, vrai ou faux et tout autre variable à 2 choix (dichotomiques) (H/F, Y/N). \ Dans R, il est possible de changer la classe en fonction de nos besoins en tout temps. --- # Variables catégorielles ## Vocabulaire - **Factor** Facteur, variable catégorielle, variable qualitative -- - **Levels** Niveaux: catégories prédéfinies, ce que l'on voit Par défaut: en ordre alphabétique -- - **Integer** Nombre entier différent/propre à chaque niveau: ce qui est traité par R En arrière/en mémoire... -- - **Vector** Vecteur, souvent utilisé pour donner les valeurs et leur ordre Écrit: `c(...)` --- #Variables catégorielles ## Attention aux pièges! - **Les chiffres** Un chiffre utilisé à des fins nominale avec ou sans ordre/hiérarchie significative, mais sans être sur une échelle CONTINUE peut être considéré comme une variable catégorielle. Ex.: Un numéro de téléphone est catégoriel, la moyenne d'un numéro de téléphone n'est pas une donnée pertinente. -- - **Il ne s'agit PAS de chaînes de caractères** Ici, les données (mots, série de caractères) que l'on voit sur l'interface cachent un nombre entier. Si vous avez un message d'erreur concernant un "character vector", méfiez-vous... -- - Les chaînes de caractères sont traitées avec stringr - Les facteurs sont traités avec forcats Il est toutefois possible d'utiliser des vecteurs de caractères dans les facteurs... --- #Pourquoi forcats? ## ou pourquoi R aime-t-il tant les facteurs alors qu'ils sont difficiles à traiter R est fan #1 de catégoriel, la coercion vers le catégoriel est assez élevée dans l'ordre de priorité MAIS il est difficile de les traiter en base R. -- #### En base R - Utilisation de vecteur -- - Manipulation avec des séries de commandes comme subset() et l'utilisation de vecteurs pour faire le tri et se débrouiller - créatif (lire: parfois tiré par les cheveux) - Difficile à suivre = facile d'introduire des biais d'interprétation -- - Utilise le point `as.factor()` --- #Pourquoi forcats? #### Forcats - Vient remplir les lacunes de R Il n'y a donc pas d'équivalent direct pour chaque commande. -- - utilisation -d'objets et de vecteurs est possible - de la syntaxe du tidyverse - la barre en dessous `as_factor()` -- - Débute avec fct -- - Message d'erreur ou avertissement lorsqu'il manque un niveau --- class: inverse, center, middle # Commencer du bon pied --- #Pour travailler avec forcats, il faut des factors! 1. Lors de la lecture du fichier et des manipulations initiales: - Base R - L'argument: `StringAsFactor = TRUE` - Tidyverse - S'amuser avec readr: `col_factor()` -- 2. En cours de travail - Base R - `as.factor()` - Vérification avec `is.factor()` - Tidyverse - Forcats: `as_factor()` --- #Création d'un factor 1. Avoir une variable (en vecteur) ```r joursdelasemaine <- c("Mardi", "Mercredi", "Vendredi") ``` 2. Créer une liste de niveaux (toujours en vecteur) ```r niveaux_jours <- c("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi") ``` --- (suite) 3. Tout mettre ensemble: création d'un facteur Version base R: ```r jours_facteur1 <- factor(joursdelasemaine, levels = niveaux_jours) jours_facteur1 ``` ``` ## [1] Mardi Mercredi Vendredi ## Levels: Dimanche Lundi Mardi Mercredi Jeudi Vendredi Samedi ``` Version forcats: ```r jours_facteur_forcats <- as_factor(joursdelasemaine) jours_facteur_forcats ``` ``` ## [1] Mardi Mercredi Vendredi ## Levels: Mardi Mercredi Vendredi ``` --- class: inverse, center, middle #Exploration des données --- ## Exploration des données: Base R Les fonctions de base sont utiles pour une exploration initiale des données Exemple de fonctions connues et utiles: `summary()` `summary(df$variable)` `class()` --- ## Exploration des données : Forcats - `fct_count(nom_du_facteur, sort = FALSE, prop = FALSE)` Savoir combien il y a d'entrées de chaque niveaux - nom_du_facteur Variable telle qu'écrite dans vos données - sort FALSE par défaut: en ordre d'apparition TRUE: liste en nombre décroissant du nombre d'entrées - prop: Donne la fraction (proportion), facultatif ```r fct_count(jours_facteur1) ``` ``` ## # A tibble: 7 × 2 ## f n ## <fct> <int> ## 1 Dimanche 0 ## 2 Lundi 0 ## 3 Mardi 1 ## 4 Mercredi 1 ## 5 Jeudi 0 ## 6 Vendredi 1 ## 7 Samedi 0 ``` --- - `fct_match(nom_du_facteur, lvls)` Chercher la présence d'un niveau en particulier - nom_du_facteur - lvls Le nom du niveau dont cherche la présence Utiliser un vecteur si on cherche plus d'un niveau Le niveau doit être présent sinon code d'erreur ```r fct_match(jours_facteur1, "Vendredi") ``` ``` ## [1] FALSE FALSE TRUE ``` --- ## Exploration des données: duplicata Forcats - `fct_unique(nom_du_facteur)` Enlever les entrées en duplicata - Donné en ordre de niveau Il faudra utiliser base R pour avoir l'ordre d'apparition dans le vecteur -- Base R - `unique(nom_du_facteur)` - Similaire, mais donne l'ordre d'apparition dans le vecteur - Fonctionne avec d'autres types de variables --- ## Exemple: Données en duplicata Exploration et utilisation de la variable clinique Compter les entrées: ```r fct_count(Cliniques) ``` ``` ## # A tibble: 48 × 2 ## f n ## <fct> <int> ## 1 112S 74 ## 2 212N 2 ## 3 212S 1 ## 4 312N 1 ## 5 32 1 ## 6 35 1 ## 7 CH05B 1 ## 8 CH06B 1 ## 9 CH09B 1 ## 10 CH10B 2 ## # … with 38 more rows ``` --- ## Exemple: Données en duplicata Exploration et utilisation de la variable clinique Avoir les données uniques: Exemple: le mettre dans un objet ```r cliniques_uniques <- fct_unique(Cliniques) cliniques_uniques ``` ``` ## [1] 112S 212N 212S 312N 32 35 CH05B CH06B CH09B CH10B CH11B CH12B ## [13] CH14B CH15B CH19B CH20B CH23B CH26B CH37B CH48B CH49B CH51B CH54B CH60B ## [25] CH73B CH85B CS05 H117B HO02B HO06B HO07B HO09B HO11B HO13B HO15B HO18B ## [37] HO19B HO22B HO29B HO34B HO35B HO37B HO56B HO59B HO64B HO77B OBST URG ## 48 Levels: 112S 212N 212S 312N 32 35 CH05B CH06B CH09B CH10B CH11B ... URG ``` --- class: inverse, center, middle #Association de facteurs --- ## Association de facteurs avec forcats - `fct_c(facteur1, facteur2)` ou `fct_cross(facteur1, facteur2)` Combine deux facteurs avec des niveaux DIFFÉRENTS ```r #Création de deux "factors" facteur1 <- as_factor(c("Roger", "Gontrand", "Gerald")) facteur2 <- as_factor(c("Armande", "Sylvaine", "Anita")) #Combiner les deux "factor" facteursCross <- fct_c(facteur1, facteur2) #Vérification facteursCross ``` ``` ## [1] Roger Gontrand Gerald Armande Sylvaine Anita ## Levels: Roger Gontrand Gerald Armande Sylvaine Anita ``` --- ## Association de facteurs avec forcats - `fct_unify(Liste_de_facteurs, levels = lvls_union(liste_de_facteurs))` Combine deux ou plusieurs facteurs ayant certain niveaux qui sont PAREILS Utile pour harmoniser/standardiser les niveaux - liste_de_facteurs Variables à joindre ensemble *en format liste* - levels Par défaut: union de tous les niveaux Utiliser l'argument si besoin de spécifier les niveaux --- class: inverse, center, middle #Changement de l'ordre des niveaux --- ## Changement de l'ordre des niveaux avec forcats ### Méthode manuelle (un exemple suivra) - `fct_relevel(nom_du_facteur, ..., after = 0L)` - nom_du_facteur - ... Facultatif: la fonction désirée pour reclasser le niveau initial va être passé dans la fonction et le résultat à la sortie va indiquer où le niveau va être placé - after Endroit où le niveau sera placé *Ressemble à stats::relevel() qui permet de bouger des niveaux* --- ## Changement de l'ordre des niveaux avec forcats ### Méthode manuelle : Exemple! ```r lettres <- factor(c("a", "b", "c", "d", "e", "f", "g"), ) fct_relevel(lettres) ``` ``` ## [1] a b c d e f g ## Levels: a b c d e f g ``` ```r fct_relevel(lettres, "e", "a", after = Inf) ``` ``` ## [1] a b c d e f g ## Levels: b c d f g e a ``` Respecte l'ordre donné: ```r fct_relevel(lettres, "a", "e", after = Inf) ``` ``` ## [1] a b c d e f g ## Levels: b c d f g a e ``` --- ## Changement de l'ordre des niveaux avec forcats - `fct_infreq()` ou `fct_inseq()` C'est à dire in frequency/sequence - Défini par la fréquence ou la valeur numérique du niveau - `fct_inorder()` - Selon l'ordre dans lequel les niveaux apparaissent Dans les trois cas: `fct_SPECIFIER-ICI(nom_du_facteur, ordered = NA)` - nom_du_facteur - ordered Par défaut NA: garde le statut tel quel (ordonné ou non) --- ## Changement de l'ordre des niveaux avec forcats ### Ordre inverse: pratique pour les graphiques! - `fct_rev(nom_du_facteur)`* Truc pour s'en suvenir: rev pour reverse order Aussi simple que ça! Fonctionne aussi avec les character vector --- ## Changement de l'ordre des niveaux avec forcats - `fct_shift(nom_du_facteur, n = 2)` Changement d'ordre pour des données cycliques Ex.: jours de la semaine - nom_du_facteur - n = Nombre de bond de position "shift" Positif: déplacement vers la gauche Négatif: vers la droite --- ## Changement de l'ordre des niveaux avec forcats - `fct_shuffle(nom_du_facteur)` Redistribution aléatoire des niveaux Attention! La redistribution se fera à chaque fois que vous lancer votre code ```r prenoms_g <- factor(c("Gino", "Gina", "Ginette", "Bob")) fct_shuffle(prenoms_g) ``` ``` ## [1] Gino Gina Ginette Bob ## Levels: Gina Bob Ginette Gino ``` --- ## Changement de l'ordre des niveaux avec forcats ### Encore plus de plaisir: réorganisation en fonction d'autres variables - `fct_reorder()` Réorganisation des niveaux en fonction de sa relation à UNE variable -- et - `fct_reorder2()` Réorganisation des niveaux en fonction de sa relation à DEUX variables Facile et pratique à intégrer dans ggplot2! --- class: inverse, center, middle #Changement des valeurs/noms des niveaux --- ## Changement de valeurs des niveaux ### Méthode manuelle - `fct_recode(facteur_ou_vecteur, nouveau_nom = "ancien_nom")` - facteur_ou_vecteur - nouveau_nom = "ancien_nom" Séquence donnant le nouveau nom et l'associe à l'ancien niveau Par défaut: les niveaux sans précision sont gardés, NULL pour enlever les niveaux non précisés - `fct_relabel()` Résultat similaire, mais utilise les règles de purrr::map --- ## Changement de valeurs des niveaux ### Anonymisation sommaire des données Pour les données sensibles: - `fct_anon(nom_du_facteur, prefix = " ")` Remplacement du niveau par un chiffre de façon aléatoire. La valeur et l'ordre du niveau de départ ne sont PAS gardés. - nom_du_facteur - prefix = " " Permet l'ajout d'un préfixe devant le nouvel identifiant Attention! Il existe des packages et algorithmes pour une anonymisation complète et complexe des données. Certains permettent de garder les informations de transition. --- ## Changement de valeurs des niveaux ### Rassembler des niveaux manuellement - `fct_collapse(nom_du_facteur, ..., other_level = NULL, group_other = 'DEPRECATED")` Rassembler les niveaux en groupes déterminés MANUELLEMENT - nom_du_facteur - ... Vecteur des niveaux dont on veut changer les noms - other_level Niveaux qui seront classés dans "other" - group_other Pour remplacer les niveaux non mentionnés par "other" --- ## Changement de valeurs des niveaux ### Rassembler des niveaux: la famille "lump" Permet de rassembler des niveaux selon des critères Généralement, rassembler ensemble les niveaux qui apparaissent moins que n fois - `fct_lump(nom_du_facteur, n, prop, w, other_level, ties.method, min)` et ses variantes: `fct_lump_min(), fct_lump_prop(), fct_lump_n(), fct_lump_lowfreq()` où - nom_du_facteur - n Si positif: conserve les valeurs les PLUS communes Si négatif: conserve les valeurs les MOINS communes - other_level Indique la valeur à donner au niveau utilisé pour les valeurs autres - ties.method Comment traiter les niveaux ayant la même valeur - min Conserve les niveaux qui apparaissent au moins min fois --- ## Changement de valeurs des niveaux ### Rassembler des niveaux: la famille "lump" Utilisation de `fct_lump_n()` pour simplifier et avoir 10 niveaux + autres ```r CliniquesSimples <- fct_lump_n(Cliniques, 10, other_level = "Autres") CliniquesSimplesUniques<- fct_unique(CliniquesSimples) CliniquesSimplesUniques ``` ``` ## [1] 112S CH11B CH12B CH49B H117B HO02B HO06B HO13B HO15B HO64B ## [11] Autres ## 11 Levels: 112S CH11B CH12B CH49B H117B HO02B HO06B HO13B HO15B ... Autres ``` --- ## Changement de valeurs des niveaux ### Rassembler des niveaux: la catégorie autre - `fct_other(nom_du_facteur, keep, drop, other_level= "Other")` Vient compléter les fonctions précédentes Converti les niveaux spécifiés en la catégorie autre PAS besoin d'avoir moins d'entrées contrairement à lump - nom_du facteur - keep ou drop Pour garder (keep) ou enlever (drop) les niveaux inscrits dans other_level - Other_level Liste des niveaux à mettre dans "other" --- class: inverse, center, middle #Ajouter et enlever des niveaux --- ## Ajouter et enlever des niveaux Trois options: - `fct_drop(nom_du_facteur, only)` - fct_du_facteur - only Vecteur qui indique les niveaux à enlever - `fct_expand(nom_du_facteur, ...)` - nom_du_facteur - ... Niveaux à ajouter - `fct_explicit_na(nom_du_facteur, na_level = "Autre")` - nom_du_facteur - na_level Niveau à utiliser pour les valeurs manquantes, dites NA Mettre entre double guillements le nom qu e vous voulez attribuer au NA Exemple: Autre --- class: inverse, center, middle --- ## Quelques ressources: [Page de forcats dans le Tidyverse](https://forcats.tidyverse.org/) [R for Epidemiologists](https://epirhandbook.com/en/) [R for Data Sciences](https://r4ds.had.co.nz/factors.html) --- class: inverse, center, middle #Et voilà! C'est aussi simple que ça. #Fin! 