R Academy · leksjon

keep(), discard() og filtrering av lister

Filtrer listeelementer med predikatfunksjoner for ryddige pipelines.

Leksjon 4 av 413 trinn

keep(), discard() og filtrering av lister er en gratis leksjon i R Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i R Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i R Academy inneholder totalt 4 leksjoner.

Filtrere lister med purrr

purrr tilbyr en familie med funksjoner for å filtrere, søke i og teste lister basert på predikater. Et predikat er en funksjon som returnerer TRUE eller FALSE. Disse funksjonene erstatter omstendelige kall til Filter() og betingede løkker.

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() — behold elementer som samsvarer med et predikat

keep(.x, .p) beholder bare elementene i .x der predikatet .p returnerer TRUE. Det er det motsatte av discard(). Predikatet kan være et funksjonsnavn, en formel eller en logisk vektor.

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() — fjern elementer som samsvarer med et predikat

discard(.x, .p) fjerner elementene der predikatet returnerer TRUE, og beholder resten. Det er motstykket til keep(). Bruk det til å filtrere bort nullverdier, NA-er eller uønskede typer fra en liste.

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() — fjern NULL-elementer

compact(.x) fjerner alle NULL-elementer fra en liste — tilsvarende discard(.x, is.null), men mer kortfattet. Dette er særlig nyttig etter map()-kall som kan returnere NULL for enkelte inndata.

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() — finn første treff

detect(.x, .p) returnerer det første elementet som oppfyller predikatet. Hvis ingen elementer samsvarer, returnerer den NULL. Bruk detect(.right=TRUE) til å søke fra høyre og finne det siste treffet.

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() — finn posisjonen til første treff

detect_index(.x, .p) returnerer indeksen til det første elementet som oppfyller predikatet (eller 0L hvis ingen blir funnet). Dette er nyttig når De trenger posisjonen, ikke verdien — for eksempel for å oppdatere eller hente ut elementet.

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() — samsvarer alle elementene?

every(.x, .p) returnerer TRUE hvis predikatet er oppfylt for alle elementene. Den avslutter ved første FALSE. Tilsvarer all(map_lgl(.x, .p)), men evalueres latensk.

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() — samsvarer noen av elementene?

some(.x, .p) returnerer TRUE hvis minst ett element oppfyller predikatet. Den avslutter ved første TRUE. Tilsvarer any(map_lgl(.x, .p)), men evalueres latensk.

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() — samsvarer ingen av elementene?

none(.x, .p) returnerer TRUE hvis ingen elementer oppfyller predikatet. Det tilsvarer !some(.x, .p), men er tydeligere i valideringssammenhenger der De vil bekrefte at en betingelse ikke forekommer.

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)

Kombinere keep() med map()

Å lenke sammen keep() (eller discard()) med map() er et vanlig mønster: Filtrer først listen til relevante elementer, og bruk deretter en transformasjon. På denne måten holdes filtreringslogikken og behandlingslogikken tydelig atskilt.

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)

Bruke keep() med is.*-funksjoner

R sine innebygde is.*-predikatfunksjoner (is.numeric, is.character, is.null, is.na, is.finite) fungerer direkte som predikater i keep() og discard(), uten at de må pakkes inn i ~.

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))

Kort sjekk

Hva returnerer detect(.x, .p) når ingen elementer i .x oppfyller predikatet .p?

Oppsummering: Funksjoner for filtrering av lister

Dette er det viktigste å huske om purrrs verktøy for filtrering av lister:

  • keep(.x, .p) — beholder elementer der predikatet er TRUE
  • discard(.x, .p) — fjerner elementer der predikatet er TRUE
  • compact(.x) — fjerner alle NULL-elementer
  • detect(.x, .p) — returnerer det første elementet som samsvarer med predikatet (eller NULL)
  • detect_index(.x, .p) — returnerer indeksen til det første treffet (eller 0L)
  • every(.x, .p) — TRUE hvis alle elementene samsvarer
  • some(.x, .p) — TRUE hvis minst ett element samsvarer
  • none(.x, .p) — TRUE hvis ingen elementer samsvarer
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))
Gratis å komme i gang

Lær deg R med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
43
Leksjoner
159

Ofte stilte spørsmål

Er leksjonen «keep(), discard() og filtrering av lister» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien R Academy, inkludert «keep(), discard() og filtrering av lister», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i R Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «keep(), discard() og filtrering av lister»?

Filtrer listeelementer med predikatfunksjoner for ryddige pipelines. Du øver på R Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med R Academy?

Ingen tidligere erfaring er nødvendig. R Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «keep(), discard() og filtrering av lister»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne R Academy-leksjonen?

Ja. Alle R Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. map() og typede varianter
  2. map2() og pmap() for flere inndata
  3. reduce(), accumulate() og walk()
  4. keep(), discard() og filtrering av lister
← Tilbake til R Academy