For Loop in R met voorbeelden voor lijst en matrix

โšก Slimme samenvatting

Een `for`-lus in R voert een codeblok รฉรฉn keer uit voor elk element van een reeks, of die reeks nu een vector, een lijst of een matrix is. Deze handleiding doorloopt elk van deze reeksen en laat zien wanneer gevectoriseerde code de betere keuze is.

  • ๐Ÿ” Kernsyntaxis: De lus `for (i in vector) { expression }` wijst achtereenvolgens elk element toe aan `i` en voert de rest van de code uit.
  • ๐Ÿ“‹ Elk object: Dezelfde syntaxis kan worden gebruikt om een โ€‹โ€‹vector, een lijst, een set kolommen van een dataframe of de rijen van een matrix te doorlopen.
  • ๐Ÿงฎ Geneste lussen: Een matrix heeft twee lussen nodig: een buitenste voor de rijen en een binnenste voor de kolommen.
  • ๐Ÿ›‘ Datatransportbesturing: `break` verlaat de lus volledig en `next` slaat alleen het huidige element over.
  • โšก Vectorisatie eerst: Ingebouwde vectorbewerkingen en de `apply`-methode zijn sneller en korter dan een expliciete lus.
  • โš ๏ธ Veilige volgordes: Gebruik seq_along(x) in plaats van 1:length(x), want dat werkt niet goed als het object leeg is.

For-lus in R-lijstmatrix

A for loop Herhaalt een codeblok รฉรฉn keer voor elk element van een reeks. Die reeks kan een vector, een lijst, een dataframe, een matrix of elk ander object zijn waar R overheen kan itereren. R is hoofdlettergevoelig, dus het trefwoord is altijd in kleine letters. besteld,En de accolades zijn nodig wanneer de tekst zich over meer dan รฉรฉn regel uitstrekt.

For-lus syntaxis in R

for (i in vector) {
    Exp
}

Hier

R zal alle variabelen in vector herhalen en de berekening uitvoeren die in de exp is geschreven.

Voor lus in R
Voor lus in R

Laten we een paar voorbeelden bekijken.

Voor lus in R Voorbeeld 1: We herhalen alle elementen van een vector en drukken de huidige waarde af.

# Create fruit vector
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')
# Create the for statement
for ( i in fruit){ 
 print(i)
}

Output:

## [1] "Apple"
## [1] "Orange"
## [1] "Passion fruit"
## [1] "Banana"

Voor lus in R Voorbeeld 2: kwadrateer elk geheel getal van 1 tot 4 en sla de resultaten op in een lijst.

# Create an empty list
list <- c()
# Create a for statement to populate the list
for (i in seq(1, 4, by=1)) {
  list[[i]] <- i*i
}
print(list)

Output:

## [1]   1  4 9 16

For-lussen zijn nuttig in machine learning. Het afstemmen van een regularisatieparameter betekent het testen van veel kandidaatwaarden en het behouden van de optimale waarde.ping De functie die de verliesfunctie minimaliseert, en een for-lus is de meest eenvoudige manier om dat bereik te doorlopen.

Hoe gebruik je break en next in een for-lus?

Twee trefwoorden onderbreken de normale volgorde van een for-lus.

  • breken verlaat de lus onmiddellijk en slaat alle resterende elementen over.
  • volgende Verlaat alleen het huidige element en gaat verder met het volgende.
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')

# break: stop at the first match
for (i in fruit) {
    if (i == 'Passion fruit') {
        print('Found it, stopping here')
        break
    }
    print(i)
}

# next: skip one element and carry on
for (i in fruit) {
    if (i == 'Orange') next
    print(i)
}

In geneste lussen moeten `break` en `next` alleen worden uitgevoerd op de binnenste lus die ze bevat. Om beide lussen in het matrixvoorbeeld te verlaten, stelt u een vlagvariabele in en test u deze ook in de buitenste lus.

Gebruik seq_along() voor indexen. Het schrijven van `for (i in 1:length(x))` lijkt onschadelijk, maar mislukt bij een leeg object, omdat `1:0` de reeks 1, 0 oplevert en de lus twee keer wordt uitgevoerd. `seq_along(x)` retourneert in plaats daarvan een lege reeks, waardoor de lus correct wordt overgeslagen.

for (i in seq_along(fruit)) {
    cat(i, fruit[i], '\n')
}

For-lus over een lijst

Toiletping Het overschrijven van een lijst werkt precies hetzelfde als het overschrijven van een lijst.ping over een vector, met dien verstande dat elk element een ander type kan bevatten:

# Create a list with three vectors
fruit <- list(Basket = c('Apple', 'Orange', 'Passion fruit', 'Banana'), 
Money = c(10, 12, 15), purchase = FALSE)
for (p  in fruit) 
{ 
	print(p)
}

Output:

## [1] "Apple" "Orange" "Passion fruit" "Banana"       
## [1] 10 12 15
## [1] FALSE

For-lus over een matrix

Een matrix heeft twee dimensies, rijen en kolommen, dus om elke cel te doorlopen zijn twee geneste for-lussen nodig: een buitenste voor de rijen en een binnenste voor de kolommen.

# Create a matrix
mat <- matrix(data = seq(10, 20, by=1), nrow = 6, ncol =2)
# Create the loop with r and c to iterate over the matrix
for (r in 1:nrow(mat))   
    for (c in 1:ncol(mat))  
         print(paste("Row", r, "and column",c, "have values of", mat[r,c]))  

