и его применение в биоинформатике
Лекция 4
Анастасия Жарикова
27 сентября 2024
Time Series:
Start = 1912
End = 1971
Frequency = 1
[1] 49.9 52.3 49.4 51.1 49.4 47.9 49.8 50.9 49.3 51.9 50.8 49.6 49.3 50.6 48.4
[16] 50.7 50.9 50.6 51.5 52.8 51.8 51.1 49.8 50.2 50.4 51.6 51.8 50.9 48.8 51.7
[31] 51.0 50.6 51.7 51.5 52.1 51.3 51.0 54.0 51.4 52.7 53.1 54.6 52.0 52.0 50.9
[46] 52.6 50.2 52.6 51.6 51.9 50.5 50.9 51.7 51.4 51.7 50.8 51.9 51.8 51.9 53.0
Time Series:
Start = 1912
End = 1971
Frequency = 1
[1] 9.944444 11.277778 9.666667 10.611111 9.666667 8.833333 9.888889
[8] 10.500000 9.611111 11.055556 10.444444 9.777778 9.611111 10.333333
[15] 9.111111 10.388889 10.500000 10.333333 10.833333 11.555556 11.000000
[22] 10.611111 9.888889 10.111111 10.222222 10.888889 11.000000 10.500000
[29] 9.333333 10.944444 10.555556 10.333333 10.944444 10.833333 11.166667
[36] 10.722222 10.555556 12.222222 10.777778 11.500000 11.722222 12.555556
[43] 11.111111 11.111111 10.500000 11.444444 10.111111 11.444444 10.888889
[50] 11.055556 10.277778 10.500000 10.944444 10.777778 10.944444 10.444444
[57] 11.055556 11.000000 11.055556 11.666667
Нужно придумать:
список параметров, которые функция принимает на вход. Например, function(x, y, z)
.
сам код, выполняющий работу, который вы записываете в тело функции внутри {...}
.
return()
return(...)
.Логическое выражение condition
должно возвращать либо TRUE, либо FALSE.
Не путайте else if () {...}
с ifelse()
.
Через параметры на вход функции передаются данные или какие-то детали. Обычно данные передаются первому параметру. В таком случае эту функцию будет легко использовать с конвейером (%>%
или |>
).
Для параметров можно задать значение по умолчанию:
Идеи для названий параметров:
x, y, z
- вектора,w
- вектор весов,df
- датафрейм,i, j
- индексы (строки и столбцы),n
- длина или число строк,p
- число столбцов.В каком случае нужно остановиться.
if() + stop()
Чтобы функция возвращала несколько объектов, нужно эти объекты возвращать в виде списка.
x
внутри функции (в ее среде) и вне функции (в глобальной среде) существуют независимо.
Изнутри функции можно переписать глобальную переменную с помощью оператора <<-
.
Если R не нашел переменную в среде функции, то он будет искать ее в глобальной среде.
library(tidyverse)
summary6 <- function(df, var) {
summarize(
df,
min = min(var, na.rm = TRUE),
mean = mean(var, na.rm = TRUE),
sd = sd(var, na.rm = TRUE),
median = median(var, na.rm = TRUE),
iqr = IQR(var, na.rm = TRUE),
max = max(var, na.rm = TRUE),
.groups = "drop")
}
summary6(mtcars, var = mpg)
Error in `summarize()`:
ℹ In argument: `min = min(var, na.rm = TRUE)`.
Caused by error in `FUN()`:
! only defined on a data frame with all numeric-alike variables
{{ ... }}
- embracingsummary6 <- function(df, var) {
summarize(
df,
min = min({{ var }}, na.rm = TRUE),
mean = mean({{ var }}, na.rm = TRUE),
sd = sd({{ var }}, na.rm = TRUE),
median = median({{ var }}, na.rm = TRUE),
iqr = IQR({{ var }}, na.rm = TRUE),
max = max({{ var }}, na.rm = TRUE),
.groups = "drop")
}
summary6(mtcars, var = mpg)
min mean sd median iqr max
1 10.4 20.09062 6.026948 19.2 7.375 33.9
[1] "Hello, Nastya!"
[1] "Hello, Nastya!"
Многие функции в R приспособлены к работе с векторами и итерации по элементам вектора. Благодаря этому нам не нужно лишний раз писать циклы.
Можно использовать функции из семейства apply
:
apply()
lapply()
sapply()
tapply()
Если нужно применить функцию к элементам некоторого вектора или списка, то используйте map
из пакета purrr (входит в tidyverse).
map
map_
map()
всегда возвращает list.map_
:
map_chr()
map_lgl()
map_int()
map_dbl()
map_vec()
.map_
mpg cyl disp hp drat wt qsec vs
"double" "double" "double" "double" "double" "double" "double" "double"
am gear carb
"double" "double" "double"
mpg cyl disp hp drat wt qsec vs am gear carb
TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
mpg cyl disp hp drat wt qsec vs am gear carb
25 3 27 22 22 29 30 2 2 3 6
mtcars
(забыли про n_distinct()
из dplyr) mpg cyl disp hp drat wt qsec vs am gear carb
25 3 27 22 22 29 30 2 2 3 6
mpg cyl disp hp drat wt qsec vs am gear carb
25 3 27 22 22 29 30 2 2 3 6
mpg cyl disp hp drat wt qsec vs am gear carb
25 3 27 22 22 29 30 2 2 3 6
Возьмите встроенный набор данных - msleep
.
map_df
Удобно использовать для чтения нескольких таблиц одного формата в единый датафрейм.
map_dfr
- это map()
+ bind_rows()
map_dfc
- это map()
+ bind_cols()
bind_rows()
и bind_cols()
- аналоги rbind()
и cbind()
из базового Rmap_df
map_df
map()
+ list_cbind()
или map()
+ list_rbind()
map
❤️ спискиlist_flatten()
, list_simplify()
, list_c()
map2
pmap
map2
, а нужен map3
или даже map4
…map2(x, y, f)
- то же, что и pmap(list(x, y), f)
.imap
imap(x, f)
- то же, что и map2(x, seq_along(x), f)
или map2(x, names(x), f)
# x - элемент списка
# idx - это название (индекс) элемента списка
x <- map(1:6, \(x) sample(1000, 10))
imap_chr(x, \(x, idx) paste0("The highest value of ", idx, " is ", max(x)))
[1] "The highest value of 1 is 820" "The highest value of 2 is 896"
[3] "The highest value of 3 is 938" "The highest value of 4 is 987"
[5] "The highest value of 5 is 945" "The highest value of 6 is 942"
Возьмите встроенный набор данных - msleep
.
Посчитайте, сколько пропущенных и уникальных значений содержится в каждом из его столбцов. Запишите результаты в датафрейм.
walk
Объедиение происходит по одному или нескольким столбцам с “ключами”.
inner_join()
- сохранить только строчки с общими “ключами”full_join()
- сохранить все строчки из обеих таблицleft_join()
- сохранить все строчки из “первой” таблицыright_join()
- сохранить все строчки из “второй” таблицыreduce
reduce()
берет на вход вектор длины n и возвращает вектор длины 1, применяя функцию к элементам вектора попарно.reduce2()
Если нужно, например, объединить несколько датафреймов, но использовать разные переменные, по которым делать объединение.
safely()
возвращает список из двух элементов:
result
нужный результат или NULL если была ошибка,error
error object или NULL, если ошибки не было.possibly()
позволяет использовать default value, если возникает ошибка.
quietly()
выдает result, output, messages и warnings.
safely()
🏠safely()
как наречие, а функцию, к которой оно применяется, как глаголList of 2
$ result: num 2.3
$ error : NULL
List of 2
$ result: NULL
$ error :List of 2
..$ message: chr "нечисловой аргумент для математической функции"
..$ call : language .Primitive("log")(x, base)
..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
safely()
🏠safely()
удобно использовать вместе с map
List of 3
$ :List of 2
..$ result: num 0
..$ error : NULL
$ :List of 2
..$ result: num 2.3
..$ error : NULL
$ :List of 2
..$ result: NULL
..$ error :List of 2
.. ..$ message: chr "нечисловой аргумент для математической функции"
.. ..$ call : language .Primitive("log")(x, base)
.. ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
safely()
🏠Можно отделить результаты от ошибок:
List of 2
$ result:List of 3
..$ : num 0
..$ : num 2.3
..$ : NULL
$ error :List of 3
..$ : NULL
..$ : NULL
..$ :List of 2
.. ..$ message: chr "нечисловой аргумент для математической функции"
.. ..$ call : language .Primitive("log")(x, base)
.. ..- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
map
🏠map
стал более подробным: указывается индекс элемента на котором все сломалось.possibly()
🏠Позволяет использовать default value, если возникает ошибка.
map
, но с возможностью параллелизации процессовКартинки, иллюстрирующие принцип работы функций из purrr, взяты из ‘Advanced R’ by Hadley Wickham.