HEAD ======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
<<<<<<< HEAD ======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2for
Чтобы понять, зачем нужен цикл for
, представьте, что вас попросили увеличить первые 5 значений массива. С текущими знаниями мы бы сделали это следующим образом:
## [1] 9 5 1 7 6 5 10 2 7 9 5 3 6 10 3
## [1] 10 6 2 8 7 5 10 2 7 9 5 3 6 10 3
Код выглядит большим и некрасивым. А вдруг нас попросили бы это сделать для 1000 значений? Как-то не очень хочется 1000 раз прописывать по сути одну и ту же строчку, даже зная комбинацию клавиш Ctrl + C
Ctrl + V
.
Можно заметить, что в наших действиях менялся только индекс массива, остальное оставалось тем же. Этот индекс можно сделать переменной, которая меняется после выполнения действия. Преобразуем код.
k <- 1
v[k] <- v[k] + 1
k <- 2
v[k] <- v[k] + 1
k <- 3
v[k] <- v[k] + 1
k <- 4
v[k] <- v[k] + 1
k <- 5
v[k] <- v[k] + 1
Этот код выполняет то же, что и предыдущий. Теперь мы явно видим, что мы выполняем одну и ту же операцию v[k] <- v[k] + 1
, но при этом меняем индекс k
.
Для облегчения таких задач и придумали цикл for
. Его конструкция выглядит следующим образом.
for
Чтобы понять, зачем нужен цикл for
, представьте, что вас попросили увеличить первые 5 значений массива. С текущими знаниями мы бы сделали это следующим образом:
## [1] 4 7 9 1 8 4 7 5 3 3 9 10 3 9 1
## [1] 5 8 10 2 9 4 7 5 3 3 9 10 3 9 1
Код выглядит большим и некрасивым. А вдруг нас попросили бы это сделать для 1000 значений? Как-то не очень хочется 1000 раз прописывать по сути одну и ту же строчку, даже зная комбинацию клавиш Ctrl + C
Ctrl + V
.
Можно заметить, что в наших действиях менялся только индекс массива, остальное оставалось тем же. Этот индекс можно сделать переменной, которая меняется после выполнения действия. Преобразуем код.
k <- 1
v[k] <- v[k] + 1
k <- 2
v[k] <- v[k] + 1
k <- 3
v[k] <- v[k] + 1
k <- 4
v[k] <- v[k] + 1
k <- 5
v[k] <- v[k] + 1
Этот код выполняет то же, что и предыдущий. Теперь мы явно видим, что мы выполняем одну и ту же операцию v[k] <- v[k] + 1
, но при этом меняем индекс k
.
Для облегчения таких задач и придумали цикл for
. Его конструкция выглядит следующим образом.
Основные моменты:
variable
- название переменной, которая будет менятьсяvector
- массив значений, которые будет принимать переменнаяРазберем цикл for
на нашей задаче.
k
.1:5
– помним, что :
это просто один из способов задать массив, можно было бы и с помощью c(1,2,3,4,5)
v[k] <- v[k] + 1
.## [1] 11 7 3 9 8 5 10 2 7 9 5 3 6 10 3
## [1] 12 8 4 10 9 5 10 2 7 9 5 3 6 10 3
Принцип такой: переменная принимает значение, выполняется тело цикла с этим значением переменной, переменная принимает следующее значение, выполняется тело цикла с новым значением переменной и так продолжается пока переменная не пройдет по всем значениям. Тело цикло может состоять из неограниченного количества действий.
=======## [1] 6 9 11 3 10 4 7 5 3 3 9 10 3 9 1
## [1] 7 10 12 4 11 4 7 5 3 3 9 10 3 9 1
Принцип такой: переменная принимает значение, выполняется тело цикла с этим значением переменной, переменная принимает следующее значение, выполняется тело цикла с новым значением переменной и так продолжается пока переменная не пройдет по всем значениям. Тело цикло может состоять из неограниченного количества действий.
>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2## [1] 1
## [1] ""
## [1] 2
## [1] ""
## [1] 3
## [1] ""
## [1] 4
## [1] ""
## [1] 5
## [1] ""
Цикл for
очень удобен. Например, вам нужно выкачать цены билетов на разные перелеты. Вы же не будете это делать для каждого перелета. Вы создадите какой-то шаблон, после чего используете цикл. О других тонкостях цикла for
будет сказано далее.
Для того чтобы понять, как еще более сложно можно использовать цикл for
, сделаем еще одно лирическое отступление и изучим новую структуру хранения данных: матрицы.
Помимо уже известных нам переменных и массивов, есть и другие структуры хранения данных. Одной из таких структур является матрица. Матрица – это двумерный массив, то есть набор нескольких массивов.
Чтобы создать матрицу нужно использовать функцию matrix
. Она имеет следующие аргументы:
data
- то чем будет заполнена матрица (массив или один объект)nrow
- количество строкncol
- количество столбцовbyrow
- как следует брать элементы из data
и заполнять их (по строкам – тогда пишем в аргумент TRUE
или по столбцам – FALSE
). По умолчанию byrow=FALSE
.## [,1] [,2] [,3] [,4] [,5]
## [1,] 0 0 0 0 0
## [2,] 0 0 0 0 0
## [3,] 0 0 0 0 0
<<<<<<< HEAD
=======
>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 4 7 10 13
## [2,] 2 5 8 11 14
## [3,] 3 6 9 12 15
<<<<<<< HEAD
=======
>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15
Мы с вами уже знакомы с очень полезной функцией length(x)
, которая считает количество элементов в массиве. Давайте попробуем выполнить ее для объекта матрицы.
## [1] 15
Получим также ожидаемый ответ – количество элементов. Однако если в массивах на этом наш интерес заканчивался, то в матрице нам было бы интересно знать не только количество элементов, но и количество строк/столбцов, так как матрица – это двумерный объект. Так как объект двумерный, у него есть так называемая размерность. Размерность – это просто два числа, где первое число – это количество строк в матрице, а второе – количество столбцов. Размерность матрицы можно узнать с помощью функции dim
.
## [1] 3 5
Также можно получать отдельно число количества строк и столбцов. За это отвечают функции nrow
и ncol
.
## [1] 3
## [1] 5
Обращение к матрицам очень похоже на обращение к массивам. Но как мы уже сказали, матрица – объект двумерный. Поэтому чтобы выделить какой-то элемент, нужно написать название матрицы, а потом в квадратных скобках через запятую указать номер строки и номер столбца, на месте которых стоит интересующий нас элемент.
m2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15
m2[1,5] # получим объект, находящийся в 1 строке и 5 столбце
## [1] 5
Также элементы матрицы можно менять.
Можно доставать отдельно весь столбец или всю строку.
Можно менять строку или столбец.
=======## [1] 15
Получим также ожидаемый ответ – количество элементов. Однако если в массивах на этом наш интерес заканчивался, то в матрице нам было бы интересно знать не только количество элементов, но и количество строк/столбцов, так как матрица – это двумерный объект. Так как объект двумерный, у него есть так называемая размерность. Размерность – это просто два числа, где первое число – это количество строк в матрице, а второе – количество столбцов. Размерность матрицы можно узнать с помощью функции dim
.
## [1] 3 5
Также можно получать отдельно число количества строк и столбцов. За это отвечают функции nrow
и ncol
.
## [1] 3
## [1] 5
Обращение к матрицам очень похоже на обращение к массивам. Но как мы уже сказали, матрица – объект двумерный. Поэтому чтобы выделить какой-то элемент, нужно написать название матрицы, а потом в квадратных скобках через запятую указать номер строки и номер столбца, на месте которых стоит интересующий нас элемент.
m2
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15
m2[1,5] # получим объект, находящийся в 1 строке и 5 столбце
## [1] 5
Также элементы матрицы можно менять.
Можно доставать отдельно весь столбец или всю строку.
Можно менять строку или столбец.
>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 1 6 8 14
## [2,] 6 -1 8 9 10
## [3,] 11 0 13 14 15
После того как мы познакомились с матрицами, можно переходить обратно к for
.
Иногда использования одного цикла for
недостаточно для решения какой-либо задачи. Очень часто бывает полезным комбинировать его с другими конструкциями (например, с уже известным нам if
или даже с самим циклов for
). Разберем несколько примеров.
Пример №1: for
+ if
Вернемся к нашему примеру про температуру с прошлого семинара. Предположим теперь, что к нам поступают несколько чисел (в виде массива, например), где каждое число – это температура на каком-то приборе. Тогда нам нужно будет “пробежаться” по всем этим числам и получить сообщение о температуре для каждого прибора.
x <- c(50, 30, 71, 90, 69) # массив из чисел
for (i in x){ # начинаем пробегаться по массиву
if (i >= 70 && i < 80){ # для каждого элемента из массива проверяем на пороговую температуру
print("Температура близится к 80 градусам!")
} else if (i > 80){
print("Температура достигла 80 градусов!!")
} else {
print("Температура в норме")
}
}
Иногда использования одного цикла for
недостаточно для решения какой-либо задачи. Очень часто бывает полезным комбинировать его с другими конструкциями (например, с уже известным нам if
или даже с самим циклов for
). Разберем несколько примеров.
Пример №1: for
+ if
Вернемся к нашему примеру про температуру с прошлого семинара. Предположим теперь, что к нам поступают несколько чисел (в виде массива, например), где каждое число – это температура на каком-то приборе. Тогда нам нужно будет “пробежаться” по всем этим числам и получить сообщение о температуре для каждого прибора.
x <- c(50, 30, 71, 90, 69) # массив из чисел
for (i in x){ # начинаем пробегаться по массиву
if (i >= 70 && i < 80){ # для каждого элемента из массива проверяем на пороговую температуру
print("Температура близится к 80 градусам!")
} else if (i > 80){
print("Температура достигла 80 градусов!!")
} else {
print("Температура в норме")
}
}
## [1] "Температура в норме"
## [1] "Температура в норме"
## [1] "Температура близится к 80 градусам!"
## [1] "Температура достигла 80 градусов!!"
## [1] "Температура в норме"
Пример №2: for
+ for
Вспомним матрицы и представим, что наша задача – это вывести на экран каждый элемент матрицы. Как мы поступим, зная конструкцию for
?
m <- matrix(1:6, nrow = 3, ncol = 2, byrow = T)
for (i in 1:nrow(m)) {
for (j in 1:ncol(m)) {
print(m[i,j])
}
}
m <- matrix(1:6, nrow = 3, ncol = 2, byrow = T)
for (i in 1:nrow(m)) {
for (j in 1:ncol(m)) {
print(m[i,j])
}
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
Видно, что сначала мы пробегаемся по всем строкам в матрице, а потом для каждой строки пробегаемся по всем столбцам. То есть сначала у нас фиксируется значение из первого for
. Затем для этого значения переменная j
меняется в своих пределах, затем переменная i
принимает следующее значение, а переменная j
снова пробегается по всем своим значениям и так далее. Вот так это выглядит с помощью индексирования:
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
while
Ну и напоследок рассмотрим еще одну конструкцию: цикл while
. Этот цикл позволяет совершать операцию пока какое-то условие выполняется.
Например, нам нужно добавлять к нашей переменной единицу, пока эта переменная меньше 5. Тогда с помощью while
это можно сделать так:
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
while
Ну и напоследок рассмотрим еще одну конструкцию: цикл while
. Этот цикл позволяет совершать операцию пока какое-то условие выполняется.
Например, нам нужно добавлять к нашей переменной единицу, пока эта переменная меньше 5. Тогда с помощью while
это можно сделать так:
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
R может сломаться, если вы используете while
неправильно. Если не менять значение переменной a
, то условие будет выполняться “вечно”. R либо зависнет, либо будет принтовать 0 не останавливаясь. В верхнем правом углу консоли появится знак stop. Нажмите на него, чтобы остановить R.
break
и next
На примере цикла while
мы с вами отметили, что иногда циклы могут зацикливаться (тавтология, да). Чтобы этого избежать, можно также использовать оператор break
. Он используется внутри циклов (for
, while
), чтобы остановить итерации в цикле и продолжить код уже за его пределами. Приведем пример в цикле for
.
## [1] 1
## [1] 2
Следующий же оператор next
полезен, когда мы хотим пропустить текущую итерацию цикла, не завершая его.
break
и next
На примере цикла while
мы с вами отметили, что иногда циклы могут зацикливаться (тавтология, да). Чтобы этого избежать, можно также использовать оператор break
. Он используется внутри циклов (for
, while
), чтобы остановить итерации в цикле и продолжить код уже за его пределами. Приведем пример в цикле for
.
## [1] 1
## [1] 2
Следующий же оператор next
полезен, когда мы хотим пропустить текущую итерацию цикла, не завершая его.
## [1] 1
## [1] 2
## [1] 4
## [1] 5