<<<<<<< HEAD ======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2 <<<<<<< HEAD ======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2 Управляющие конструкции: for, while и матрицы <<<<<<< HEAD ======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2

<<<<<<< HEAD

Цикл for

Чтобы понять, зачем нужен цикл for, представьте, что вас попросили увеличить первые 5 значений массива. С текущими знаниями мы бы сделали это следующим образом:

v <- sample(x = 1:10, size = 15, replace = TRUE)
print(v)
##  [1]  9  5  1  7  6  5 10  2  7  9  5  3  6 10  3
v[1] <- v[1] + 1
v[2] <- v[2] + 1
v[3] <- v[3] + 1
v[4] <- v[4] + 1
v[5] <- v[5] + 1
print(v)
##  [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 (variable in vector) {
  # здесь тело цикла
}
=======

Цикл 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.

Можно заметить, что в наших действиях менялся только индекс массива, остальное оставалось тем же. Этот индекс можно сделать переменной, которая меняется после выполнения действия. Преобразуем код.

Этот код выполняет то же, что и предыдущий. Теперь мы явно видим, что мы выполняем одну и ту же операцию v[k] <- v[k] + 1, но при этом меняем индекс k.

Для облегчения таких задач и придумали цикл for. Его конструкция выглядит следующим образом.

>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2

Основные моменты:

  • variable - название переменной, которая будет меняться
  • vector- массив значений, которые будет принимать переменная
  • тело цикла - что будет выполняться на каждой итерации

Разберем цикл for на нашей задаче.

  • Название переменной в ней: k.
  • Массив: 1:5 – помним, что : это просто один из способов задать массив, можно было бы и с помощью c(1,2,3,4,5)
  • Тело цикла: v[k] <- v[k] + 1.
<<<<<<< HEAD
print(v)
##  [1] 11  7  3  9  8  5 10  2  7  9  5  3  6 10  3
for (k in 1:5) {
  v[k] <- v[k] + 1
}
print(v)
##  [1] 12  8  4 10  9  5 10  2  7  9  5  3  6 10  3

Принцип такой: переменная принимает значение, выполняется тело цикла с этим значением переменной, переменная принимает следующее значение, выполняется тело цикла с новым значением переменной и так продолжается пока переменная не пройдет по всем значениям. Тело цикло может состоять из неограниченного количества действий.

for(i in 1:5){
  print(i)
  print('')
}
=======
##  [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, сделаем еще одно лирическое отступление и изучим новую структуру хранения данных: матрицы.

<<<<<<< HEAD
=======
>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2

Матрицы

Помимо уже известных нам переменных и массивов, есть и другие структуры хранения данных. Одной из таких структур является матрица. Матрица – это двумерный массив, то есть набор нескольких массивов.

Чтобы создать матрицу нужно использовать функцию matrix. Она имеет следующие аргументы:

  • data - то чем будет заполнена матрица (массив или один объект)
  • nrow - количество строк
  • ncol - количество столбцов
  • byrow - как следует брать элементы из data и заполнять их (по строкам – тогда пишем в аргумент TRUE или по столбцам – FALSE). По умолчанию byrow=FALSE.
<<<<<<< HEAD
m <- matrix(data = 0, nrow = 3, ncol = 5)
print(m)
======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    0    0    0    0    0
## [2,]    0    0    0    0    0
## [3,]    0    0    0    0    0
<<<<<<< HEAD
m1 <- matrix(data = 1:15, nrow = 3, ncol = 5)
print(m1)
======= >>>>>>> 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
m2 <- matrix(data = 1:15, nrow = 3, ncol = 5, byrow = TRUE)
print(m2)
======= >>>>>>> 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), которая считает количество элементов в массиве. Давайте попробуем выполнить ее для объекта матрицы.

<<<<<<< HEAD
length(m2)
## [1] 15

Получим также ожидаемый ответ – количество элементов. Однако если в массивах на этом наш интерес заканчивался, то в матрице нам было бы интересно знать не только количество элементов, но и количество строк/столбцов, так как матрица – это двумерный объект. Так как объект двумерный, у него есть так называемая размерность. Размерность – это просто два числа, где первое число – это количество строк в матрице, а второе – количество столбцов. Размерность матрицы можно узнать с помощью функции dim.

dim(m2)
## [1] 3 5

Также можно получать отдельно число количества строк и столбцов. За это отвечают функции nrow и ncol.

nrow(m2) 
## [1] 3
ncol(m2)
## [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

Также элементы матрицы можно менять.

m2[1,5] <- 7

Можно доставать отдельно весь столбец или всю строку.

m2[1,] # 1 строка
## [1] 1 2 3 4 7
m2[,2] # 2 столбец
## [1]  2  7 12

