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

Что такое цикл for в R
Цикл for в R выполняет блок кода повторно для каждого элемента указанного набора значений. Один короткий термин: итерация — одно выполнение тела цикла с конкретным значением переменной цикла. Цикл управляется переменной-итератором, которая принимает последовательно значения из последовательности после ключевого слова in.
Циклы в R применяются для:
- повторных вычислений (суммы, агрегаты);
- форматированного вывода множества строк или отчётов;
- итеративной обработки объектов, если нельзя (или неудобно) применять векторизированные операции.
Базовый синтаксис for в R
Синтаксис очень близок к другим языкам: после in может быть диапазон (1:10), вектор, список и т.п. Переменная цикла получает либо индекс, либо само значение в зависимости от используемой последовательности.
Фиксированное число итераций
Пример фиксированного диапазона:
for (x in 1:10) {
print(x)
}Здесь x принимает значения 1,2,…,10. После каждой итерации происходит проверка — дошли ли мы до конечного значения.
Итерация по массивам, спискам и векторам
Если после in указать вектор или список, переменная цикла будет принимать не индекс, а элементы этого объекта — поведение похоже на foreach в других языках:
employees <- list("Ben", "Jane", "Suzi", "Josh", "Carol")
for (x in employees) {
print(x)
}В этом примере x будет поочерёдно строками “Ben”, “Jane” и т.д. Такой подход удобен для перебора объектов без явного обращения по индексу.
Создание вектора прямо в объявлении цикла (c)
Функция c объединяет элементы в вектор — её удобно использовать прямо в объявлении цикла:
for (x in c("Ben", "Jane", "Suzi", "Josh", "Carol")) {
print(x)
}Вывод будет таким же, как в предыдущем примере.
Операторы перехода в циклах: break и next
Два ключевых оператора позволяют менять поток выполнения внутри цикла: break и next. Они служат разным целям — важно понимать разницу.
break
break немедленно прекращает выполнение текущего цикла и передаёт управление дальше по коду за его пределами:
days <- c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
"Sunday")
for (x in days) {
if (x == "Saturday") {
break
}
print(x)
}Результат: печать только рабочих дней — цикл остановится, когда встретит “Saturday”.
next
next пропускает оставшуюся часть текущей итерации, но сам цикл продолжается для следующих элементов:
days <- c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
"Sunday")
for (x in days) {
if (x == "Saturday") {
next
}
print(x)
}Результат: будут напечатаны все дни, кроме субботы. Это полезно, когда нужно просто пропустить обработку для определённых значений.
Практические примеры использования
Ниже — типичные сценарии, где цикл for бывает полезен в реальной аналитике данных.
Суммирование значений из списка заказов
orders <- list(23.4, 699.8, 1042.0)
total <- 0.0
for (order in orders) {
total <- order + total
}
cat("the total is $", total, "\n")Этот цикл последовательно добавляет каждое значение в общий total.
Форматированный вывод по дням
day_totals <- c(567.82, 364.72, 762.81, 354.99, 622.87)
for (day in 1:length(day_totals)) {
cat("Day #", day, ": $", day_totals[day],"\n")
day <- day + 1
}Цикл печатает пронумерованные строки с суммами по дням. Обратите внимание: увеличение переменной day в конце итерации здесь избыточно, потому что for сам назначает следующее значение перебора — изменение счётчика внутри тела цикла редко нужно и может запутать читателей.
Вычисление среднего значения
test_scores <- c(67, 89, 72, 44)
score_total <- 0
num_tests <- 0
for (score in test_scores) {
score_total <- score_total + score
num_tests <- num_tests + 1
}
average_score <- score_total / num_tests
print(average_score)Цикл аккумулирует сумму и количество элементов, после чего вычисляет среднее — стандартный шаблон обхода коллекции.
Когда for работает плохо: ограничения и альтернативы
Циклы for просты и понятны, но при работе с большими объёмами данных они могут быть медленнее векторных операций. Вот несколько альтернатив:
- Векторизация: операции над целыми векторами (например, +, *, логические сравнения) реализованы очень эффективно в R.
- apply, lapply, sapply, vapply: функции для обхода матриц, списков и векторов с возвращением результатов в удобной форме.
- purrr::map и другие функции пакета purrr дают чистый, функциональный стиль и хорошо читаемую композицию.
- data.table и dplyr: для работы с таблицами часто можно выразить операцию через группировки и агрегации без явных циклов.
Пример замены цикла суммирования на векторную операцию (тот же результат, быстрее и компактнее):
orders <- c(23.4, 699.8, 1042.0)
total <- sum(orders)
cat("the total is $", total, "\n")Эвристики и ментальные модели
- Если задача сводится к применению одной операции ко всем элементам и результат сохраняется в вектор — сначала попытайтесь векторизовать.
- Если операция на элементе зависит от предыдущих результатов (например, рекурсивные вычисления, скользящие суммы), цикл for более естественен.
- Для создания сложных структур результата (списков, фреймов) рассмотрите использование lapply/map, они чаще дают корректную и предсказуемую форму результата.
Производительность и хорошие практики
- Избегайте расширять вектор внутри цикла (например, делать result <- c(result, x) в каждой итерации) — это дорого по аллокациям. Лучше заранее выделить нужный размер или собирать в список и затем конвертировать.
- Не изменяйте переменную-итератор вручную внутри тела цикла — это усложняет чтение и может привести к ошибкам.
- Профилируйте код (Rprof, profvis), если предполагается работа с большими данными.
Ролевые чек-листы перед использованием for
Для аналитика данных:
- Можно ли заменить цикл векторной операцией? Если да — используйте её.
- Нужно ли сохранять результаты промежуточно? Выделите контейнер заранее.
Для разработчика кода:
- Есть ли тесты, покрывающие граничные случаи (пустой вектор, один элемент)?
- Является ли код читаемым для коллег? Добавьте комментарии и понятные имена переменных.
Мини-методология: как выбирать между for и альтернативами
- Оцените зависимость итераций от предыдущих шагов.
- Попробуйте выразить операцию векторно (sum, mean, arithmetic).
- Если требуется сложная логика на каждом элементе — рассмотрите lapply/purrr::map.
- Если ничего из вышеперечисленного не подходит — используйте for, но соблюдайте практики производительности.
Критерии приёмки
- Код корректно обрабатывает пустые коллекции и коллекции с одним элементом.
- Результаты совпадают с векторной реализацией (если применимо).
- Нет роста используемой памяти за счёт постоянного расширения вектора в цикле.
Глоссарий (в одну строку)
- Итерация: одно выполнение тела цикла для конкретного значения переменной цикла.
Контрпримеры и типичные ошибки
- Попытка изменить индексную переменную вручную внутри for (например, day <- day + 1) — обычно лишняя и вводит в заблуждение.
- Использование for для операций, которые легко выражаются sum, mean, apply — это приводит к неоптимальному коду.
- Модификация коллекции, по которой идёт перебор, во время итерации может привести к непредсказуемому поведению.
Краткое резюме
Циклы for — фундаментальный инструмент в R: они просты, универсальны и понятны. Для многих задач, особенно тех, что зависят от состояния между итерациями, for остаётся лучшим выбором. Но при работе с большими объёмами данных сначала подумайте о векторизации и функциях apply/purrr, чтобы получить лучшую производительность и более идиоматичный R-код.
Extras: шаблон социальных сетей — заголовок: “Циклы for в R: понятные примеры и советы”; описание: “Быстрое руководство по for в R: синтаксис, break/next, альтернативы и практические приёмы.”.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone