R Academy · Leçon

keep(), discard() et filtrage de listes

Filtrez les éléments d’une liste avec des fonctions prédicats pour créer des pipelines clairs.

Leçon 4 sur 413 étapes

keep(), discard() et filtrage de listes est une leçon R Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage R Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours R Academy comprend 4 leçons au total.

Filtrer des listes avec purrr

purrr fournit une famille de fonctions pour filtrer, rechercher et tester des listes à partir de prédicats. Un prédicat est une fonction qui renvoie TRUE ou FALSE. Ces fonctions remplacent les appels verbeux à Filter() et les boucles conditionnelles.

library(purrr)

# A mixed list to filter
mixed <- list(1L, 'hello', 3.14, NULL, TRUE, 42L, 'world', NULL)

cat('Total elements:', length(mixed), '\n')
cat('Non-NULL elements:', length(compact(mixed)))

keep() — Conserver les éléments correspondant à un prédicat

keep(.x, .p) conserve uniquement les éléments de .x pour lesquels le prédicat .p renvoie TRUE. C’est l’opposé de discard(). Le prédicat peut être un nom de fonction, une formule ou un vecteur logique.

library(purrr)

mixed <- list(1L, 'hello', 3.14, TRUE, 42L, 'world', 2.7)

# Keep only numeric values
numeric_only <- keep(mixed, is.numeric)
print(numeric_only)

# Keep values greater than 5
keep(mixed, ~is.numeric(.x) && .x > 5)

discard() — Supprimer les éléments correspondant à un prédicat

discard(.x, .p) supprime les éléments pour lesquels le prédicat renvoie TRUE et conserve les autres. C’est l’inverse de keep(). Utilisez-la pour exclure d’une liste les valeurs nulles, les NA ou les types indésirables.

library(purrr)

results <- list(
  model_a = list(rmse=2.5, converged=TRUE),
  model_b = list(rmse=NA, converged=FALSE),
  model_c = list(rmse=1.8, converged=TRUE),
  model_d = list(rmse=NA, converged=FALSE)
)

# Discard models that did not converge
converged_models <- discard(results, ~!.x$converged)
map_dbl(converged_models, ~.x$rmse)

compact() — Supprimer les éléments NULL

compact(.x) supprime tous les éléments NULL d’une liste — ce qui équivaut à discard(.x, is.null), en plus concis. Cette fonction est particulièrement utile après des appels à map() susceptibles de renvoyer NULL pour certaines entrées.

library(purrr)

# Simulate fetching data that might return NULL
ids <- 1:6
fetch_data <- function(id) {
  if (id %% 2 == 0) NULL else list(id=id, value=id*10)
}

raw_results <- map(ids, fetch_data)
cat('With NULLs:', length(raw_results), '\n')

clean_results <- compact(raw_results)
cat('Without NULLs:', length(clean_results))

detect() — Trouver la première correspondance

detect(.x, .p) renvoie le premier élément qui satisfait le prédicat. Si aucun élément ne correspond, la fonction renvoie NULL. Utilisez detect(.right=TRUE) pour effectuer la recherche de droite à gauche et trouver la dernière correspondance.

library(purrr)

prices <- list(15.99, 8.50, 23.99, 5.25, 19.99, 4.75)

# Find first price under $10
first_cheap <- detect(prices, ~.x < 10)
cat('First price under $10:', first_cheap, '\n')

# Find last price under $10
last_cheap <- detect(prices, ~.x < 10, .right=TRUE)
cat('Last price under $10:', last_cheap)

detect_index() — Trouver la position de la première correspondance

detect_index(.x, .p) renvoie l’indice du premier élément qui satisfait le prédicat (ou 0L si aucune correspondance n’est trouvée). Cette fonction est utile lorsque vous avez besoin de la position plutôt que de la valeur, par exemple pour mettre à jour ou extraire cet élément.

library(purrr)

models <- list(
  list(name='lm', rmse=3.5),
  list(name='rf', rmse=2.1),
  list(name='xgb', rmse=1.8),
  list(name='svm', rmse=2.4)
)

# Find the index of the best model (lowest RMSE)
best_idx <- detect_index(models, function(m) m$rmse < 2.0)
cat('Best model index:', best_idx, '\n')
cat('Best model name:', models[[best_idx]]$name)

every() — Tous les éléments correspondent-ils ?

every(.x, .p) renvoie TRUE si le prédicat est satisfait pour chaque élément. L’évaluation s’arrête dès le premier FALSE. C’est l’équivalent de all(map_lgl(.x, .p)), mais avec une évaluation différée.

library(purrr)

batch_results <- list(
  list(status='success', rows=150),
  list(status='success', rows=200),
  list(status='success', rows=175)
)

failed_batch <- list(
  list(status='success', rows=150),
  list(status='error', rows=0),
  list(status='success', rows=175)
)

cat('All success (good):', every(batch_results, ~.x$status == 'success'), '\n')
cat('All success (bad):', every(failed_batch, ~.x$status == 'success'))

some() — Certains éléments correspondent-ils ?