Output:

## [1] "Row 1 and column 1 have values of 10"
## [1] "Row 1 and column 2 have values of 16"
## [1] "Row 2 and column 1 have values of 11"
## [1] "Row 2 and column 2 have values of 17"
## [1] "Row 3 and column 1 have values of 12"
## [1] "Row 3 and column 2 have values of 18"
## [1] "Row 4 and column 1 have values of 13"
## [1] "Row 4 and column 2 have values of 19"
## [1] "Row 5 and column 1 have values of 14"
## [1] "Row 5 and column 2 have values of 20"
## [1] "Row 6 and column 1 have values of 15"
## [1] "Row 6 and column 2 have values of 10" 

For-lus over een dataframe in R

Een dataframe is een lijst met kolommen, dus een gewone for-lus doorloopt de kolommen in plaats van de rijen. Dat is meestal wat je wilt:

df <- data.frame(a = 1:5, b = 6:10, c = 11:15)

# Loop over the columns
for (col in names(df)) {
    cat(col, 'has mean', mean(df[[col]]), '\n')
}

Let op de dubbele haakjes. df[[col]] extracts geeft de kolom weer als een vector, terwijl df[col] een dataframe met รฉรฉn kolom retourneert dat mean() niet kan verwerken.

Toiletping over rijen. Rijgewijze iteratie is mogelijk, maar traag, omdat R de rij bij elke iteratie kopieert:

for (r in seq_len(nrow(df))) {
    cat('Row', r, 'sums to', sum(df[r, ]), '\n')
}

Voor meer dan een paar duizend rijen kunt u het beste rowSums(df), apply(df, 1, sum) of een dplyr gebruiken. group_by() en summarise() pijplijn, die allemaal hetzelfde werk doen zonder te kopiรซren.

For-lussen versus vectorisatie in R

R is een gevectoriseerde taal: de meeste operatoren en functies werken in gecompileerde C-code al direct op hele vectoren. Een expliciete lus die een gevectoriseerde bewerking element voor element herhaalt, is zowel langer als trager.

# Loop version
squares <- c()
for (i in 1:4) {
    squares[i] <- i * i
}

# Vectorized version, same result
squares <- (1:4)^2
Taak Ringleiding Gevectoriseerd equivalent
Elementgewijze rekenkunde voor over elk element x * 2, x + y, x^2
Pas per kolom een โ€‹โ€‹functie toe. voor over namen(df) sapply(df, mean)
Pas per rij een functie toe. voor over seq_len(nrow(df)) toepassen(df, 1, som)
Stel een lijst met resultaten samen. voor met lijst[[i]] <- โ€ฆ lapply(v, f)
Voorwaardelijke hercodering want met als en anders ifelse(cond, a, b)

Wanneer een lus nog steeds de juiste oplossing is. Gebruik de for-lus alleen wanneer elke iteratie afhankelijk is van het vorige resultaat, wanneer je een externe service aanroept of bestanden schrijft, of wanneer duidelijkheid belangrijker is dan snelheid bij een klein object.

Als je een lus nodig hebt, reserveer dan vooraf geheugen. Door een object binnen een lus te vergroten, dwing je R om het bij elke iteratie te kopiรซren. Maak het eerst op volledige grootte aan:

# Slow: the vector is reallocated on every pass
out <- c()
for (i in 1:1000) out[i] <- i^2

# Fast: allocated once
out <- numeric(1000)
for (i in 1:1000) out[i] <- i^2

For-lus in R: snel naslagwerk

Alle constructies die in deze handleiding worden gebruikt, staan โ€‹โ€‹hieronder vermeld:

Objectief Code
Loop over een vector
for (i in v) { print(i) }
Loop veilig over indexen
for (i in seq_along(v)) { print(v[i]) }
Loop door een lijst
for (p in my_list) { print(p) }
Loop over de kolommen van het dataframe
for (col in names(df)) { print(mean(df[[col]])) }
Loop over een matrix
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
Verlaat de lus vroegtijdig
if (condition) break
Sla รฉรฉn iteratie over.
if (condition) next
Reserveer de uitvoer vooraf.
out <- numeric(n)

Veelgestelde vragen

Als x leeg is, geeft 1:length(x) de reeks 1, 0 terug en wordt de lus twee keer uitgevoerd op niet-bestaande elementen. seq_along(x) geeft een lege reeks terug, waardoor de lus terecht wordt overgeslagen.

De lus zelf is niet het probleem. Het probleem zit hem in het vergroten van een object binnen de lus, omdat R het hele object bij elke iteratie kopieert. Als je het resultaat vooraf reserveert of een gevectoriseerde functie gebruikt, verdwijnt het probleem grotendeels.

Kolommen. Een dataframe is een lijst met kolommen, dus elke iteratie levert je รฉรฉn volledige kolom op. Gebruik expliciet `seq_len(nrow(df))` als je de rijen wilt doorlopen.

For-lussen sturen hyperparameter-sweeps, cross-validatie-folds en trainingsepochs aan. Elk van deze onderdelen heeft een bekend aantal iteraties, en dat is precies waarvoor de for-lus is ontworpen.

Ja. AI-assistenten kunnen de meeste elementgewijze lussen omzetten in gevectoriseerde of apply-achtige equivalenten. Vergelijk de uitvoer van beide versies met identical() voordat je het origineel vervangt.

Vat dit bericht samen met: