library(tidyverse)
library(here)
library(scales)
source(here("R", "theme_cours.R"))
Sys.setenv(LANGUAGE = "en") # messages d'erreur en anglaisSéance 1 : Premiers pas avec R et RStudio
Interface, projets, objets, fonctions, packages, vecteurs et data frames
Objectifs de la séance
- Installer R et RStudio et vous repérer dans les quatre panneaux.
- Travailler dans un projet RStudio et construire des chemins de fichiers avec
here::here(). - Créer des objets, appeler des fonctions et lire une page d’aide.
- Savoir ce que R garde en mémoire, et vérifier qu’un script tourne seul après un redémarrage.
- Distinguer l’installation d’un package de son chargement, lire les trois messages d’erreur les plus courants, distinguer une erreur d’un avertissement, et poser une question à laquelle on peut répondre.
- Manipuler des vecteurs (y compris les valeurs manquantes) et des data frames avec R de base.
- Calculer le PIB par habitant de trois pays : la première étape de notre fil rouge.
Préparer votre session R
Avez-vous suivi les étapes « Avant la première séance » de la page d’accueil ? Sinon, faites-les d’abord : le bloc ci-dessous a besoin des packages et du fichier R/theme_cours.R qu’elles installent.
Script de la séance : télécharger seance-1.R, tout le code de cette page dans un seul fichier.
Rythme. Le parcours principal dure environ 200 minutes, exercices compris. L’exercice 1.7 est Facultatif : pour aller plus loin ; les exercices 1.3, 1.4, 1.8 et 1.9 sont à faire à la maison.
Que sont R et RStudio ?
≈ 15 min À la fin de cette section, vous saurez dire ce que sont R et RStudio, et pourquoi nous les utilisons.
R est un langage de programmation pour les statistiques et l’analyse de données. RStudio (désormais édité par Posit) est l’éditeur que nous utilisons pour écrire et exécuter du code R. R est le moteur, RStudio est le tableau de bord.
R est le moteur d’une voiture, RStudio est le tableau de bord et le volant. On peut conduire sans tableau de bord, mais on n’en a pas envie.
Pourquoi R pour un économiste ?
- Gratuit et open source : votre code tourne de la même façon sur n’importe quelle machine, aujourd’hui et dans cinq ans.
- Packages : des milliers d’extensions sur le CRAN (l’archive officielle) pour la manipulation de données, l’économétrie, les cartes, l’analyse de texte.
- Reproductible : le code, les résultats et le texte vivent dans un seul document (Quarto, séance 6).
- Très utilisé dans le monde académique, les banques centrales et les organisations internationales, avec une large communauté.
Installation
Installez dans cet ordre : d’abord R depuis le CRAN, puis RStudio Desktop depuis Posit. Le chapitre Starting with R and RStudio (en anglais) de Hands-On Programming with R détaille les deux installations avec des captures d’écran.
Les quatre panneaux

