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

A за цикъл повтаря блок от код веднъж за всеки елемент от последователност. Тази последователност може да бъде вектор, списък, рамка от данни, матрица или друг обект, който R може да итерира. R е чувствителен към главни и малки букви, така че ключовата дума винаги е малка. за, а къдравите скоби са задължителни винаги, когато тялото обхваща повече от един ред.
Синтаксис на цикъл For в R
for (i in vector) { Exp }
Тук
R ще премине през всички променливи във вектора и ще направи изчислението, записано в exp.

Нека видим няколко примера.
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) |
