За цикъл в R с примери за списък и матрица

⚡ Умно обобщение

Цикълът For в R изпълнява блок код веднъж за всеки елемент от последователност, независимо дали тази последователност е вектор, списък или матрица. Това ръководство итерира през всеки от тях и показва кога векторизираният код е по-добрият избор.

  • 🔁 Основен синтаксис: for (i in vector) { expression } присвоява всеки елемент на i последователно и изпълнява тялото.
  • 📋 Всеки обект: Същият синтаксис обхожда вектор, списък, набор от колони на рамка с данни или редовете на матрица.
  • 🧮 Вложени цикли: Матрицата се нуждае от два цикъла, външен за редове и вътрешен за колони.
  • 🛑 Контрол на потока: break напуска цикъла изцяло, а next пропуска само текущия елемент.
  • Векторизация първо: Вградените векторизирани операции и семейството на apply са по-бързи и по-кратки от експлицитния цикъл.
  • ⚠️ Безопасни последователности: Използвайте seq_along(x) вместо 1:length(x), което се държи неправилно, когато обектът е празен.

Цикъл For в матрица от R списък

A за цикъл повтаря блок от код веднъж за всеки елемент от последователност. Тази последователност може да бъде вектор, списък, рамка от данни, матрица или друг обект, който R може да итерира. R е чувствителен към главни и малки букви, така че ключовата дума винаги е малка. за, а къдравите скоби са задължителни винаги, когато тялото обхваща повече от един ред.

Синтаксис на цикъл For в R

for (i in vector) {
    Exp
}

Тук

R ще премине през всички променливи във вектора и ще направи изчислението, записано в exp.

За цикъл в R
За цикъл в R

Нека видим няколко примера.

For цикъл в R Пример 1: Преминаваме през всички елементи на вектор и отпечатваме текущата стойност.

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

Изход:

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

For цикъл в R Пример 2: повдига на квадрат всяко цяло число от 1 до 4 и съхранява резултатите в списък.

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

Изход:

## [1]   1  4 9 16

Циклите for са полезни в машинното обучение. Настройването на параметър за регуляризация означава тестване на много кандидат-стойности и запазване...ping този, който минимизира функцията на загуба, а цикълът for е най-лесният начин за обхождане на този диапазон.

Как да използваме break и next в цикъл For

Две ключови думи прекъсват нормалната последователност на цикъл for.

  • почивка излиза от цикъла незабавно и пропуска всеки останал елемент.
  • до изоставя само текущия елемент и преминава към следващия.
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)
}

Във вложените цикли, break и next действат само върху най-вътрешния цикъл, който ги съдържа. За да оставите и двата цикъла в матричния пример, задайте променлива flag и я тествайте и във външния цикъл.

Използвайте seq_along() за индекси. Записването на for (i в 1:length(x)) изглежда безобидно, но се проваля при празен обект, защото 1:0 произвежда последователността 1, 0 и цикълът се изпълнява два пъти. seq_along(x) връща празна последователност, така че цикълът е правилно пропуснат:

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

Цикъл For върху списък

клозетping върху списък работи точно като тоалетнатаping върху вектор, с изключение на това, че всеки елемент може да съдържа различен тип:

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

Изход:

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

Цикъл For върху матрица

Матрицата има две измерения, редове и колони, така че итерирането през всяка клетка изисква два вложени for цикъла: външен за редовете и вътрешен за колоните.

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

Изход:

## [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 върху кадър от данни в R

Кадрът с данни е списък от колони, така че обикновен for цикъл обхожда колоните му, а не редовете му. Това обикновено е, което искате:

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

Обърнете внимание на двойната скоба. df[[col]] extracts колоната като вектор, докато df[col] връща рамка от данни с една колона, която mean() не може да обработи.

клозетping над редове. Итерацията по редове е възможна, но бавна, защото R копира реда при всяко преминаване:

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

За всичко над няколко хиляди реда, предпочитайте rowSums(df), apply(df, 1, sum) или dplyr. group_by() и summarize() конвейер, всички от които вършат една и съща работа без копиране.

For Loops срещу векторизация в R

R е векторизиран език: повечето от неговите оператори и функции вече действат върху цели вектори едновременно, в компилиран C код. Изричен цикъл, който повтаря векторизирана операция елемент по елемент, е едновременно по-дълъг и по-бавен.

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

# Vectorized version, same result
squares <- (1:4)^2
Task Контур Векторизиран еквивалент
Елементна аритметика за над всеки елемент x * 2, x + y, x^2
Прилагане на функция за всяка колона за над имена (df) sapply(df, средна стойност)
Прилагане на функция на ред за над seq_len(nrow(df)) прилагам(df, 1, сума)
Създайте списък с резултати за със списък[[i]] <- … lapply(v, f)
Условно прекодиране за с if и else ако(условие, a, b)

Когато цикълът все още е правилният отговор. Запазете цикъла for, когато всяка итерация зависи от предишния резултат, когато извиквате външна услуга или записвате файлове, или когато яснотата е по-важна от скоростта при малък обект.

Ако трябва да правите цикъл, направете предварително разпределение. Увеличаването на обект в цикъл принуждава R да го копира на всеки проход. Първо го създайте в пълен размер:

# 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 в R: Бърз справочник

Всяка конструкция, използвана в този урок, е изброена по-долу:

Цел Code
Цикъл върху вектор
for (i in v) { print(i) }
Безопасно преминаване през индекси
for (i in seq_along(v)) { print(v[i]) }
Цикъл върху списък
for (p in my_list) { print(p) }
Цикъл върху колони от рамката с данни
for (col in names(df)) { print(mean(df[[col]])) }
Цикъл върху матрица
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
Излезте от цикъла рано
if (condition) break
Пропускане на една итерация
if (condition) next
Предварително разпределете изхода
out <- numeric(n)

Въпроси и Отговори

Когато x е празно, 1:length(x) връща последователността 1, 0 и цикълът се изпълнява два пъти върху несъществуващи елементи. seq_along(x) връща празна последователност, така че цикълът е правилно пропуснат.

Самият цикъл не е проблем. Проблемът е в нарастването на обект вътре в него, защото R копира целия обект при всяко преминаване. Предварително разпределете резултата или използвайте векторизирана функция и празнината до голяма степен ще изчезне.

Колони. Кадрът с данни е списък от колони, така че всяка итерация ви предоставя една цяла колона. Използвайте seq_len(nrow(df)) изрично, ако е необходимо да се разхождате по редовете.

Циклите for управляват хиперпараметрични обхождания, кръстосани валидационни сгъвания и епохи на обучение. Всяка от тях има известен брой итерации, което е точно това, за което е проектирана конструкцията for.

Да. Асистентите с изкуствен интелект могат да конвертират повечето цикли по елементи във векторизирани или еквиваленти от типа „apply-family“. Сравнете резултата от двете версии с identique(), преди да замените оригинала.

Обобщете тази публикация с: