Data frames et tibbles en R : créer, inspecter, convertir
Créer, inspecter et convertir les deux structures de données rectangulaires de R
Manipulez les deux structures de données rectangulaires de R : le data frame de base (data.frame(), la forme de mtcars et iris) et le tibble du tidyverse (tibble()). Créez-les, inspectez-les avec str(), head(), dim(), names() et summary(), accédez aux lignes et colonnes avec $, [[ ]] et [i, j], ajoutez ou modifiez des colonnes, comprenez les différences qui comptent (affichage, sous-ensemblage qui ne réduit jamais silencieusement à un vecteur, correspondance partielle, stringsAsFactors, colonnes-listes), et convertissez de l’un à l’autre avec as_tibble() et as.data.frame().
Date de publication
16 juillet 2026
Modifié
17 juillet 2026
AstucePoints clés
Un data frame est un tableau rectangulaire : les lignes sont des observations, les colonnes des variables, et chaque colonne peut contenir un type différent. Les jeux mtcars et iris intégrés sont des data frames.
Créez-en un avec data.frame() ; inspectez-le avec str(), head(), dim()/nrow()/ncol(), names() et summary().
Accédez aux colonnes avec df$col ou df[["col"]], et aux lignes/colonnes avec df[i, j] — un filtre de lignes s’écrit df[df$x > 3, ].
df[, 1]réduit le résultat à un vecteur ; conservez un data frame à une colonne avec df[, 1, drop = FALSE].
Un tibble (tibble::tibble()) est le data frame moderne du tidyverse : il affiche les 10 premières lignes avec le type des colonnes, [ ] ne réduit jamais silencieusement à un vecteur, il ne fait aucune correspondance partielle des noms, et il peut contenir des colonnes-listes.
Convertissez avec as_tibble(df) et as.data.frame(tbl) — les data frames de base ne nécessitent aucun package ; les tibbles s’affichent plus proprement et se comportent de façon plus prévisible dans les pipelines.
Introduction
Presque tous les jeux de données que vous chargez dans R arrivent sous la forme d’un data frame — un tableau où chaque ligne est une observation et chaque colonne une variable. C’est la structure que retourne read.csv(), la forme que prennent les jeux de données intégrés mtcars et iris, et ce qu’attendent presque toutes les fonctions de modélisation et de tracé. Savoir en créer un, regarder à l’intérieur, et en extraire les lignes et colonnes dont vous avez besoin est une compétence R fondamentale.
R vous donne en réalité deux variantes de ce tableau. Le data frame de base (data.frame()) est toujours disponible, sans aucune dépendance. Le tibble (tibble(), du tidyverse) est une refonte moderne de la même idée, qui s’affiche plus proprement et supprime quelques vieilles surprises. Cette leçon couvre d’abord le data frame de base — le créer, l’inspecter et le sous-ensembler — puis montre précisément en quoi un tibble diffère et quand recourir à chacun.
Qu’est-ce qu’un data frame ?
Un data frame stocke les données en lignes et en colonnes, comme un tableur ou une table de base de données. Sa caractéristique déterminante est que des colonnes différentes peuvent contenir des types différents — une colonne de texte, une colonne de nombres, une colonne de TRUE/FALSE — tant que chaque colonne a la même longueur. On en construit un en passant des vecteurs nommés à data.frame() :
# Each argument becomes a column; every column must be the same lengthpatients <-data.frame(name =c("Ann", "Ben", "Cara", "Dan"),age =c(34, 52, 41, 29),smoker =c(FALSE, TRUE, FALSE, TRUE))patients
name age smoker
1 Ann 34 FALSE
2 Ben 52 TRUE
3 Cara 41 FALSE
4 Dan 29 TRUE
Chaque argument nommé (name, age, smoker) devient une colonne, et les vecteurs s’alignent ligne par ligne. Le résultat est un tableau de 4 lignes et 3 colonnes mêlant des données de type caractère, numérique et logique.
La plupart du temps, vous ne construirez pas un data frame à la main — vous en chargerez un, ou utiliserez l’un des jeux intégrés de R. mtcars et irissont des data frames :
Avant d’analyser un tableau, regardez-le. Une poignée de fonctions répondent aux questions habituelles — quelle est sa taille, quelles sont ses colonnes, et qu’y a-t-il à l’intérieur ?
patients <-data.frame(name =c("Ann", "Ben", "Cara", "Dan"),age =c(34, 52, 41, 29),smoker =c(FALSE, TRUE, FALSE, TRUE))# str() is the single most useful overview: dimensions + each column's typestr(patients)
'data.frame': 4 obs. of 3 variables:
$ name : chr "Ann" "Ben" "Cara" "Dan"
$ age : num 34 52 41 29
$ smoker: logi FALSE TRUE FALSE TRUE
str() (structure) affiche le nombre d’observations et de variables, puis le nom, le type et les premières valeurs de chaque colonne en un bloc compact — la première chose à exécuter sur tout tableau inconnu.
Pour vérifier rapidement les dimensions et les noms, utilisez les fonctions dédiées :
patients <-data.frame(name =c("Ann", "Ben", "Cara", "Dan"),age =c(34, 52, 41, 29),smoker =c(FALSE, TRUE, FALSE, TRUE))nrow(patients) # number of rows
[1] 4
ncol(patients) # number of columns
[1] 3
dim(patients) # both at once: rows, columns
[1] 4 3
names(patients) # the column names
[1] "name" "age" "smoker"
Et summary() fournit un aperçu statistique par colonne — min/médiane/moyenne/max pour les colonnes numériques, effectifs pour les autres :
name age smoker
Length:4 Min. :29.00 Mode :logical
Class :character 1st Qu.:32.75 FALSE:2
Mode :character Median :37.50 TRUE :2
Mean :39.00
3rd Qu.:43.75
Max. :52.00
head(df) (premières lignes) et tail(df) (dernières lignes) complètent la panoplie ; ensemble, elles vous permettent de vous orienter dans n’importe quel data frame en quelques secondes.
Accéder aux colonnes et aux lignes
On extrait des données d’un data frame de plusieurs manières interchangeables. Pour saisir une seule colonne sous forme de vecteur, utilisez $ avec le nom de la colonne ou [[ ]] avec le nom entre guillemets :
patients <-data.frame(name =c("Ann", "Ben", "Cara", "Dan"),age =c(34, 52, 41, 29),smoker =c(FALSE, TRUE, FALSE, TRUE))patients$age # the age column, as a numeric vector
[1] 34 52 41 29
patients[["age"]] # identical result
[1] 34 52 41 29
df$col est la forme courante ; df[["col"]] fait la même chose mais prend le nom sous forme de chaîne, ce dont vous avez besoin quand le nom de la colonne est stocké dans une variable.
Pour une tranche rectangulaire, utilisez la forme à deux indices df[rows, columns] — laissez une position vide pour signifier « toutes » :
patients[2:3, c("name", "age")] # rows 2-3, two named columns
name age
2 Ben 52
3 Cara 41
L’opération la plus courante est un filtre de lignes — conserver les lignes où une condition est TRUE. Placez le test logique en position de ligne et laissez la position de colonne vide :
patients <-data.frame(name =c("Ann", "Ben", "Cara", "Dan"),age =c(34, 52, 41, 29),smoker =c(FALSE, TRUE, FALSE, TRUE))# Keep only the smokerspatients[patients$smoker, ]
name age smoker
2 Ben 52 TRUE
4 Dan 29 TRUE
# Keep rows where age is above 40patients[patients$age >40, ]
name age smoker
2 Ben 52 TRUE
3 Cara 41 FALSE
patients$age > 40 produit un vecteur logique (FALSE TRUE TRUE FALSE), et l’indexation avec ce vecteur ne retourne que les lignes TRUE.
Le piège drop = FALSE
Il y a une surprise qu’il vaut la peine de connaître dès maintenant. Quand vous sélectionnez une seule colonne avec la forme [ , ], R de base réduit le résultat à un simple vecteur au lieu de conserver un data frame :
class(patients[, "age", drop =FALSE]) # "data.frame" — kept as a table
[1] "data.frame"
Sélectionner deux colonnes ou plus conserve un data frame, mais une seule colonne s’effondre silencieusement. Ajoutez drop = FALSE quand vous avez besoin que le résultat reste un data frame à une colonne — une source fréquente de bugs « pourquoi mon data frame s’est-il transformé en vecteur ? ». (Comme vous le verrez plus bas, les tibbles suppriment complètement ce piège.)
Ajouter ou modifier une colonne
Affectez à un nom de colonne avec $ pour ajouter une nouvelle colonne ou en écraser une existante. Le membre de droite doit simplement avoir la même longueur que le nombre de lignes (ou être une valeur unique que R recyclera) :
name age smoker age_group age_months
1 Ann 34 FALSE under 40 408
2 Ben 52 TRUE 40+ 624
3 Cara 41 FALSE 40+ 492
4 Dan 29 TRUE under 40 348
Affecter à un nom qui n’existe pas encore ajoute une colonne à droite ; affecter à un nom existant la remplace. C’est ainsi que vous créez de nouvelles variables à partir de variables existantes.
Les tibbles : le data frame moderne
Un tibble est la version du data frame proposée par le tidyverse — la structure que les packages dplyr, ggplot2 et readr produisent et attendent. C’est un data frame (chaque tibble passe is.data.frame()), donc tout ce qui précède fonctionne encore ; il corrige simplement une poignée de désagréments de longue date. Créez-en un avec tibble() du package tibble, exactement comme vous le feriez avec data.frame() :
# A tibble: 3 × 3
name score pass
<chr> <dbl> <lgl>
1 Ann 90.5 TRUE
2 Ben 82.1 FALSE
3 Cara 77.8 TRUE
Regardez cet affichage — c’est la première chose que vous remarquerez à propos des tibbles. Il indique les dimensions (# A tibble: 3 × 3), et sous chaque nom de colonne une abréviation de type : <chr> pour caractère, <dbl> pour double (numérique), <lgl> pour logique. Vous voyez d’un coup d’œil ce que vous tenez, sans appel séparé à str().
Le contraste est le plus net sur un tableau plus grand. Un data frame de base affiche toutes les lignes — print(mtcars) déverse ses 32 lignes dans la console — tandis que le convertir en tibble n’affiche que les 10 premières lignes plus un pied de tableau indiquant combien il en reste :
library(tibble)as_tibble(mtcars) # first 10 rows, column types, and a "# ℹ 22 more rows" footer
Sur un vrai jeu de données de milliers de lignes, c’est la différence entre un résumé lisible et une console inondée.
En quoi un tibble diffère d’un data frame
L’affichage épuré est le changement visible, mais quelques différences de comportement comptent davantage en pratique.
1. L’affichage montre les types et tronque. Comme ci-dessus, un tibble indique le type de chaque colonne et n’affiche que les 10 premières lignes — un data frame de base affiche tout et aucun type.
2. [ ] ne réduit jamais à un vecteur. Vous vous souvenez du piège drop = FALSE ? Les tibbles ne l’ont pas. Sélectionner une seule colonne avec [ , ] retourne toujours un tibble, si bien que votre code ne casse jamais parce qu’un tableau serait devenu un vecteur à l’improviste :
library(tibble)tb <-as_tibble(mtcars)class(tb[, "mpg"]) # still "tbl_df" — a tibble, never dropped
[1] "tbl_df" "tbl" "data.frame"
Utilisez tb$mpg ou tb[["mpg"]] quand vous voulez délibérément la colonne sous forme de vecteur.
3. Aucune correspondance partielle des noms. Avec un data frame de base, $ correspondra silencieusement à un préfixe d’un nom de colonne — df$al retourne la colonne alpha. Ce comportement « serviable » masque les fautes de frappe. Un tibble refuse de deviner : il retourne NULL (avec un avertissement), de sorte que l’erreur apparaît immédiatement.
# base data frame: $ partial-matches a prefix (a silent trap)df <-data.frame(alpha =1:3)df$al # returns the alpha column, no error
[1] 1 2 3
# tibble: no partial matching — you get NULL and a warning, not a wrong columnlibrary(tibble)tb <-tibble(alpha =1:3)tb$al # NULL + "Unknown or uninitialised column: `al`"
Warning: Unknown or uninitialised column: `al`.
NULL
4. stringsAsFactors — un piège historique que les tibbles n’ont jamais eu. Avant R 4.0, data.frame() convertissait par défaut les colonnes de caractères en facteurs (stringsAsFactors = TRUE), ce qui a surpris des générations d’utilisateurs. Depuis R 4.0.0 la valeur par défaut est FALSE, donc data.frame() conserve les chaînes comme caractères — mais vous rencontrerez encore l’ancien comportement dans du code et des tutoriels plus anciens. Les tibbles n’ont jamais fait cette conversion :
# Since R 4.0, base data.frame keeps strings as character (was factor before)df <-data.frame(name =c("Ann", "Ben"))class(df$name) # "character" on R >= 4.0
[1] "character"
5. Les tibbles autorisent les colonnes-listes. Une colonne de tibble peut contenir une liste, si bien que chaque cellule peut renfermer un vecteur entier, un modèle ou un tableau imbriqué — impossible à créer proprement avec data.frame(). C’est le fondement des flux de travail avancés du tidyverse :
# A tibble: 2 × 2
id vals
<int> <list>
1 1 <int [3]>
2 2 <int [7]>
Convertir de l’un à l’autre
Passer de l’un à l’autre tient à une fonction dans chaque sens. as_tibble() transforme un data frame en tibble ; as.data.frame() retransforme un tibble en data frame ordinaire :
library(tibble)# data frame -> tibbleiris_tbl <-as_tibble(iris)class(iris_tbl) # "tbl_df" "tbl" "data.frame"
[1] "tbl_df" "tbl" "data.frame"
# tibble -> plain data frameiris_df <-as.data.frame(iris_tbl)class(iris_df) # "data.frame"
[1] "data.frame"
Remarquez que la classe d’un tibble inclut "data.frame" — c’est pourquoi toute opération de data frame de base fonctionne encore sur lui.
Lequel utiliser ? Optez pour un data frame de base quand vous voulez zéro dépendance (il est toujours là, dans chaque installation de R) ou quand une fonction en retourne ou en attend un précisément. Optez pour un tibble quand vous travaillez dans le tidyverse, que vous voulez l’affichage plus épuré sur de grands tableaux, ou que vous voulez le sous-ensemblage plus sûr et l’absence de correspondance partielle dans un pipeline plus long. Ils sont suffisamment interchangeables pour que la conversion soit peu coûteuse — choisissez celui qui convient à la tâche.
Essayez en direct
Les blocs ci-dessus se sont exécutés au moment de la génération. Modifiez celui-ci et appuyez sur Run pour construire un data frame, l’inspecter et le convertir en tibble — il s’exécute dans votre navigateur via webR, aucune installation.
🟢 Avec un agent IA
Vous ne savez pas si une fonction vous a remis un data frame ou un tibble — ou pourquoi une colonne s’est transformée en vecteur ? Collez l’objet et demandez à Prova« quelle est cette structure et comment la garder en data frame ? » — elle explique la classe et la correction. Ensuite, parce que le runtime est juste ici, exécutez vous-même class() et str() dessus et confirmez que la réponse correspond à ce que R contient réellement — l’explication n’est juste que si le code est d’accord. Demander à Prova →
Vous travaillez en Python ? Les DataFrame de pandas couvrent le même terrain — construisez-en un avec pd.DataFrame({...}), inspectez avec .info()/.head()/.shape, sélectionnez des colonnes avec df["col"], et filtrez les lignes avec df[df["x"] > 3]. Un guide pandas arrive dans la série Python.
Problèmes fréquents
Mon data frame s’est transformé en vecteur. Sélectionner une seule colonne avec la forme [ , ] réduit le résultat à un simple vecteur : df[, 1] ou df[, "age"] retourne un vecteur numérique, pas un data frame à une colonne. Ajoutez drop = FALSE — df[, "age", drop = FALSE] — pour conserver un tableau. Les tibbles n’ont pas ce comportement, donc passer d’abord par as_tibble(df) est un autre moyen de l’éviter.
Du vieux code a transformé mon texte en facteurs. Le code écrit pour R avant la version 4.0 s’appuyait sur l’ancienne valeur par défaut stringsAsFactors = TRUE de data.frame(), si bien que les colonnes de caractères devenaient des facteurs — ce qui casse les opérations sur les chaînes et affiche des niveaux inattendus. Sur R moderne, la valeur par défaut est FALSE ; si vous exécutez de vieux scripts et avez besoin de l’ancien comportement, définissez-le explicitement avec data.frame(..., stringsAsFactors = TRUE), ou reconvertissez une colonne avec as.character().
Un tibble s’affiche différemment et j’ai cru qu’il était cassé. Un tibble n’affiche délibérément que les 10 premières lignes plus un pied # ℹ N more rows, et liste le type des colonnes sous les noms — c’est une fonctionnalité, pas des données tronquées. Toutes les lignes sont toujours là ; utilisez print(tb, n = 50) pour en voir plus, ou as.data.frame(tb) pour l’affichage complet classique.
Questions fréquentes
NoteQuelle est la différence entre un data frame et un tibble en R ?
Un tibble est un data frame moderne issu du tidyverse : c’est un data frame (il passe is.data.frame()), mais il n’affiche que les 10 premières lignes avec le type de chaque colonne, son sous-ensemblage [ ] ne réduit jamais silencieusement une seule colonne à un vecteur, il ne fait aucune correspondance partielle des noms, et il peut contenir des colonnes-listes. Un data.frame() de base affiche toutes les lignes, réduit les colonnes uniques à des vecteurs sauf si vous ajoutez drop = FALSE, et fait de la correspondance partielle des noms de colonnes avec $. Les deux stockent les mêmes données rectangulaires.
NoteComment créer un data frame en R ?
Passez des vecteurs nommés de longueur égale à data.frame() : data.frame(name = c("Ann", "Ben"), age = c(34, 52)). Chaque argument nommé devient une colonne, et les vecteurs s’alignent ligne par ligne. Pour un tibble, utilisez tibble() du package tibble avec la même syntaxe.
NoteComment convertir un data frame en tibble ?
Utilisez as_tibble() du package tibble (ou dplyr) : as_tibble(my_data_frame). Pour aller dans l’autre sens — d’un tibble vers un data frame ordinaire — utilisez as.data.frame(my_tibble). La classe d’un tibble inclut toujours "data.frame", donc les opérations de base fonctionnent sur lui dans les deux cas.
NotePourquoi df[, 1] retourne-t-il un vecteur au lieu d’un data frame ?
Parce que R de base réduit par défaut une sélection d’une seule colonne à un vecteur. df[, 1] et df[, "col"] retournent la colonne sous forme de simple vecteur ; sélectionner deux colonnes ou plus conserve un data frame. Pour forcer un data frame à une colonne, ajoutez drop = FALSE : df[, 1, drop = FALSE]. Les tibbles ne réduisent jamais, donc as_tibble(df)[, 1] reste un tibble.
NoteComment filtrer les lignes d’un data frame en R ?
Placez une condition logique en position de ligne de [ , ] et laissez la position de colonne vide : df[df$age > 40, ] conserve chaque ligne où age est supérieur à 40. La condition produit un vecteur TRUE/FALSE, et l’indexation avec ce vecteur ne retourne que les lignes TRUE. Combinez les conditions avec & (et) et | (ou).
Testez vos connaissances
ImportantExercice : construire, inspecter, filtrer et convertir
Construisez un data frame cars2 à partir du jeu intégré mtcars avec uniquement les colonnes mpg et cyl pour les 8 premières voitures. Conservez ensuite uniquement les lignes dont le mpg est supérieur à 20, et convertissez le résultat en tibble.
# Column names go in quotes inside c(...): c("mpg", "cyl").# Filter on the mpg column: cars2$mpg > 20.# Convert with as_tibble().
library(tibble)
cars2 <- mtcars[1:8, c("mpg", "cyl")] # first 8 rows, mpg and cyl
cars2 <- cars2[cars2$mpg > 20, ] # keep mpg above 20
as_tibble(cars2) # a tibble with <dbl> columns
library(tibble)cars2 <- mtcars[1:8, c("mpg", "cyl")] # first 8 rows, mpg and cylcars2 <- cars2[cars2$mpg >20, ] # keep mpg above 20as_tibble(cars2) # a tibble with <dbl> columns
NoteVérification rapide : que retourne ceci ?
df <-data.frame(x =1:3, y =4:6)class(df[, "x"])
A. "data.frame" B. "integer" C. "tbl_df"
Afficher la réponse
B. Sélectionner une seule colonne avec la forme [ , ]réduit le résultat à un simple vecteur — ici un vecteur d’entiers — donc class() renvoie "integer", et non "data.frame". Ajoutez drop = FALSE pour conserver un data frame à une colonne, ou utilisez un tibble, qui ne réduit jamais.
Conclusion
Un data frame est le tableau central de R — les lignes sont des observations, les colonnes des variables, et les colonnes peuvent différer par leur type. Créez-en un avec data.frame(), regardez à l’intérieur avec str(), head(), dim(), names() et summary(), extrayez des données avec $, [[ ]] et df[rows, cols] (un filtre de lignes est df[df$x > 3, ]), et ajoutez des colonnes en affectant à un nom. Un tibble est le même tableau modernisé : affichage plus épuré avec le type des colonnes, sous-ensemblage qui ne réduit jamais silencieusement à un vecteur, aucune correspondance partielle, et colonnes-listes — convertissez avec as_tibble() et as.data.frame(). Utilisez un data frame de base pour la simplicité sans dépendance et un tibble pour le travail dans le tidyverse et un comportement plus sûr et plus prévisible.
Cette leçon est reproductible : chaque résultat de cette page a été produit par le code affiché — modifiez n’importe quel bloc et appuyez sur Run pour le reproduire dans votre navigateur. The runtime is the judge.