20 Задания

Задания, которые помечены звездочкой (*) можно пропускать: это задания повышенной сложности, в них требуется подумать над решением, а не просто применить выученные инструменты.

20.1 Начало работы в R

  • Разделите 9801 на 9.
## [1] 1089
  • Посчитайте логарифм от 2176782336 по основанию 6.
## [1] 12
  • Теперь натуральный логарифм 10 и умножьте его на 5.
## [1] 11.51293
  • С помощью функции sin() посчитайте \(\sin (\pi), \sin \left(\frac{\pi}{2}\right), \sin \left(\frac{\pi}{6}\right)\).

Значение \(\pi\) - зашитая в R константа (pi).

## [1] 1.224647e-16
## [1] 1
## [1] 0.5

20.2 Создание векторов

  • Создайте вектор из значений 2, 30 и 4000.
## [1]    2   30 4000
  • Создайте вектор от 1 до 20.
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
  • Создайте вектор от 20 до 1.
##  [1] 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1

Функция sum() возвращает сумму элементов вектора на входе. Посчитайте сумму первых 100 натуральных чисел (т.е. всех целых чисел от 1 до 100).

## [1] 5050
  • Создайте вектор от 1 до 20 и снова до 1. Число 20 должно присутствовать только один раз!
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 19 18 17 16 15
## [26] 14 13 12 11 10  9  8  7  6  5  4  3  2  1
  • Создайте вектор значений 5, 4, 3, 2, 2, 3, 4, 5:
## [1] 5 4 3 2 2 3 4 5
  • Создайте вектор 2, 4, 6, … , 18, 20.
##  [1]  2  4  6  8 10 12 14 16 18 20
  • Создайте вектор 0.1, 0.2, 0.3, …, 0.9, 1.
##  [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
  • 2020 год — високосный. Следующий високосный год через 4 года — это будет 2024 год. Составьте календарь всех високосных годов XXI века, начиная с 2020 года.

2100 год относится к XXI веку, а не к XXII.

##  [1] 2020 2024 2028 2032 2036 2040 2044 2048 2052 2056 2060 2064 2068 2072 2076
## [16] 2080 2084 2088 2092 2096 2100
  • Создайте вектор, состоящий из 20 повторений “Хэй!”
##  [1] "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!"
## [11] "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!" "Хэй!"
  • Как я и говорил, многие функции, работающие с одним значением на входе, так же прекрасно работают и с целыми векторами. Попробуйте посчитать квадратный корень чисел от 1 до 10 с помощью функции sqrt() и сохраните результат в векторе roots.
##  [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
##  [9] 3.000000 3.162278
  • Давайте убедимся, что это действительно квадратные корни. Для этого возведите все значения вектора roots в квадрат!
##  [1]  1  2  3  4  5  6  7  8  9 10
  • Если все верно, то того же самого можно добиться поэлементным умножением вектора roots на себя.
##  [1]  1  2  3  4  5  6  7  8  9 10
  • *Создайте вектор из одной единицы, двух двоек, трех троек, …. , девяти девяток.
##  [1] 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 9 9
## [39] 9 9 9 9 9 9 9

20.3 Приведение типов

  • Сделайте вектор vec1, в котором соедините 3, а также значения "Мой" и "вектор".
## [1] "3"      "Мой"    "вектор"
  • Попробуйте вычесть TRUE из 10.
## [1] 9
  • Соедините значение 10 и TRUE в вектор vec2.
## [1] 10  1
  • Соедините вектор vec2 и значение "r":
## [1] "10" "1"  "r"
  • Соедините значения 10, TRUE, "r" в вектор.
## [1] "10"   "TRUE" "r"

20.4 Векторизация

  • Создайте вектор p, состоящий из значений 4, 5, 6, 7, и вектор q, состоящий из 0, 1, 2, 3.
## [1] 4 5 6 7
## [1] 0 1 2 3
  • Посчитайте поэлементную сумму векторов p и q:
## [1]  4  6  8 10
  • Посчитайте поэлементную разницу p и q:
## [1] 4 4 4 4
  • Поделите каждый элемент вектора p на соответствующий ему элемент вектора q:

О, да, Вам нужно делить на 0!

## [1]      Inf 5.000000 3.000000 2.333333
  • Возведите каждый элемент вектора p в степень соответствующего ему элемента вектора q:
## [1]   1   5  36 343
  • Умножьте каждое значение вектора p на 10.
## [1] 40 50 60 70
  • Создайте вектор квадратов чисел от 1 до 10:
##  [1]   1   4   9  16  25  36  49  64  81 100
  • Создайте вектор 0, 2, 0, 4, … , 18, 0, 20.
##  [1]  0  2  0  4  0  6  0  8  0 10  0 12  0 14  0 16  0 18  0 20
  • Создайте вектор 1, 0, 3, 0, 5, …, 17, 0, 19, 0.
##  [1]  1  0  3  0  5  0  7  0  9  0 11  0 13  0 15  0 17  0 19  0
  • *Создайте вектор, в котором будут содержаться первые 20 степеней двойки.
##  [1]       2       4       8      16      32      64     128     256     512
## [10]    1024    2048    4096    8192   16384   32768   65536  131072  262144
## [19]  524288 1048576
  • *Создайте вектор из чисел 1, 10, 100, 1000, 10000:
## [1]     1    10   100  1000 10000
  • *Посчитать сумму последовательности \(\frac{1}{1 \cdot 2}+\frac{1}{2 \cdot 3}+\frac{1}{3 \cdot 4}+\ldots+\frac{1}{50 \cdot 51}\).
## [1] 0.9803922
  • *Посчитать сумму последовательности \(\frac{1}{2^{0}}+\frac{1}{2^{1}}+\frac{1}{2^{2}}+\frac{1}{2^{3}}+\ldots \frac{1}{2^{20}}\).
## [1] 1.999999
  • *Посчитать сумму последовательности \(1+\frac{4}{3}+\frac{7}{9}+\frac{10}{27}+\frac{13}{81}+\ldots+\frac{28}{19683}\).
## [1] 3.749174
  • *Сколько чисел из последовательности \(1+\frac{4}{3}+\frac{7}{9}+\frac{10}{27}+\frac{13}{81}+\ldots+\frac{28}{19683}\) больше чем 0.5?
## [1] 3

20.5 Индексирование векторов

  • Создайте вектор troiki со значениями 3, 6, 9, …, 24, 27.
## [1]  3  6  9 12 15 18 21 24 27
  • Извлеките 2, 5 и 7 значения вектора troiki.
## [1]  6 15 21
  • Извлеките предпоследнее значение вектора troiki.
## [1] 24
  • Извлеките все значения вектора troiki кроме предпоследнего:
## [1]  3  6  9 12 15 18 21 27

Создайте вектор vec3:

vec3 <- c(3, 5, 2, 1, 8, 4, 9, 10, 3, 15, 1, 11)
  • Найдите второй элемент вектора vec3.
## [1] 5
  • Верните второй и пятый элемент вектора vec3.
## [1] 5 8
  • Попробуйте извлечь сотое значение вектора vec3:
## [1] NA
  • Верните все элементы вектора vec3 кроме второго элемента.
##  [1]  3  2  1  8  4  9 10  3 15  1 11
  • Верните все элементы вектора vec3 кроме второго и пятого элемента.
##  [1]  3  2  1  4  9 10  3 15  1 11
  • Найдите последний элемент вектора vec3.
## [1] 11
  • Верните все значения вектора vec3 кроме первого и последнего.
##  [1]  5  2  1  8  4  9 10  3 15  1
  • Найдите все значения вектора vec3, которые больше 4.
## [1]  5  8  9 10 15 11
  • Найдите все значения вектора vec3, которые больше 4, но меньше 10.

Если хотите сделать это в одну строчку, то вам помогут логические операторы!

## [1] 5 8 9
  • Найдите все значения вектора vec3, которые меньше 4 или больше 10.
## [1]  3  2  1  3 15  1 11
  • Возведите в квадрат каждое значение вектора vec3.
##  [1]   9  25   4   1  64  16  81 100   9 225   1 121
  • *Возведите в квадрат каждое значение вектора на нечетной позиции и извлеките корень из каждого значения на четной позиции вектора vec3.

Извлечение корня - это то же самое, что и возведение в степень 0.5.

##  [1]  9.000000  2.236068  4.000000  1.000000 64.000000  2.000000 81.000000
##  [8]  3.162278  9.000000  3.872983  1.000000  3.316625
  • Создайте вектор 2, 4, 6, … , 18, 20 как минимум 2 новыми способами.

Знаю, это задание может показаться бессмысленным, но это очень базовая операция, с помощью которой можно, например, разделить данные на две части. Чем больше способов Вы знаете, тем лучше!

