keep(), discard() e filtraggio delle liste
Filtri gli elementi delle liste con funzioni predicato per ottenere pipeline pulite.
keep(), discard() e filtraggio delle liste è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
Filtrare le liste con purrr
purrr offre una famiglia di funzioni per filtrare, cercare e verificare le liste in base a predicati. Un predicato è una funzione che restituisce TRUE o FALSE. Queste funzioni sostituiscono le chiamate prolisse a Filter() e i cicli condizionali.
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() — Conservare gli elementi che soddisfano un predicato
keep(.x, .p) conserva solo gli elementi di .x per i quali il predicato .p restituisce TRUE. È l'opposto di discard(). Il predicato può essere il nome di una funzione, una formula o un vettore logico.
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() — Rimuovere gli elementi che soddisfano un predicato
discard(.x, .p) rimuove gli elementi per i quali il predicato restituisce TRUE, conservando gli altri. È il complemento di keep(). Lo utilizzi per filtrare da una lista i valori nulli, gli NA o i tipi indesiderati.
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() — Rimuovere gli elementi NULL
compact(.x) rimuove tutti gli elementi NULL da una lista: equivale a discard(.x, is.null), ma è più conciso. È particolarmente utile dopo chiamate a map() che potrebbero restituire NULL per alcuni input.
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() — Trovare la prima corrispondenza
detect(.x, .p) restituisce il primo elemento che soddisfa il predicato. Se nessun elemento corrisponde, restituisce NULL. Utilizzi detect(.right=TRUE) per cercare da destra e trovare l'ultima corrispondenza.
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() — Trovare la posizione della prima corrispondenza
detect_index(.x, .p) restituisce l'indice del primo elemento che soddisfa il predicato, oppure 0L se non ne trova nessuno. È utile quando serve la posizione anziché il valore, ad esempio per aggiornare o estrarre quell'elemento.
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() — Tutti gli elementi corrispondono?
every(.x, .p) restituisce TRUE se il predicato è soddisfatto per ogni elemento. Interrompe la valutazione al primo FALSE. Equivale a all(map_lgl(.x, .p)), ma con valutazione lazy.
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() — Almeno un elemento corrisponde?
some(.x, .p) restituisce TRUE se almeno un elemento soddisfa il predicato. Interrompe la valutazione al primo TRUE. Equivale a any(map_lgl(.x, .p)), ma con valutazione lazy.
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() — Nessun elemento corrisponde?
none(.x, .p) restituisce TRUE se nessun elemento soddisfa il predicato. Equivale a !some(.x, .p), ma risulta più chiaro nei contesti di convalida in cui si vuole verificare l'assenza di una condizione.
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)Combinare keep() con map()
Concatenare keep() (o discard()) con map() è uno schema comune: prima si filtra la lista per conservare gli elementi pertinenti, poi si applica una trasformazione. In questo modo la logica di filtraggio e quella di elaborazione restano chiaramente separate.
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)Usare keep() con le funzioni is.*
Le funzioni predicato integrate di R is.* (is.numeric, is.character, is.null, is.na, is.finite) possono essere usate direttamente come predicati in keep() e discard(), senza doverle racchiudere in ~.
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))Verifica rapida
Che cosa restituisce detect(.x, .p) quando nessun elemento di .x soddisfa il predicato .p?
Riepilogo: funzioni per filtrare le liste
Punti chiave degli strumenti di purrr per filtrare le liste:
keep(.x, .p)— conserva gli elementi per cui il predicato è TRUEdiscard(.x, .p)— rimuove gli elementi per cui il predicato è TRUEcompact(.x)— rimuove tutti gli elementi NULLdetect(.x, .p)— restituisce il primo elemento che soddisfa il predicato (oppure NULL)detect_index(.x, .p)— restituisce l'indice della prima corrispondenza (oppure 0L)every(.x, .p)— TRUE se tutti gli elementi soddisfano il predicatosome(.x, .p)— TRUE se almeno un elemento soddisfa il predicatonone(.x, .p)— TRUE se nessun elemento soddisfa il predicato
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))Domande Frequenti
La lezione «keep(), discard() e filtraggio delle liste» è gratuita?
Sì — il testo completo di «keep(), discard() e filtraggio delle liste» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «keep(), discard() e filtraggio delle liste»?
Filtri gli elementi delle liste con funzioni predicato per ottenere pipeline pulite. Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «keep(), discard() e filtraggio delle liste»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- map() e varianti tipizzate
- map2() e pmap() per input multipli
- reduce(), accumulate() e walk()
- keep(), discard() e filtraggio delle liste