Можно менять строку или столбец.

m2[1,] <- m2[1,] * 2
m2[,2] <- c(1, -1, 0)
m2
=======
## [1] 15

Получим также ожидаемый ответ – количество элементов. Однако если в массивах на этом наш интерес заканчивался, то в матрице нам было бы интересно знать не только количество элементов, но и количество строк/столбцов, так как матрица – это двумерный объект. Так как объект двумерный, у него есть так называемая размерность. Размерность – это просто два числа, где первое число – это количество строк в матрице, а второе – количество столбцов. Размерность матрицы можно узнать с помощью функции dim.

## [1] 3 5

Также можно получать отдельно число количества строк и столбцов. За это отвечают функции nrow и ncol.

## [1] 3
## [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.

<<<<<<< HEAD

Комбинирование разных конструкций

Иногда использования одного цикла 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 Вернемся к нашему примеру про температуру с прошлого семинара. Предположим теперь, что к нам поступают несколько чисел (в виде массива, например), где каждое число – это температура на каком-то приборе. Тогда нам нужно будет “пробежаться” по всем этим числам и получить сообщение о температуре для каждого прибора.

>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
## [1] "Температура в норме"
## [1] "Температура в норме"
## [1] "Температура близится к 80 градусам!"
## [1] "Температура достигла 80 градусов!!"
## [1] "Температура в норме"

Пример №2: for + for Вспомним матрицы и представим, что наша задача – это вывести на экран каждый элемент матрицы. Как мы поступим, зная конструкцию for?

<<<<<<< HEAD
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])
  }
}
======= >>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6

Видно, что сначала мы пробегаемся по всем строкам в матрице, а потом для каждой строки пробегаемся по всем столбцам. То есть сначала у нас фиксируется значение из первого for. Затем для этого значения переменная j меняется в своих пределах, затем переменная i принимает следующее значение, а переменная j снова пробегается по всем своим значениям и так далее. Вот так это выглядит с помощью индексирования:

<<<<<<< HEAD
m[1,1]
## [1] 1
m[1,2]
## [1] 2
m[2,1]
## [1] 3
m[2,2]
## [1] 4
m[3,1]
## [1] 5
m[3,2]
## [1] 6

Цикл while

Ну и напоследок рассмотрим еще одну конструкцию: цикл while. Этот цикл позволяет совершать операцию пока какое-то условие выполняется.

Например, нам нужно добавлять к нашей переменной единицу, пока эта переменная меньше 5. Тогда с помощью while это можно сделать так:

a <- 0
while (a < 5) {
  a <- a + 1
  print(a)
}
=======
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6

Цикл while

Ну и напоследок рассмотрим еще одну конструкцию: цикл while. Этот цикл позволяет совершать операцию пока какое-то условие выполняется.

Например, нам нужно добавлять к нашей переменной единицу, пока эта переменная меньше 5. Тогда с помощью while это можно сделать так:

>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5

R может сломаться, если вы используете while неправильно. Если не менять значение переменной a, то условие будет выполняться “вечно”. R либо зависнет, либо будет принтовать 0 не останавливаясь. В верхнем правом углу консоли появится знак stop. Нажмите на него, чтобы остановить R.

<<<<<<< HEAD
# a <- 0
# while (a < 5) {
#   print(a)
# }

break и next

На примере цикла while мы с вами отметили, что иногда циклы могут зацикливаться (тавтология, да). Чтобы этого избежать, можно также использовать оператор break. Он используется внутри циклов (for, while), чтобы остановить итерации в цикле и продолжить код уже за его пределами. Приведем пример в цикле for.

vec <- c(1,2,3,4,5)
for (i in vec){
  if (i == 3){
    break
  }
  print(i)
}
## [1] 1
## [1] 2

Следующий же оператор next полезен, когда мы хотим пропустить текущую итерацию цикла, не завершая его.

vec <- c(1,2,3,4,5)
for( i in vec ){
  if(i == 3){
    next
  }
  print(i)
}
=======

break и next

На примере цикла while мы с вами отметили, что иногда циклы могут зацикливаться (тавтология, да). Чтобы этого избежать, можно также использовать оператор break. Он используется внутри циклов (for, while), чтобы остановить итерации в цикле и продолжить код уже за его пределами. Приведем пример в цикле for.

## [1] 1
## [1] 2

Следующий же оператор next полезен, когда мы хотим пропустить текущую итерацию цикла, не завершая его.

>>>>>>> 0d2a519f0dd42f255611f2ea985fcc1a9e38f6b2
## [1] 1
## [1] 2
## [1] 4
## [1] 5