##  [1]  2  4  6  8 10 12 14 16 18 20

20.6 Работа с пропущенными значениями

  • Создайте вектор vec4 со значениями 300, 15, 8, 2, 0, 1, 110:
vec4 <- c(300, 15, 8, 20, 0, 1, 110)
vec4
## [1] 300  15   8  20   0   1 110
  • Замените все значения vec4, которые больше 20 на NA.

  • Проверьте полученный вектор vec4:

## [1] NA 15  8 20  0  1 NA
  • Посчитайте сумму vec4 с помощью функции sum(). Ответ NA не считается!
## [1] 44

20.7 Матрицы

  • Создайте матрицу 4х4, состоящую из единиц. Назовите ее M1.
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    1
## [2,]    1    1    1    1
## [3,]    1    1    1    1
## [4,]    1    1    1    1
  • Поменяйте все некрайние значения матрицы M1 (то есть значения на позициях [2,2], [2,3], [3,2] и [3,3]) на число 2.
##      [,1] [,2] [,3] [,4]
## [1,]    1    1    1    1
## [2,]    1    2    2    1
## [3,]    1    2    2    1
## [4,]    1    1    1    1
  • Выделите второй и третий столбик из матрицы M1.
##      [,1] [,2]
## [1,]    1    1
## [2,]    2    2
## [3,]    2    2
## [4,]    1    1
  • Сравните (==) вторую колонку и вторую строчку матрицы M1.
## [1] TRUE TRUE TRUE TRUE
  • *Создайте таблицу умножения (9х9) в виде матрицы. Сохраните ее в переменную mult_tab.
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
##  [1,]    1    2    3    4    5    6    7    8    9
##  [2,]    2    4    6    8   10   12   14   16   18
##  [3,]    3    6    9   12   15   18   21   24   27
##  [4,]    4    8   12   16   20   24   28   32   36
##  [5,]    5   10   15   20   25   30   35   40   45
##  [6,]    6   12   18   24   30   36   42   48   54
##  [7,]    7   14   21   28   35   42   49   56   63
##  [8,]    8   16   24   32   40   48   56   64   72
##  [9,]    9   18   27   36   45   54   63   72   81
  • *Из матрицы mult_tab выделите подматрицу, включающую в себя только строчки с 6 по 8 и столбцы с 3 по 7.
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   18   24   30   36   42
## [2,]   21   28   35   42   49
## [3,]   24   32   40   48   56
  • *Создайте матрицу с логическими значениями, где TRUE, если в этом месте в таблице умножения (mult_tab) двузначное число и FALSE, если однозначное.

Матрица - это почти вектор. К нему можно обращаться с единственным индексом.

##        [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]
##  [1,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [2,] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [3,] FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [4,] FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [5,] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [6,] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [7,] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [8,] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [9,] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
  • *Создайте матрицу mult_tab2, в которой все значения tab меньше 10 заменены на 0.
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
##  [1,]    0    0    0    0    0    0    0    0    0
##  [2,]    0    0    0    0   10   12   14   16   18
##  [3,]    0    0    0   12   15   18   21   24   27
##  [4,]    0    0   12   16   20   24   28   32   36
##  [5,]    0   10   15   20   25   30   35   40   45
##  [6,]    0   12   18   24   30   36   42   48   54
##  [7,]    0   14   21   28   35   42   49   56   63
##  [8,]    0   16   24   32   40   48   56   64   72
##  [9,]    0   18   27   36   45   54   63   72   81

20.8 Списки

Дан список list1:

list1 = list(numbers = 1:5, letters = letters, logic = TRUE)
list1
## $numbers
## [1] 1 2 3 4 5
## 
## $letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## 
## $logic
## [1] TRUE
  • Найдите первый элемент списка list1. Ответ должен быть списком длиной один.
## $numbers
## [1] 1 2 3 4 5
  • Теперь найдите содержание первого элемента списка list1 двумя разными способами. Ответ должен быть вектором.
## [1] 1 2 3 4 5
## [1] 1 2 3 4 5
  • Теперь возьмите первый элемент содержания первого элемента списка list1. Ответ должен быть вектором.
## [1] 1
  • Создайте список list2, содержащий в себе два списка list1. Один из них будет иметь имя pupa, а другой — lupa.