some(.x, .p) renvoie TRUE si au moins un élément satisfait le prédicat. L’évaluation s’arrête dès le premier TRUE. C’est l’équivalent de any(map_lgl(.x, .p)), mais avec une évaluation différée.

library(purrr)

datasets <- list(
  data.frame(x=1:3, y=c(1,NA,3)),
  data.frame(x=4:6, y=7:9),
  data.frame(x=7:9, y=c(NA,NA,NA))
)

# Does any dataset contain NAs?
cat('Any NAs:', some(datasets, anyNA), '\n')

# Is every dataset NA-free?
cat('All clean:', every(datasets, ~!anyNA(.x)))

none() — Aucun élément ne correspond-il ?

none(.x, .p) renvoie TRUE si aucun élément ne satisfait le prédicat. C’est l’équivalent de !some(.x, .p), mais la formulation est plus claire dans les contextes de validation où vous souhaitez vérifier l’absence d’une condition.

library(purrr)

api_responses <- list(
  list(code=200, data='OK'),
  list(code=200, data='OK'),
  list(code=201, data='Created')
)

# Ensure no errors occurred
no_errors <- none(api_responses, ~.x$code >= 400)
cat('No errors:', no_errors, '\n')

# Check another batch
bad_batch <- c(api_responses, list(list(code=500, data='Error')))
none(bad_batch, ~.x$code >= 400)

Combiner keep() et map()

Enchaîner keep() (ou discard()) avec map() est un schéma courant : vous filtrez d’abord la liste pour ne conserver que les éléments pertinents, puis vous appliquez une transformation. Cela sépare clairement la logique de filtrage de la logique de traitement.

library(purrr)

model_results <- list(
  list(name='A', converged=TRUE, rmse=2.5),
  list(name='B', converged=FALSE, rmse=NA),
  list(name='C', converged=TRUE, rmse=1.8),
  list(name='D', converged=TRUE, rmse=3.1)
)

# Keep converged, extract RMSE
model_results %>%
  keep(~.x$converged) %>%
  map_dbl(~.x$rmse)

Utiliser keep() avec les fonctions is.*

Les fonctions prédicats intégrées à R, is.* (is.numeric, is.character, is.null, is.na, is.finite), peuvent être utilisées directement comme prédicats dans keep() et discard(), sans avoir besoin de les envelopper dans ~.

library(purrr)

mixed_env <- list(
  count = 42L,
  name = 'Alice',
  ratio = 3.14,
  flag = TRUE,
  missing = NULL,
  data = data.frame(x=1:3)
)

# Extract different types
numeric_items <- keep(mixed_env, is.numeric)
cat('Numeric items:', length(numeric_items), '\n')

# Remove NULL items
cleaned <- discard(mixed_env, is.null)
cat('After removing NULL:', length(cleaned))

Vérification rapide

Que renvoie detect(.x, .p) lorsqu’aucun élément de .x ne satisfait le prédicat .p ?

Récapitulatif : fonctions de filtrage des listes

Points essentiels à retenir sur les outils de filtrage des listes de purrr :

  • keep(.x, .p) — conserve les éléments pour lesquels le prédicat vaut TRUE
  • discard(.x, .p) — supprime les éléments pour lesquels le prédicat vaut TRUE
  • compact(.x) — supprime tous les éléments NULL
  • detect(.x, .p) — renvoie le premier élément correspondant au prédicat (ou NULL)
  • detect_index(.x, .p) — renvoie l’indice de la première correspondance (ou 0L)
  • every(.x, .p) — TRUE si tous les éléments correspondent
  • some(.x, .p) — TRUE si au moins un élément correspond
  • none(.x, .p) — TRUE si aucun élément ne correspond
library(purrr)

scores <- list(45, 72, 88, 53, 91, 67, 39, 85)

passing <- keep(scores, ~.x >= 60)
failing <- discard(scores, ~.x >= 60)

cat('Passing:', length(passing), 'students\n')
cat('Failing:', length(failing), 'students\n')
cat('All pass:', every(scores, ~.x >= 60), '\n')
cat('Any fail:', some(scores, ~.x < 60), '\n')
cat('First pass score:', detect(scores, ~.x >= 60))
Gratuit pour commencer

Apprends R avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
43
Leçons
159

Questions Fréquemment Posées

La leçon « keep(), discard() et filtrage de listes » est-elle gratuite ?

Oui — le texte complet de « keep(), discard() et filtrage de listes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours R Academy, passe à CoddyKit PRO. Le cours R Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « keep(), discard() et filtrage de listes » ?

Filtrez les éléments d’une liste avec des fonctions prédicats pour créer des pipelines clairs. Tu pratiques R Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer R Academy ?

Aucune expérience préalable n'est requise. R Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « keep(), discard() et filtrage de listes » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon R Academy ?

Oui. Chaque leçon R Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. map() et ses variantes typées
  2. map2() et pmap() pour plusieurs entrées
  3. reduce(), accumulate() et walk()
  4. keep(), discard() et filtrage de listes
← Retour à R Academy