Ce chapitre est évoqué dans le webin-R #09 (Graphiques uni- et bivariés avec ggplot2) sur YouTube.

Il existe de nombreuses fonctions pour mettre en forme des nombres sous R. La fonction de base est format. Plusieurs packages proposent des variations pour rendre cette mise en forme plus facile. Cependant, s’il y a une extension à retenir, c’est l’extension scales.

number() ou label_number() ?

Les deux fonctions de base sont number et label_number. Elles ont l’air très similaires et partagent un grand nombre de paramètres en commun. La différence est que number a besoin d’un vecteur numérique en entrée qu’elle va mettre en forme, tandis que que label_number renvoie une fonction que l’on pourra ensuite appliquer à un vecteur numérique.

library(scales)
x <- c(0.0023, .123, 4.567, 874.44, 8957845)
number(x)
[1] "0.00"         "0.12"         "4.57"        
[4] "874.44"       "8 957 845.00"
f <- label_number()
f(x)
[1] "0.00"         "0.12"         "4.57"        
[4] "874.44"       "8 957 845.00"
label_number()(x)
[1] "0.00"         "0.12"         "4.57"        
[4] "874.44"       "8 957 845.00"

Dans de nombreux cas de figure (par exemple pour un graphique ggplot2 ou un tableau gtsummary), il sera demandé de fournir une fonction, auquel cas on aura recours aux fonctions de scales préfixées par label_*().

label_number()

label_number est la fonction de base de mise en forme de nombres dans scales, une majorité des autres fonctions faisant appel à label_number et partageant les mêmes arguments.

Le paramètre accurary permets de définir le niveau d’arrondi à utiliser. Par exemple, .1 pour afficher une seule décimale. Il est aussi possible d’indiquer un nombre qui n’est pas une puissance de 10 (par exemple .25). Si on n’indique rien (NULL), alors label_number essaiera de deviner un nombre de décimales pertinent en fonction des valeurs du vecteur de nombres à mettre en forme.

label_number(accuracy = NULL)(x)
[1] "0.00"         "0.12"         "4.57"        
[4] "874.44"       "8 957 845.00"
label_number(accuracy = .1)(x)
[1] "0.0"         "0.1"         "4.6"         "874.4"      
[5] "8 957 845.0"
label_number(accuracy = .25)(x)
[1] "0.0"         "0.0"         "4.5"         "874.5"      
[5] "8 957 845.0"
label_number(accuracy = 10)(x)
[1] "0"         "0"         "0"         "870"      
[5] "8 957 840"

L’option scale permets d’indiquer un facteur multiplicatif à appliquer avant de mettre en forme. On utilisera le plus souvent les options prefix et suffix en même temps pour indiquer les unités.

label_number(scale = 100, suffix = "%")(x) # pour cent
[1] "0%"           "12%"          "457%"        
[4] "87 444%"      "895 784 500%"
label_number(scale = 1000, suffix = "\u2030")(x) # pour mille
[1] "2‰"             "123‰"           "4 567‰"        
[4] "874 440‰"       "8 957 845 000‰"
label_number(scale = .001, suffix = " milliers", accuracy = .1)(x)
[1] "0.0 milliers"     "0.0 milliers"     "0.0 milliers"    
[4] "0.9 milliers"     "8 957.8 milliers"

Les arguments decimal.mark et big.mark permettent de définir, respectivement, le séparateur de décimale et le séparateur de milliers. Ainsi, pour afficher des nombres à la française (virgule pour les décimales, espace pour les milliers) :

label_number(decimal.mark = ",", big.mark = " ")(x)
[1] "0,00"         "0,12"         "4,57"        
[4] "874,44"       "8 957 845,00"

Note : il est possible d’utiliser small.interval et small.mark pour ajouter des séparateurs parmi les décimales.

label_number(accuracy = 10^-9, small.mark = "|", small.interval = 3)(x)
[1] "0.002|300|000"         "0.123|000|000"        
[3] "4.567|000|000"         "874.440|000|000"      
[5] "8 957 845.000|000|000"

label_comma()

label_comma (et comma) est une variante de label_number qui, par défaut, affiche les nombres à l’américaine, avec une virgule comme séparateur de milliers.

label_comma()(x)
[1] "0.00"         "0.12"         "4.57"        
[4] "874.44"       "8,957,845.00"

label_percent()

label_percent (et percent) est une variante de label_number qui affiche les nombres sous formes de pourcentages (scale = 100, suffix = "%").

label_percent()(x)
[1] "0%"           "12%"          "457%"        
[4] "87 444%"      "895 784 500%"

label_dollar()

label_dollar est adapté à l’affichage des valeurs monétaires.

label_dollar()(x)
[1] "$0"         "$0"         "$5"         "$874"      
[5] "$8,957,845"
label_dollar(prefix = "", suffix = " €", accuracy = .01, big.mark = " ")(x)
[1] "0.00 \200"         "0.12 \200"         "4.57 \200"        
[4] "874.44 \200"       "8 957 845.00 \200"