## $pupa
## $pupa$numbers
## [1] 1 2 3 4 5
## 
## $pupa$letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## 
## $pupa$logic
## [1] TRUE
## 
## 
## $lupa
## $lupa$numbers
## [1] 1 2 3 4 5
## 
## $lupa$letters
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## 
## $lupa$logic
## [1] TRUE
  • *Извлеките первый элемент списка list2, из него — второй полэлемент, а из него — третье значение.
## [1] "c"

20.9 Датафрейм

  • Запустите команду data(mtcars) чтобы загрузить встроенный датафрейм с информацией про автомобили. Каждая строчка датафрейма - модель автомобиля, каждая колонка - отдельная характеристика. Подробнее см. ?mtcars.
data(mtcars)
mtcars
  • Изучите структуру датафрейма mtcars с помощью функции str().
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
  • Найдите значение третьей строчки четвертого столбца датафрейма mtcars.
## [1] 93
  • Извлеките первые шесть строчек и первые шесть столбцов датафрейма mtcars.
  • Извлеките колонку wt датафрейма mtcars - массу автомобиля в тысячах фунтов.
##  [1] 2.620 2.875 2.320 3.215 3.440 3.460 3.570 3.190 3.150 3.440 3.440 4.070
## [13] 3.730 3.780 5.250 5.424 5.345 2.200 1.615 1.835 2.465 3.520 3.435 3.840
## [25] 3.845 1.935 2.140 1.513 3.170 2.770 3.570 2.780
  • Извлеките колонки из mtcars в следующем порядке: hp, mpg, cyl.
  • Посчитайте количество автомобилей с 4 цилиндрами (cyl) в датафрейме mtcars.
## [1] 11
  • Посчитайте долю автомобилей с 4 цилиндрами (cyl) в датафрейме mtcars.
## [1] 0.34375
  • Найдите все автомобили мощностью не менее 100 лошадиных сил (hp) в датафрейме mtcars.
  • Найдите все автомобили мощностью не менее 100 лошадиных сил (hp) и 4 цилиндрами (cyl) в датафрейме mtcars.
  • Посчитайте максимальную массу (wt) автомобиля в выборке, воспользовавшись функцией max():
## [1] 5.424
  • Посчитайте минимальную массу (wt) автомобиля в выборке, воспользовавшись функцией min():
## [1] 1.513
  • Найдите строчку датафрейма mtcars с самым легким автомобилем.
  • Извлеките строчки датафрейма mtcars с автомобилями, масса которых ниже средней массы.
  • Масса автомобиля указана в тысячах фунтов. Создайте колонку wt_kg с массой автомобиля в килограммах. Результат округлите до целых значений с помощью функции round().

1 фунт = 0.45359237 кг.

20.10 Условные конструкции

  • Создайте вектор vec5:
vec5 <- c(5, 20, 30, 0, 2, 9)
  • Создайте новый строковый вектор, где на месте чисел больше 10 в vec5 будет стоять “большое число,” а на месте остальных чисел — “маленькое число.”
## [1] "маленькое число" "большое число"   "большое число"   "маленькое число"
## [5] "маленькое число" "маленькое число"
  • Загрузите файл heroes_information.csv в переменную heroes.
heroes <- read.csv("data/heroes_information.csv", 
                   stringsAsFactors = FALSE,
                   na.strings = c("-", "-99"))
  • Создайте новою колонку hair в heroes, в которой будет значение "Bold" для тех супергероев, у которых в колонке Hair.color стоит "No Hair", и значение "Hairy" во всех остальных случаях.
  • Создайте новою колонку tall в heroes, в которой будет значение "tall" для тех супергероев, у которых в колонке Height стоит число больше 190, значение "short" для тех супергероев, у которых в колонке Height стоит число меньше 170, и значение "middle" во всех остальных случаях.

20.11 Создание функций

  • Создайте функцию plus_one(), которая принимает число и возвращает это же число + 1.

  • Проверьте функцию plus_one() на числе 41.

plus_one(41)
## [1] 42
  • Создайте функцию circle_area(), которая вычисляет площадь круга по радиусу согласно формуле \(\pi r^2\).

  • Посчитайте площадь круга с радиусом 5.

## [1] 78.53982
  • Создайте функцию cels2fahr(), которая будет превращать градусы по Цельсию в градусы по Фаренгейту.

  • Проверьте на значениях -100, -40 и 0, что функция cels2fahr() работает корректно.

cels2fahr(c(-100, -40, 0))
## [1] -148  -40   32
  • Напишите функцию highlight(), которая принимает на входе строковый вектор, а возвращает тот же вектор, но дополненный значением "***" в начале и конце вектора. Лучше всего это рассмотреть на примере:
highlight(c("Я", "Бэтмен!"))
## [1] "***"     "Я"       "Бэтмен!" "***"
  • Теперь сделайте функцию highlight более гибкой. Добавьте в нее параметр wrapper =, который по умолчанию равен "***". Значение параметра wrapper = и будет вставлено в начало и конец вектора.

  • Проверьте написанную функцию на векторе c("Я", "Бэтмен!").

highlight(c("Я", "Бэтмен!")) 
## [1] "***"     "Я"       "Бэтмен!" "***"
highlight(c("Я", "Бэтмен!"), wrapper = "__") 
## [1] "__"      "Я"       "Бэтмен!" "__"
  • Создайте функцию na_n(), которая будет возвращать количество NA в векторе.

  • Проверьте функцию na_n() на векторе:

na_n(c(NA, 3:5, NA, 2, NA))
## [1] 3
  • Напишите функцию factors(), которая будет возвращать все делители числа в виде числового вектора.

Здесь может понадобиться оператор для получения остатка от деления: %%.

  • Проверьте функцию factors() на простых и сложных числах:
factors(3)
## [1] 1 3
factors(161)
## [1]   1   7  23 161
factors(1984)
##  [1]    1    2    4    8   16   31   32   62   64  124  248  496  992 1984
  • *Напишите функцию is_prime(), которая проверяет, является ли число простым.

Здесь может пригодиться функция any() - она возвращает TRUE, если в векторе есть хотя бы один TRUE.

  • Проверьте какие года были для нас простыми, а какие нет:
is_prime(2017)
## [1] TRUE
is_prime(2019)
## [1] FALSE
2019/3 #2019 делится на 3 без остатка
## [1] 673
is_prime(2020)
## [1] FALSE
is_prime(2021)
## [1] FALSE
  • *Создайте функцию monotonic(), которая возвращает TRUE, если значения в векторе не убывают (то есть каждое следующее - больше или равно предыдущему) или не возврастают.

Полезная функция для этого — diff() — возвращает разницу соседних значений.

monotonic(1:7)
## [1] TRUE
monotonic(c(1:5,5:1))
## [1] FALSE
monotonic(6:-1)
## [1] TRUE
monotonic(c(1:5, rep(5, 10), 5:10))
## [1] TRUE