| Panneau | À quoi il sert |
|---|---|
| Source (en haut à gauche) | Vos scripts (fichiers .R). C’est là que vous écrivez le code que vous voulez conserver. |
| Console (en bas à gauche) | L’endroit où R exécute le code et affiche les résultats. Pratique pour les tests rapides. |
| Environment (en haut à droite) | Les objets actuellement en mémoire. |
| Files / Plots / Packages / Help (en bas à droite) | Explorateur de fichiers, graphiques, packages installés, pages d’aide. |
Projets RStudio et chemins de fichiers
≈ 15 min Après cette section, vous saurez mettre en place un dossier de projet dans lequel chaque chemin fonctionne sur n’importe quel ordinateur.
Faites-le dès le premier jour, cela vous fera gagner des heures plus tard.
Un projet RStudio est un dossier contenant un fichier .Rproj. Quand vous l’ouvrez, RStudio fixe le répertoire de travail sur ce dossier, de sorte que tout chemin peut s’écrire relativement au projet.
-
File > New Project > New Directory > New Project. Nommez-ler-courseet choisissez son emplacement. - Décompressez
data.zip(page d’accueil) dans le dossier du projet. Cela créedata/(tous les fichiers de données y vont),data/raw/etR/theme_cours.R. - Créez un script :
File > New File > R Script, enregistrez-le soussession1.Rdans le dossier du projet.
Votre dossier de projet ressemble maintenant à ceci :
r-course/
├── r-course.Rproj
├── session1.R
├── data/ # les données du cours (de data.zip)
│ └── raw/ # fichiers originaux, en lecture seule
├── R/
│ └── theme_cours.R # thème graphique commun (de data.zip)
└── output/ # tout ce que vous produisez (créé en séance 2)
Pourquoi here::here() et jamais setwd()
Beaucoup de tutoriels commencent leurs scripts par setwd("/Users/john/Desktop/course"). Ne le faites jamais. Ce chemin n’existe que sur votre propre ordinateur : le script plante sur toute autre machine (celle de votre collègue, de votre directeur de mémoire, la vôtre dans six mois). N’écrivez jamais setwd() avec un chemin de votre propre ordinateur dans un script que vous partagez.
À la place, le package here construit les chemins à partir de la racine du projet, où que se trouve celui-ci :
# Construit "<racine du projet>/data/wdi_panel.csv" sur n'importe quel ordinateur
here::here("data", "wdi_panel.csv")
# Utilisé dans une fonction de lecture (séance 2)
wdi <- read_csv(here::here("data", "wdi_panel.csv"))Un projet par cours ou par article, les données dans data/, les chemins construits avec here::here(). Votre code tourne alors sur n’importe quel ordinateur sans modifier un seul chemin.
Ouvrir un fichier .R en double-cliquant dessus, en dehors du projet. Le répertoire de travail est alors faux et here() ne trouve pas data/. Ouvrez toujours d’abord le fichier .Rproj (le nom du projet s’affiche en haut à droite de RStudio).
Scripts, console et commentaires
≈ 10 min Après cette section, vous saurez écrire, exécuter et commenter du code dans un script.
Vous pouvez taper dans la console, mais ce que vous y tapez est perdu. Le code que vous voulez garder va dans un script.
flowchart LR
A["Script : écrire et enregistrer le code"] -->|"Cmd/Ctrl + Enter"| B["Console : R l'exécute"]
B --> C["Environment : objets en mémoire"]
B --> D["Plots / Files : sorties"]
- Écrivez le code dans le script, puis exécutez la ligne courante (ou les lignes sélectionnées) avec
Ctrl + Enter(Windows/Linux) ouCmd + Enter(Mac). R l’envoie à la console. - Exécutez tout le script avec
Ctrl/Cmd + Shift + Enter. - Tout ce qui suit
#sur une ligne est un commentaire : R l’ignore. Commentez le pourquoi, pas l’évident.
# Un commentaire : R ignore cette ligne
2 + 2 # un commentaire peut aussi suivre du code[1] 4
Le script est votre production ; la console est un brouillon. Si ce n’est pas dans le script, cela n’existe plus demain.
Une bonne habitude : un script doit pouvoir s’exécuter de haut en bas dans une session R neuve et donner les mêmes résultats. Si ce n’est pas le cas, quelque chose est caché dans votre environnement (Ce que R retient montre comment le vérifier).
Objets, types et opérateurs
≈ 30 min Après cette section, vous saurez ranger n’importe quoi sous un nom, le retrouver, distinguer les types et utiliser les opérateurs.
R est un langage fondé sur les objets
Tout ce que vous manipulez dans R vit dans un objet : un nom qui pointe vers une valeur stockée dans la mémoire de l’ordinateur. Deux gestes font tout le travail :
-
name <- valuestocke la valeur sous le nom (la flèche d’assignation<-, raccourciAlt + -sous Windows,Option + -sous Mac). Rien ne s’affiche. - Taper le nom seul rappelle la valeur et l’affiche.
Vous pouvez ranger n’importe quoi sous un nom : un nombre, un texte, un vecteur, un tableau entier, le résultat d’un calcul, et plus tard un modèle de régression (séance 4) ou un graphique (séance 5). Même une fonction est un objet.
gdp_usa <- 20.9 # un nombre : PIB des États-Unis, milliers de milliards de US$, 2020
three_countries <- c("USA", "China", "India") # un vecteur de textes (voir Vecteurs)
gdp_table <- tibble(country = three_countries,
gdp_bn = c(20894, 14688, 2671)) # un tableau entier (voir Data frames)
gdp_sum <- sum(gdp_table$gdp_bn) # le résultat d'un calcul
my_mean <- mean # même une fonction
gdp_usa # taper le nom rappelle la valeur[1] 20.9
gdp_table# A tibble: 3 × 2
country gdp_bn
<chr> <dbl>
1 USA 20894
2 China 14688
3 India 2671
my_mean(gdp_table$gdp_bn) # my_mean fonctionne maintenant exactement comme mean[1] 12751
flowchart LR
A["gdp_usa"] -->|"pointe vers"| A2["20.9"]
B["three_countries"] -->|"pointe vers"| B2["USA, China, India"]
C["gdp_table"] -->|"pointe vers"| C2["un tableau : 3 lignes, 2 colonnes"]
D["my_mean"] -->|"pointe vers"| D2["la fonction mean()"]
Chaque objet que vous créez apparaît dans le panneau Environment (en haut à droite), avec un aperçu de sa valeur ; cliquez sur un tableau pour l’ouvrir. ls() affiche la même liste dans la console :
ls() [1] "course_lang" "gdp_sum" "gdp_table" "gdp_usa"
[5] "my_mean" "nb" "nb_dollar" "nb_pct"
[9] "pal_cours" "pal_regions" "theme_cours" "three_countries"
La liste contient aussi des objets que vous n’avez pas tapés : pal_cours, theme_cours, nb et quelques autres ont été créés par source(here("R", "theme_cours.R")) dans le bloc de préparation. theme_cours et nb sont des fonctions, rangées sous un nom comme n’importe quel autre objet.
Un objet est une boîte étiquetée. <- met quelque chose dans la boîte et écrit l’étiquette ; taper l’étiquette ouvre la boîte. Une boîte peut contenir un seul nombre ou un jeu de données entier.
« J’ai exécuté la ligne et il ne s’est rien passé. » Rien ne s’est affiché, mais la valeur a été stockée : regardez dans le panneau Environment, ou tapez le nom.
Rangez le PIB 2020 de l’Inde, 2671 (milliards de US$), dans gdp_india ; les trois PIB 20894, 14688, 2671 dans un vecteur gdp_three ; et leur total dans gdp_total. (a) Retrouvez les trois objets dans le panneau Environment. (b) Rappelez gdp_total en tapant son nom. (c) Rangez la fonction max sous le nom largest et appliquez-la à gdp_three.
gdp_india <- 2671
gdp_three <- c(20894, 14688, 2671)
gdp_total <- sum(gdp_three)
gdp_total # (b) rappel par le nom[1] 38253
largest <- max # (c) une fonction rangée sous un nouveau nom
largest(gdp_three)[1] 20894
Types de valeurs
gdp_usa <- 20.9 # numeric (nombre)
country <- "United States" # character (texte, toujours entre guillemets)
is_rich <- TRUE # logical (TRUE ou FALSE, sans guillemets)
gdp_usa[1] 20.9
country[1] "United States"
is_rich[1] TRUE
Trois types de base : numeric (nombres), character (texte), logical (TRUE/FALSE). class() vous dit lequel vous avez :
class(gdp_usa)[1] "numeric"
class(country)[1] "character"
class(is_rich)[1] "logical"
Règles de nommage : lettres, chiffres, _ et ., pas d’espaces, ne pas commencer par un chiffre. R est sensible à la casse (gdp et GDP sont deux objets différents). Ne réutilisez pas les noms de fonctions existantes (sum, mean, summary, data) : cela fonctionne jusqu’au jour où cela provoque un bug déroutant. Utilisez des noms descriptifs comme total_gdp.
Opérateurs arithmétiques et logiques
3 + 5 # addition[1] 8
10 - 4 # soustraction[1] 6
6 * 7 # multiplication[1] 42
20 / 4 # division[1] 5
2^3 # puissance[1] 8
17 %/% 5 # division entière[1] 3
17 %% 5 # reste[1] 2
Les comparaisons renvoient une valeur logique :
3 == 3 # égal (deux signes égal !)[1] TRUE
5 != 4 # différent[1] TRUE
7 > 5[1] TRUE
2 < 6[1] TRUE
4 >= 4[1] TRUE
Combinez les conditions avec & (et), | (ou) et ! (non) :
TRUE & FALSE[1] FALSE
TRUE | FALSE[1] TRUE
!TRUE[1] FALSE
Écrire x = 3 quand on veut dire x == 3. Le premier assigne (et n’affiche rien), le second compare et renvoie TRUE ou FALSE. Utilisez <- pour assigner et gardez = pour les arguments de fonctions.
Fonctions et arguments
Fonction : une recette nommée. Elle prend des entrées (les arguments) entre parenthèses et renvoie un résultat.
Une fonction prend des entrées (arguments) entre parenthèses et renvoie un résultat. Les arguments peuvent être donnés par position ou par nom.
sqrt(16)[1] 4
round(3.14159, digits = 2)[1] 3.14
round(3.14159, 2) # idem, par position[1] 3.14
mean(c(4, 8, 15, 16, 23, 42))[1] 18
Vous pouvez stocker un résultat dans un nouvel objet et le réutiliser :
total_gdp <- sum(20.9, 14.7, 2.7)
total_gdp[1] 38.3
Ce que R retient
≈ 15 min Après cette section, vous saurez distinguer votre script de la mémoire de R, et prouver que votre script tourne seul.
R garde deux choses différentes, et les débutants les confondent sans cesse :
Le script (session1.R) |
L’environnement (les objets en mémoire) | |
|---|---|---|
| Où | Un fichier sur votre disque | La mémoire de R, affichée dans le panneau Environment |
| Survit à la fermeture de RStudio ? | Oui, une fois enregistré (Ctrl/Cmd + S) |
Non : on le reconstruit en exécutant le script |
| Change quand | Vous tapez et enregistrez | Vous exécutez une ligne |
Trois conséquences :
- Modifier une ligne du script ne change pas l’objet tant que vous n’exécutez pas cette ligne à nouveau.
- Supprimer une ligne ne supprime pas l’objet : il reste en mémoire jusqu’au redémarrage de R.
- Un objet créé dans la console est en mémoire mais dans aucun fichier. Demain, il a disparu.
R stocke une valeur, pas une formule. Un objet calculé à partir d’un autre ne se met pas à jour quand le premier change :
pop_india <- 1380 # millions, arrondi 2020
pop_three <- 331 + 1411 + pop_india # calculé une fois, à partir de la valeur 1380
pop_india <- 1400 # on modifie pop_india...
pop_three # ...pop_three contient toujours l'ancien total[1] 3122
Un tableur recalculerait pop_three ; R ne le fait pas. Pour le mettre à jour, exécutez à nouveau sa ligne.
Redémarrer R et tout relancer
La seule preuve que votre script est complet, c’est de l’exécuter dans une mémoire vide :
-
Session > Restart R(Ctrl/Cmd + Shift + F10). L’environnement est vidé ; le script n’est pas touché. - Exécutez tout le script :
Ctrl/Cmd + Shift + Enter, ou le bouton Source au-dessus du script. - S’il va jusqu’au bout et donne les mêmes résultats, votre script fonctionne seul. S’il s’arrête, vous avez trouvé quelque chose qui n’existait qu’en mémoire.
Faites-le avant d’envoyer un script à qui que ce soit, et chaque fois que des résultats vous semblent étranges.
Faites démarrer RStudio à vide à chaque fois. Dans Tools > Global Options > General :
- décochez Restore .RData into workspace at startup ;
- réglez Save workspace to .RData on exit sur Never.
Sinon, RStudio recharge discrètement les objets de la veille, et un script cassé peut sembler fonctionner.
Le script fait foi ; l’environnement n’en est qu’une copie temporaire. Tout ce dont vous aurez besoin demain doit être écrit dans le script.
Hier, Amina a testé une valeur dans la console en tapant pop_mn <- c(331, 1411, 1380). Puis elle a écrit ce script, l’a exécuté et a obtenu trois PIB par habitant :
gdp_bn <- c(20894, 14688, 2671) # PIB, milliards de US$, 2020
gdp_pc <- gdp_bn * 1000 / pop_mn # PIB par habitant, US$
gdp_pcReproduisez sa journée : tapez sa ligne dans la console, mettez les trois lignes dans votre script et exécutez-les. Redémarrez ensuite R et exécutez à nouveau le script. Que se passe-t-il, pourquoi, et comment corriger le script ?
Après le redémarrage, la mémoire est vide et le script s’arrête :
gdp_bn <- c(20894, 14688, 2671) # PIB, milliards de US$, 2020
gdp_pc <- gdp_bn * 1000 / pop_mn # PIB par habitant, US$Error:
! object 'pop_mn' not found
pop_mn n’a jamais été créé que dans la console : il vivait en mémoire, pas dans le script. Hier, cela fonctionnait parce que l’objet était encore là. La correction consiste à écrire la ligne manquante dans le script, au-dessus de la ligne qui l’utilise :
gdp_bn <- c(20894, 14688, 2671) # PIB, milliards de US$, 2020
pop_mn <- c(331, 1411, 1380) # population, millions, 2020
gdp_pc <- gdp_bn * 1000 / pop_mn # PIB par habitant, US$
gdp_pc[1] 63123.867 10409.639 1935.507
Redémarrez R et exécutez le script une fois de plus : il fonctionne maintenant seul.
Obtenir de l’aide
≈ 15 min Après cette section, vous saurez trouver et lire la page d’aide de n’importe quelle fonction, et poser une question à laquelle on peut répondre.
Personne ne retient toutes les fonctions. Savoir trouver de l’aide est la vraie compétence.
-
?meanouhelp("mean")ouvre la page d’aide d’une fonction (dans le panneau Help). -
??regressioncherche un mot dans toutes les pages d’aide installées. - Les vignettes et les sites web des packages (p. ex. tidyverse.org, en anglais) donnent des exemples travaillés.
- Cherchez le message d’erreur exact en ligne : quelqu’un l’a déjà rencontré.
?mean
help("round")Comment lire une page d’aide, dans cet ordre :
- Description : ce que fait la fonction, en une ligne.
-
Usage : les arguments et leurs valeurs par défaut.
mean(x, trim = 0, na.rm = FALSE, ...)vous indique quena.rmvautFALSEsauf si vous le changez. - Arguments : ce que signifie chacun d’eux.
- Value : ce que vous récupérez.
- Examples en bas de page : copiez-les dans votre console et exécutez-les. C’est souvent le moyen le plus rapide de comprendre.
ChatGPT, Claude, Copilot et les outils similaires sont utiles pour expliquer un message d’erreur ou vous rappeler la syntaxe d’une fonction. Trois règles :
- Exécutez toujours le code et vérifiez qu’il fait ce que vous avez demandé ; le code produit par une IA peut être faux ou utiliser des fonctions obsolètes.
- Si vous ne savez pas expliquer une ligne, ne la gardez pas. Vous êtes responsable de chaque résultat que vous rendez.
- Ne collez jamais de données confidentielles ou personnelles dans un outil public.
Apprenez d’abord les bases : on ne peut pas vérifier une réponse qu’on ne comprend pas.
Poser une question à laquelle on peut répondre
Que vous demandiez à l’enseignant, à un camarade ou à un assistant d’IA, la réponse ne peut pas être meilleure que la question. Une bonne question donne quatre choses :
- Ce que vous voulez faire, en une phrase.
- Le plus petit morceau de code qui échoue : retirez tout ce qui n’est pas nécessaire pour voir le problème. Redémarrez d’abord R et vérifiez que l’échec se produit toujours.
- Le message exact, copié-collé, ni retapé ni résumé.
- Ce que vous attendiez, et ce que vous avez déjà essayé.
Comparez :
- Mauvaise : « Mon code sur le PIB ne marche pas, au secours ! » Personne ne peut répondre sans vous poser quatre questions en retour.
- Bonne : « Je veux le PIB par habitant de trois pays. Dans une session neuve,
gdp_pc <- gdp_bn * 1000 / pop_mnrenvoieError: object 'pop_mn' not found. J’attendais trois nombres. J’ai vérifié l’orthographe depop_mn. Qu’est-ce qui m’échappe ? »
Souvent, réduire votre code au plus petit exemple qui échoue vous montre le problème avant même d’envoyer la question. Ce n’est pas du temps perdu : c’est ainsi que les utilisateurs expérimentés déboguent.
Packages : installer une fois, charger à chaque fois
≈ 10 min Après cette section, vous saurez distinguer l’installation d’un package de son chargement.
R de base est petit. L’essentiel de ce que nous utilisons vient de packages. Deux étapes distinctes :
- Installer (une fois par ordinateur) : télécharger le package depuis le CRAN. Tapez ceci dans la console, jamais dans un script que vous partagez.
-
Charger (à chaque session) :
library()rend ses fonctions disponibles. Placez les appels àlibrary()en haut de votre script.
# Étape 1, une seule fois, dans la console : tous les packages utilisés dans ce cours
install.packages(c(
"tidyverse", "here", "janitor", "readxl", "writexl", "lubridate", "scales",
"WDI", "gt", "fixest", "modelsummary", "ggrepel", "sf", "rnaturalearth",
"rnaturalearthdata", "patchwork", "plotly", "crosstalk", "shiny"
))
# Étape 2, en haut de chaque script
library(tidyverse)Installer un package, c’est acheter un livre pour votre étagère (une fois). Le charger avec library(), c’est le prendre sur l’étagère et l’ouvrir (à chaque fois que vous travaillez).
Mettre install.packages() en haut d’un script. Cela retélécharge le package à chaque exécution et plante sur la machine d’un collègue. Installez dans la console, chargez dans le script.
Installez-les tous maintenant (quelques minutes). Chaque séance suivante commence par une ligne « Packages utilisés aujourd’hui » qui vous dit quoi installer s’il manque quelque chose.
tidyverse est un ensemble de packages (ggplot2, dplyr, tibble, readr, …) que nous utilisons tout au long du cours. Pour les packages que nous n’utilisons qu’une fois, package::function() (comme dans here::here()) appelle une fonction sans charger tout le package.
Lire les messages d’erreur
≈ 20 min Après cette section, vous saurez lire les trois messages d’erreur les plus courants et les corriger, distinguer une erreur d’un avertissement ou d’un message, et sortir de l’invite +.
Vous aurez des erreurs tous les jours, y compris dans dix ans. Une erreur n’est pas un échec : R vous dit ce qu’il n’a pas pu faire. Lisez le message, puis regardez la ligne qu’il désigne. Voici les trois que vous rencontrerez le plus.
1. object 'xxx' not found (« objet introuvable ») : vous utilisez un nom qui n’existe pas. Faute de frappe, mauvaise casse, ou vous avez oublié d’exécuter la ligne qui le crée.
gdp_china <- 14.7
gdp_chinaa + 1 # faute de frappe dans le nomError:
! object 'gdp_chinaa' not found
2. unexpected symbol / unexpected numeric constant / unexpected ',' (« symbole inattendu ») : la syntaxe est incorrecte, souvent une virgule, un guillemet ou une parenthèse manquants. R vous dit quel élément il n’attendait pas (ici le 2), donc l’erreur se trouve juste avant : la virgule manquante après le 1. Dans la console, le message s’écrit unexpected numeric constant in "c(1 2" ; cette page le met en forme différemment.
c(1 2 3) # virgules manquantesError in parse(text = input): <text>:1:5: unexpected numeric constant
1: c(1 2
^
3. could not find function "xxx" (« fonction introuvable ») : le nom de la fonction est mal orthographié, ou son package n’est pas chargé. Ici feols() vient de fixest, que nous n’avons pas chargé avec library().
feols(gdp ~ year, data = tibble(gdp = 1:3, year = 1:3))Error in `feols()`:
! could not find function "feols"
Un message d’erreur est une information, pas un verdict. Il nomme l’objet, le symbole ou la fonction sur lequel R a buté ; commencez par là.
Méthode : (1) lisez le message à voix haute, (2) trouvez la ligne, (3) vérifiez l’orthographe, les virgules, les guillemets et les parenthèses, (4) vérifiez que vous avez exécuté les lignes précédentes et chargé le package, (5) seulement ensuite, cherchez en ligne ou demandez à un assistant d’IA en collant le message exact (voir Poser une question à laquelle on peut répondre).
Erreur, avertissement ou message ?
R vous parle de trois façons, qui ne veulent pas dire la même chose.
Un avertissement (warning) signifie que R est allé au bout, mais que quelque chose semble anormal. Ici, la population de la Chine a été stockée comme texte avec une virgule des milliers ; R ne peut pas lire "1,411" comme un nombre :
pop_text <- c("331", "1,411", "1380") # des nombres stockés comme texte
as.numeric(pop_text)Warning: NAs introduced by coercion
[1] 331 NA 1380
Vous avez obtenu un résultat, mais il contient un NA (une valeur manquante, voir Vecteurs) à la place de la Chine. N’ignorez jamais un avertissement : cherchez ce qu’il signale.
Un message est une simple information. read_csv() (séance 2) vous dit ce qu’il a lu :
gdp_3 <- read_csv(here("data", "wdi_3countries.csv"))Rows: 63 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): country, iso3c
dbl (2): year, gdp
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
| R affiche | Commence par | R est-il allé au bout ? | Ce que vous faites |
|---|---|---|---|
| Erreur | Error |
Non : rien n’a été produit | Corrigez le code, puis relancez-le |
| Avertissement | Warning |
Oui, mais vérifiez le résultat | Cherchez ce que signale l’avertissement |
| Message | (n’importe quoi) | Oui | Lisez-le une fois ; souvent, rien à faire |
L’invite + : R vous attend
La console affiche normalement >, prête pour une nouvelle commande. Si elle affiche +, R pense que votre expression n’est pas terminée : une parenthèse ou un guillemet est encore ouvert, alors il attend la suite.
> mean(c(4, 8, 15)
+
> country <- "India
+
La première ligne oublie une ), la seconde un " fermant. Appuyez sur Échap (Escape) pour revenir à >, corrigez la ligne dans votre script et exécutez-la à nouveau.
Vecteurs
≈ 25 min Après cette section, vous saurez construire des vecteurs, les indexer et calculer avec eux, y compris avec des valeurs manquantes.
Vecteur : une liste ordonnée de valeurs du même type. C’est la brique de base de R : une colonne d’un jeu de données est un vecteur.
population <- c(331, 1411, 1380) # numeric (nombres)
countries <- c("USA", "China", "India") # character (texte)
high_income <- c(TRUE, FALSE, FALSE) # logical (vrai/faux)Séquences et répétitions :
1:10 # entiers de 1 à 10 [1] 1 2 3 4 5 6 7 8 9 10
seq(1, 10, by = 2) # pas de 2[1] 1 3 5 7 9
seq(0, 1, length.out = 5) # 5 valeurs régulièrement espacées[1] 0.00 0.25 0.50 0.75 1.00
rep(5, times = 3)[1] 5 5 5
rep(c("a", "b"), each = 2)[1] "a" "a" "b" "b"
Indexation
Les crochets sélectionnent des éléments par position (en commençant à 1) ou par condition :
population[2] # deuxième élément[1] 1411
population[c(1, 3)] # premier et troisième[1] 331 1380
population[-1] # tous sauf le premier[1] 1411 1380
population[population > 1000] # éléments qui satisfont une condition[1] 1411 1380
countries[population > 1000] # un vecteur sert à filtrer un autre[1] "China" "India"
Opérations vectorisées
Les opérations s’appliquent à tous les éléments d’un coup, sans boucle.
population + 2[1] 333 1413 1382
population * 1000000 # des millions aux personnes[1] 3.310e+08 1.411e+09 1.380e+09
population / sum(population) # part du total[1] 0.1060218 0.4519539 0.4420243
Afficher le code du graphique (vu en séance 5)
tibble(country = countries, population = population,
share = 100 * population / sum(population)) |>
mutate(country = fct_reorder(country, share)) |>
ggplot(aes(x = share, y = country)) +
geom_col(fill = pal_cours[["principal"]]) +
geom_text(aes(label = paste0(round(share), " %")), hjust = -0.2) +
scale_x_continuous(limits = c(0, 55)) +
labs(
title = "La Chine et l'Inde concentrent 89 % de la population des trois pays",
x = "Part de la population totale des trois pays (%)",
y = NULL,
caption = "Source : valeurs 2020 arrondies d'une version antérieure des WDI (Banque mondiale), à visée pédagogique."
)
Une opération vectorisée, c’est une photocopieuse avec un tampon : une seule instruction (/ sum(population)) est appliquée à toutes les feuilles d’un coup.
Valeurs manquantes
NA signifie « valeur non disponible ». Ce n’est pas zéro. Tout calcul impliquant NA renvoie NA, car R ne peut pas deviner la valeur manquante.
gini <- c(41.5, 38.2, NA, 35.7)
mean(gini)[1] NA
mean(gini, na.rm = TRUE) # na.rm = TRUE : retirer les NA avant le calcul[1] 38.46667
is.na(gini)[1] FALSE FALSE TRUE FALSE
sum(is.na(gini)) # nombre de valeurs manquantes[1] 1
Utiliser na.rm = TRUE par réflexe. Demandez-vous pourquoi la valeur est manquante et si l’écarter biaise le résultat. Dans les WDI, le Gini manque pour beaucoup de pays pauvres, comme le montre le graphique.
Afficher le code du graphique (vu en séance 5)
read_csv(here("data", "wdi_panel.csv"), show_col_types = FALSE) |>
filter(year == 2019, !is.na(income)) |>
summarise(share_na = 100 * mean(is.na(gini)), .by = income) |>
mutate(income = factor(income, levels = c("Low income", "Lower middle income",
"Upper middle income", "High income"))) |>
ggplot(aes(x = income, y = share_na)) +
geom_col(fill = pal_cours[["accent"]]) +
geom_text(aes(label = paste0(round(share_na), " %")), vjust = -0.4) +
scale_y_continuous(limits = c(0, 100)) +
labs(
title = "Le Gini manque pour la plupart des pays une année donnée",
x = "Groupe de revenu de la Banque mondiale (classification actuelle)",
y = "Pays dont le Gini est manquant, 2019 (%)",
caption = "Source : Banque mondiale, World Development Indicators (WDI), 2019."
)Les données d’inégalités sont les plus rares là où elles comptent le plus. Faire la moyenne des seuls pays qui déclarent un Gini décrit les pays qui mesurent l’inégalité, pas le monde.
Data frames et tibbles
≈ 25 min Après cette section, vous saurez construire un petit tableau, l’explorer et calculer une nouvelle colonne.
Data frame (tableau de données) : un tableau dont chaque colonne est un vecteur, tous de même longueur.
Un tibble est la version tidyverse d’un data frame, avec un affichage plus lisible. Nous utiliserons des tibbles tout au long du cours.
Notre fil rouge commence ici : trois pays, avec des valeurs 2020 arrondies (PIB en milliards de dollars US courants, population en millions ; chiffres approximatifs à visée pédagogique, issus d’une version antérieure des WDI de la Banque mondiale). La version actuelle, utilisée à partir de la séance 2, donne des chiffres légèrement différents : la Banque mondiale révise ses séries.
countries3 <- tibble(
country = c("United States", "China", "India"),
gdp_bn = c(20894, 14688, 2671), # PIB, milliards de US$ courants, arrondi 2020
pop_mn = c(331, 1411, 1380), # population, millions, arrondi 2020
high_income = c(TRUE, FALSE, FALSE)
)
countries3# A tibble: 3 × 4
country gdp_bn pop_mn high_income
<chr> <dbl> <dbl> <lgl>
1 United States 20894 331 TRUE
2 China 14688 1411 FALSE
3 India 2671 1380 FALSE
Explorer un data frame
nrow(countries3) # nombre de lignes[1] 3
ncol(countries3) # nombre de colonnes[1] 4
names(countries3) # noms des colonnes[1] "country" "gdp_bn" "pop_mn" "high_income"
str(countries3) # structure : type de chaque colonnetibble [3 × 4] (S3: tbl_df/tbl/data.frame)
$ country : chr [1:3] "United States" "China" "India"
$ gdp_bn : num [1:3] 20894 14688 2671
$ pop_mn : num [1:3] 331 1411 1380
$ high_income: logi [1:3] TRUE FALSE FALSE
summary(countries3) # statistiques rapides par colonne country gdp_bn pop_mn high_income
Length : 3 Min. : 2671 Min. : 331.0 Mode :logical
N.unique : 3 1st Qu.: 8680 1st Qu.: 855.5 FALSE:2
N.blank : 0 Median :14688 Median :1380.0 TRUE :1
Min.nchar: 5 Mean :12751 Mean :1040.7
Max.nchar:13 3rd Qu.:17791 3rd Qu.:1395.5
Max. :20894 Max. :1411.0
head(countries3, 2) # 2 premières lignes# A tibble: 2 × 4
country gdp_bn pop_mn high_income
<chr> <dbl> <dbl> <lgl>
1 United States 20894 331 TRUE
2 China 14688 1411 FALSE
Sélectionner des colonnes et des lignes
countries3$gdp_bn # une colonne (un vecteur) avec $[1] 20894 14688 2671
countries3[1, ] # première ligne, toutes les colonnes# A tibble: 1 × 4
country gdp_bn pop_mn high_income
<chr> <dbl> <dbl> <lgl>
1 United States 20894 331 TRUE
countries3[ , "country"] # toutes les lignes, une colonne# A tibble: 3 × 1
country
<chr>
1 United States
2 China
3 India
countries3[2, "pop_mn"] # une cellule# A tibble: 1 × 1
pop_mn
<dbl>
1 1411
countries3[countries3$pop_mn > 1380, ] # lignes satisfaisant une condition# A tibble: 1 × 4
country gdp_bn pop_mn high_income
<chr> <dbl> <dbl> <lgl>
1 China 14688 1411 FALSE
Le schéma est data[lignes, colonnes]. Laisser un côté vide signifie « tout ».
Pensez à un tableur : data[2, 3] signifie « ligne 2, colonne 3 ». La virgule sépare les lignes (avant) des colonnes (après).
Ajouter une colonne
countries3$gdp_pc <- countries3$gdp_bn * 1000 / countries3$pop_mn
countries3# A tibble: 3 × 5
country gdp_bn pop_mn high_income gdp_pc
<chr> <dbl> <dbl> <lgl> <dbl>
1 United States 20894 331 TRUE 63124.
2 China 14688 1411 FALSE 10410.
3 India 2671 1380 FALSE 1936.
Unités : un PIB en milliards divisé par une population en millions donne des milliers de dollars par personne ; on multiplie donc par 1 000 pour obtenir des US$ par personne.
Trier et filtrer (R de base)
# Trier par PIB par habitant, du plus élevé au plus faible
countries3[order(countries3$gdp_pc, decreasing = TRUE), ]# A tibble: 3 × 5
country gdp_bn pop_mn high_income gdp_pc
<chr> <dbl> <dbl> <lgl> <dbl>
1 United States 20894 331 TRUE 63124.
2 China 14688 1411 FALSE 10410.
3 India 2671 1380 FALSE 1936.
# Garder uniquement les pays de plus de 1 000 millions d'habitants
countries3[countries3$pop_mn > 1000, ]# A tibble: 2 × 5
country gdp_bn pop_mn high_income gdp_pc
<chr> <dbl> <dbl> <lgl> <dbl>
1 China 14688 1411 FALSE 10410.
2 India 2671 1380 FALSE 1936.
Cela fonctionne mais c’est lourd à écrire. En séance 3, dplyr rendra cela lisible (arrange(), filter(), mutate()).
Fil rouge : le PIB par habitant de trois pays
countries3[order(countries3$gdp_pc, decreasing = TRUE), c("country", "gdp_pc")]# A tibble: 3 × 2
country gdp_pc
<chr> <dbl>
1 United States 63124.
2 China 10410.
3 India 1936.
Les États-Unis produisent environ six fois plus par habitant que la Chine et environ trente-trois fois plus que l’Inde (valeurs 2020 arrondies, US$ courants, donc non corrigées des différences de prix entre pays). À partir de la séance 2, nous utilisons le jeu de données complet de la Banque mondiale avec tous les pays.
Afficher le code du graphique (vu en séance 5)
countries3 |>
mutate(country = fct_reorder(country, gdp_pc)) |>
ggplot(aes(x = gdp_pc, y = country)) +
geom_col(fill = pal_cours[["principal"]]) +
geom_text(aes(label = label_dollar()(round(gdp_pc))), hjust = -0.1) +
scale_x_continuous(limits = c(0, 80000), labels = label_dollar()) +
labs(
title = "Les États-Unis produisent six fois plus par habitant que la Chine",
x = "PIB par habitant ($ courants, 2020)",
y = NULL,
caption = "Source : valeurs 2020 arrondies d'une version antérieure des WDI (Banque mondiale), à visée pédagogique."
)
PIB par habitant = PIB / population. Le total vous dit la taille d’une économie ; le ratio vous dit combien elle produit par personne. À populations proches, le PIB total de la Chine (5,5 fois celui de l’Inde) se traduit par un écart par habitant de même ampleur.
Le pipe |>
≈ 10 min Après cette section, vous saurez lire et écrire une chaîne d’étapes avec le pipe, et l’exécuter une étape à la fois.
Le pipe |> passe le résultat situé à sa gauche comme premier argument de la fonction située à sa droite. Le code se lit de gauche à droite, comme une recette :
flowchart LR
A["c(1, 4, 9)"] -->|"puis somme"| B["14"] -->|"puis racine carrée"| C["3.74"]
sqrt(sum(c(1, 4, 9))) # imbriqué : à lire de l'intérieur vers l'extérieur[1] 3.741657
c(1, 4, 9) |> sum() |> sqrt() # avec pipe : « prendre c(1, 4, 9), puis la somme, puis la racine carrée »[1] 3.741657
Lisez |> comme « et ensuite » : prenez le vecteur, et ensuite faites-en la somme, et ensuite prenez la racine carrée.
Même résultat. À partir de la séance 2, la plupart de notre code utilise le pipe (raccourci Ctrl/Cmd + Shift + M).
Quand une chaîne échoue, exécutez-la une étape à la fois. Sélectionnez le code jusqu’à la fin d’une étape (par exemple c(1, 4, 9) |> sum()) et exécutez seulement la sélection avec Ctrl/Cmd + Enter. Regardez le résultat, puis ajoutez l’étape suivante. La première étape dont le résultat vous surprend est celle où se trouve le problème. La séance 3 s’y exerce sur des chaînes plus longues.
c(1, 4, 9) # étape 1 : les données[1] 1 4 9
c(1, 4, 9) |> sum() # étapes 1 et 2[1] 14
c(1, 4, 9) |> sum() |> sqrt() # la chaîne complète[1] 3.741657
Exercices
≈ 10 min Après ces exercices, vous saurez appliquer seul chaque outil de la séance.
Les exercices 1.1 et 1.2 se trouvent dans les sections précédentes. Ici, faites les exercices 1.5 et 1.6 en classe. Les exercices 1.3 et 1.4 reprennent les objets et les opérateurs : faites-les à la maison. L’exercice 1.7 est Facultatif : pour aller plus loin ; 1.8 et 1.9 sont à faire à la maison.
Créez un objet my_age avec votre âge, un objet my_name avec votre nom, et un objet is_student avec une valeur logique. Affichez les trois, puis vérifiez la classe de chacun.
my_age <- 25
my_name <- "Pierre"
is_student <- TRUE
my_age[1] 25
my_name[1] "Pierre"
is_student[1] TRUE
class(my_age)[1] "numeric"
class(my_name)[1] "character"
class(is_student)[1] "logical"
Créez x <- 12 et y <- 5. Calculez leur somme, leur différence, leur produit et leur quotient. Vérifiez ensuite si x est supérieur à y et si x est divisible par y (indice : le reste %%).
x <- 12
y <- 5
x + y[1] 17
x - y[1] 7
x * y[1] 60
x / y[1] 2.4
x > y[1] TRUE
x %% y == 0 # FALSE : le reste est 2[1] FALSE
Ouvrez la page d’aide de round(). Que fait l’argument digits, et quelle est sa valeur par défaut ? Arrondissez ensuite pi à 3 décimales.
?rounddigits est le nombre de décimales ; la valeur par défaut est 0.
round(pi, digits = 3)[1] 3.142
Créez un vecteur numérique gdp_growth avec les valeurs 2.3, 5.1, NA, 3.8, -0.4 (taux de croissance annuels en %). Calculez sa moyenne avec et sans la valeur manquante, puis sélectionnez les années où la croissance dépasse 2.
gdp_growth <- c(2.3, 5.1, NA, 3.8, -0.4)
mean(gdp_growth) # NA[1] NA
mean(gdp_growth, na.rm = TRUE) # 2,7[1] 2.7
# Attention : comparer NA à 2 donne NA, donc on retire d'abord les NA
gdp_growth[!is.na(gdp_growth) & gdp_growth > 2][1] 2.3 5.1 3.8
Créez le vecteur 1:10 puis, avec une seule opération chacun, (a) le vecteur de ses carrés, (b) uniquement les nombres pairs (indice : %% 2 == 0), (c) les nombres impairs de 1 à 9 avec seq().
v <- 1:10
v^2 [1] 1 4 9 16 25 36 49 64 81 100
v[v %% 2 == 0][1] 2 4 6 8 10
seq(1, 9, by = 2)[1] 1 3 5 7 9
Créez un data frame students avec trois colonnes name, age, is_student et quatre lignes (inventez-les). Puis : (a) affichez la colonne age, (b) affichez la première ligne, (c) gardez les lignes dont age est strictement supérieur à 20, quel que soit leur statut d’étudiant, (d) triez par âge.
students <- tibble(
name = c("Alice", "Bob", "Charlie", "Dalia"),
age = c(19, 24, 31, 22),
is_student = c(TRUE, TRUE, FALSE, TRUE)
)
students$age # (a)[1] 19 24 31 22
students[1, ] # (b)# A tibble: 1 × 3
name age is_student
<chr> <dbl> <lgl>
1 Alice 19 TRUE
students[students$age > 20, ] # (c) condition sur l'âge uniquement# A tibble: 3 × 3
name age is_student
<chr> <dbl> <lgl>
1 Bob 24 TRUE
2 Charlie 31 FALSE
3 Dalia 22 TRUE
students[order(students$age), ] # (d)# A tibble: 4 × 3
name age is_student
<chr> <dbl> <lgl>
1 Alice 19 TRUE
2 Dalia 22 TRUE
3 Bob 24 TRUE
4 Charlie 31 FALSE
À partir de countries3, ajoutez une colonne gdp_share égale à la part du PIB de chaque pays dans le PIB total des trois pays, en %. Affichez ensuite les pays triés par gdp_share, du plus élevé au plus faible.
countries3$gdp_share <- 100 * countries3$gdp_bn / sum(countries3$gdp_bn)
countries3[order(countries3$gdp_share, decreasing = TRUE),
c("country", "gdp_share")]# A tibble: 3 × 2
country gdp_share
<chr> <dbl>
1 United States 54.6
2 China 38.4
3 India 6.98
À retenir
- Travaillez dans un projet RStudio, gardez les données dans
data/et construisez les chemins avechere::here(). N’utilisez jamaissetwd()avec un chemin de votre propre ordinateur. - Écrivez le code dans un script, exécutez-le avec
Ctrl/Cmd + Enteret commentez le pourquoi. - R est fondé sur les objets :
name <- valuerange n’importe quoi (un nombre, un vecteur, un tableau, un résultat, une fonction) et taper le nom le rappelle. Les trois types de base sont numeric, character et logical. Ne donnez pas à vos objets des noms de fonctions (sum,mean,summary). - Le script fait foi, l’environnement n’en est qu’une copie temporaire. Redémarrez R (
Ctrl/Cmd + Shift + F10) et relancez tout le script pour prouver qu’il tourne seul ; ne restaurez jamais.RDataau démarrage. -
Installez un package une fois (
install.packages(), dans la console), chargez-le dans chaque script (library(), en haut). - Lisez les erreurs calmement : object not found (faute de frappe), unexpected symbol (syntaxe), could not find function (faute de frappe ou package non chargé).
?functionouvre la page d’aide. - Une erreur arrête R ; un avertissement signifie que R est allé au bout mais que le résultat doit être vérifié ; un message est une information. Un
+dans la console signale une ligne inachevée : appuyez sur Échap. - Posez des questions auxquelles on peut répondre : l’objectif, le plus petit code qui échoue, le message exact, ce que vous attendiez.
- Les opérations sur les vecteurs sont vectorisées ;
NAest contagieux, utilisez doncna.rm = TRUEen connaissance de cause. - Un data frame est un ensemble de vecteurs de même longueur :
data$col,data[rows, cols]. PIB par habitant = PIB / population. - Le pipe
|>transmet le résultat d’une étape à la suivante :x |> f() |> g(). Quand une chaîne échoue, exécutez-la une étape à la fois.