L’option negative_parens permet d’afficher les valeurs négatives avec des parenthèses, convention utilisée dans certaines disciplines.

label_dollar()(c(12.5, -4, 21, -56.36))
[1] "$12.50"  "-$4.00"  "$21.00"  "-$56.36"
label_dollar(negative_parens = TRUE)(c(12.5, -4, 21, -56.36))
[1] "$12.50"   "($4.00)"  "$21.00"   "($56.36)"

label_pvalue(), style_pvalue() & signif_stars()

label_pvalue est adapté pour la mise en forme de p-valeurs.

label_pvalue()(c(0.000001, 0.023, 0.098, 0.60, 0.9998))
[1] "<0.001" "0.023"  "0.098"  "0.600"  ">0.999"
label_pvalue(accuracy = .01, add_p = TRUE)(c(0.000001, 0.023, 0.098, 0.60))
[1] "p<0.01" "p=0.02" "p=0.10" "p=0.60"

À noter, la fonction style_pvalue de l’extension gtsummary ayant à peu près le même objectif mais adaptant le nombre de décimales en fonction de la p-valeur.

gtsummary::style_pvalue(c(0.000001, 0.023, 0.098, 0.60, 0.9998))
[1] "<0.001" "0.023"  "0.10"   "0.6"    ">0.9"  

La fonction signif_stars de GGally permet quant à elle d’afficher les p-valeurs sous forme d’étoiles de significativité, Par défaut, trois astérisques si p < 0.001, deux si p < 0.01, une si p < 0.05 et un point si p < 0.10. Les valeurs sont bien sur paramétrables.

p <- c(0.5, 0.1, 0.05, 0.01, 0.001)
GGally::signif_stars(p)
Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2
[1] ""    "."   "*"   "**"  "***"
GGally::signif_stars(p, one = .15, point = NULL)
[1] ""    "*"   "*"   "**"  "***"

label_number_si()

label_number_si cherche le préfixe du Système international d’unités le plus proche et arrondi chaque valeur en fonction, en ajoutant la précision correspondante.

label_number_si(unit = "g")(c(.00000145, .0034, 5, 12478, 14569787))
[1] "1.4 µg"  "3.4 mg"  "5.0 g"   "12.5 kg" "14.6 Mg"

label_scientific()

label_scientific affiche les nombres dans un format scientifique (avec des puissances de 10).

label_scientific(unit = "g")(c(.00000145, .0034, 5, 12478, 14569787))
[1] "1.45e-06" "3.40e-03" "5.00e+00" "1.25e+04" "1.46e+07"

label_bytes()

label_bytes mets en forme des tailles exprimées en octets, utilisant au besoin des multiples de 1024.

b <- c(478, 1235468, 546578944897)
label_bytes()(b)
[1] "478 B"  "1 MB"   "547 GB"
label_bytes(units = "auto_binary")(b)
[1] "478 iB"  "1 MiB"   "509 GiB"

label_ordinal()

label_bytes permets d’afficher des rangs ou nombres ordinaux. Plusieurs langues sont disponibles.

label_ordinal()(1:5)
[1] "1st" "2nd" "3rd" "4th" "5th"
label_ordinal(rules = ordinal_french())(1:5)
[1] "1er" "2e"  "3e"  "4e"  "5e" 
label_ordinal(rules = ordinal_french(gender = "f", plural = TRUE))(1:5)
[1] "1res" "2es"  "3es"  "4es"  "5es" 

label_date(), label_date_short() & label_time()

label_date, label_date_short et label_time peuvent être utilisées pour la mise en forme de dates.

label_date()(as.Date("2020-02-14"))
[1] "2020-02-14"
label_date(format = "%d/%m/%Y")(as.Date("2020-02-14"))
[1] "14/02/2020"
label_date_short()(as.Date("2020-02-14"))
[1] "14\nfévr.\n2020"

La mise en forme des dates est un peu complexe. Ne pas hésiter à consulter le fichier d’aide de la fonction strptime pour plus d’informations.

label_wrap()

La fonction label_wrap est un peu différente. Elle permets d’insérer des retours à la ligne (\n) dans des chaines de caractères. Elle tient compte des espaces pour identifier les mots et éviter ainsi des coupures au milieu d’un mot.

x <- "Ceci est un texte assez long et que l'on souhaiterait afficher sur plusieurs lignes. Cependant, on souhaite éviter que des coupures apparaissent au milieu d'un mot."
label_wrap(80)(x)
[1] "Ceci est un texte assez long et que l'on souhaiterait afficher sur plusieurs\nlignes. Cependant, on souhaite éviter que des coupures apparaissent au milieu\nd'un mot."
label_wrap(80)(x) |> message()
Ceci est un texte assez long et que l'on souhaiterait afficher sur plusieurs
lignes. Cependant, on souhaite éviter que des coupures apparaissent au milieu
d'un mot.
label_wrap(40)(x) |> message()
Ceci est un texte assez long et que
l'on souhaiterait afficher sur
plusieurs lignes. Cependant, on
souhaite éviter que des coupures
apparaissent au milieu d'un mot.