Бинарные операторы типа + или %in% тоже представляют собой функции. Более того, мы можем создавать свои бинарные операторы! В этом нет особой сложности — нужно все так же создавать функцию (для двух переменных), главное окружать их % и название обрамлять обратными штрихами `. Например, можно сделать свой бинарный оператор %notin%, который будет выдавать TRUE, если значения слева нет в векторе справа:

`%notin%` <- function(x, y) ! (x %in% y)
1:10 %notin% c(1, 4, 5)
##  [1] FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
  • *Создайте бинарный оператор %without%, который будет возвращать все значения вектора слева без значений вектора справа.
c("а", "и", "б", "сидели", "на", "трубе") %without% c("а", "б")
## [1] "и"      "сидели" "на"     "трубе"
  • *Создайте бинарный оператор %between%, который будет возвращать TRUE, если значение в векторе слева накходится в диапазоне значений вектора справа:
1:10 %between% c(1, 4, 5)
##  [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE

20.12 Проверка на адекватность

  • Создайте функцию trim(), которая будет возвращать вектор без первого и последнего значения (вне зависимости от типа данных).

  • Проверьте, что функция trim() работает корректно:

trim(1:7)
## [1] 2 3 4 5 6
trim(letters)
##  [1] "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
## [20] "u" "v" "w" "x" "y"
  • Теперь добавьте в функцию trim() параметр n = со значением по умолчанию 1. Этот параметр будет обозначать сколько значений нужно отрезать слева и справа от вектора.

  • Проверьте полученную функцию:

trim(letters)
##  [1] "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t"
## [20] "u" "v" "w" "x" "y"
trim(letters, n = 2)
##  [1] "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u"
## [20] "v" "w" "x"
  • Сделайте так, чтобы функция trim() работала корректно с n = 0, т.е. функция возвращала бы исходный вектор без изменений.
trim(letters, n = 0)
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
  • *Теперь добавьте проверку на адекватность входных данных: функция trim() должна выдавать ошибку, если n = меньше нуля или если n = слишком большой и отрезает все значения вектора:

  • *Проверьте полученную функцию trim():

trim(1:6, 3)
## Error in trim(1:6, 3): n слишком большой!
trim(1:6, -1)
## Error in trim(1:6, -1): n не может быть меньше нуля!

20.13 Семейство функций apply()

  • Создайте матрицу M2:
M2 <- matrix(c(20:11, 11:20), nrow = 5)
M2
##      [,1] [,2] [,3] [,4]
## [1,]   20   15   11   16
## [2,]   19   14   12   17
## [3,]   18   13   13   18
## [4,]   17   12   14   19
## [5,]   16   11   15   20
  • Посчитайте максимальное значение матрицы M2 по каждой строчке.
## [1] 20 19 18 19 20
  • Посчитайте максимальное значение матрицы M2 по каждому столбцу.
## [1] 20 15 15 20
  • Посчитайте среднее значение матрицы M2 по каждой строке.
## [1] 15.5 15.5 15.5 15.5 15.5
  • Посчитайте среднее значение матрицы M2 по каждому столбцу.
## [1] 18 13 13 18
  • Создайте список list3:
list3 <- list(
  a = 1:5,
  b = 0:20,
  c = 4:24,
  d = 6:3,
  e = 6:25
  )
  • Найдите максимальное значение каждого вектора списка list3.
##  a  b  c  d  e 
##  5 20 24  6 25
  • Посчитайте сумму каждого вектора списка list3.
##   a   b   c   d   e 
##  15 210 294  18 310
  • Посчитайте длину каждого вектора списка list3.
##  a  b  c  d  e 
##  5 21 21  4 20
  • Напишите функцию max_item(), которая будет принимать на входе список, а возвращать - (первый) самый длинный его элемент.

Для этого вам может понадобиться функция which.max(), которая возвращает индекс максимального значения (первого, если их несколько).

  • Проверьте функцию max_item() на списке list3.
max_item(list3)
##  [1]  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
  • Теперь мы сделаем сложный список list4:
list4 <- list(1:3, 3:40, list3)
  • Посчитайте длину каждого вектора в списке, в т.ч. для списка внутри. Результат должен быть списком с такой же структорой, как и изначальный список list4.

Для этого может понадобиться функция rapply(): recursive lapply

## [[1]]
## [1] 3
## 
## [[2]]
## [1] 38
## 
## [[3]]
## [[3]]$a
## [1] 5
## 
## [[3]]$b
## [1] 21
## 
## [[3]]$c
## [1] 21
## 
## [[3]]$d
## [1] 4
## 
## [[3]]$e
## [1] 20
  • *Загрузите набор данных heroes и посчитайте, сколько NA в каждом из столбцов.

Для этого удобно использовать ранее написанную функцию na_n().

##          X       name     Gender  Eye.color       Race Hair.color     Height 
##          0          0         29        172        304        172        217 
##  Publisher Skin.color  Alignment     Weight       hair       tall 
##          0        662          7        239        172        217
  • *Используя ранее написанную функцию is_prime(), напишите функцию prime_numbers(), которая будет возвращать все простые числа до выбранного числа.
prime_numbers(200)
##  [1]   3   5   7  11  13  17  19  23  29  31  37  41  43  47  53  59  61  67  71
## [20]  73  79  83  89  97 101 103 107 109 113 127 131 137 139 149 151 157 163 167
## [39] 173 179 181 191 193 197 199

20.14 magrittr::%>%

  • Перепишите следующие выражения, используя %>%:
sqrt(sum(1:10))
## [1] 7.416198
## [1] 7.416198
abs(min(-5:5))
## [1] 5
## [1] 5
c("Корень из", 2, "равен", sqrt(2))
## [1] "Корень из"       "2"               "равен"           "1.4142135623731"
## [1] "Корень из"       "2"               "равен"           "1.4142135623731"

20.15 Выбор столбцов: dplyr::select()

Для выполнения следующих заданий нам понадобятся датасеты heroes и powers, которые можно загрузить, используя следующие команды:

library(tidyverse)
heroes <- read_csv("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/heroes_information.csv",
                   na = c("-", "-99"))
powers <- read_csv("https://raw.githubusercontent.com/Pozdniakov/tidy_stats/master/data/super_hero_powers.csv")
  • Выберете первые 4 столбца в powers.
  • Выберите все столбцы от Reflexes до Empathy в тиббле powers:
  • Выберите все столбцы тиббла powers кроме первого (hero_names):