Как работать с функциями в R: от использования чужих, до создания своих!

R функцииФункции - это ключевой класс объектов в языке R. Они используются почти на каждом этапе анализа данных, начиная от загрузки таблицы в R и показа описательной статистики, заканчивая функциями для решения узконаправленных задач. Особое место занимают функции "собственного производства": без них сложно обойтись, но их отнюдь не сложно создать. Именно о том, что такое функции, как их использовать и написать самим, я расскажу в этой статье!

Для чего нужны функции в R?

При анализе данных код R записывают в виде скрипта для того, чтобы в последующем можно было легко продолжить работу с ним, либо предоставить возможность воспроизвести Ваш анализ данных другому человеку. Таким образом, скриптовой программой (или скриптом) называется последовательность команд, записанная в текстовом формате. В идеале скрипт должен быть компактным и понятным для другого человека. Для того, чтобы уменьшить количество строк кода, сделать код более читабельным и удобным для редактирования используют функции.

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

Структура R функции
Сначала следует написать имя функции, затем знак присвоения и слово function, которое создает объект класса функция. В скобках мы указываем аргументы, а тело функции находится внутри фигурных скобок. Важно отметить, что для использования функции требуется ввести только имя функции и ее аргументы:

вызов функции в R
Таким образом массивный скрипт с большим количеством повторяющегося кода при помощи функций становится более компактным и понятным для пользователя. Также не забывайте комментировать код, трактовка которого неочевидна, чтобы Вы или другой человек могли понять алгоритм и замысел Вашего анализа.

Использование существующих функций в R

К счастью существует множество готовых функций в R. Так например, mean(), summary(), read.table(), lm() являются базовыми функциями, которыми можно пользоваться без применения сторонних пакетов. Чтобы узнать какие именно аргументы требуется ввести для использования функции введите в консоль знак вопроса и имя функции, например: ?read.table. На открывшейся странице в разделах Usage и Arguments будет перечень аргументов для использования данной функции. Как правило, критически важные аргументы для работы функции находятся в начале списка. Аргументы, которые не будут заполнены примут значения по умолчанию:

read.table("D:/Folder/mytable.txt", sep = "\t", header = T)

Так как официальный архив R пакетов (CRAN) насчитывает более 11 тысяч R пакетов, то количество доступных функций для анализа данных стремительно приближается к 1 млн!!! Как же нам проводить поиск нужной функции во всех этих пакетах? Для этого существует сайт rdocumentation.org: удобный сервис поиска функций и пакетов по искомому слову или сочетанию слов. Следует заметить, что базовая версия R, которая была загружена на Ваш компьютер, состоит из 30 встроенных пакетов. Остальные следует загружать и подключать самостоятельно. Следовательно, сначала мы ищем к какому пакету принадлежит функция, устанавливаем этот пакет в библиотеку пакетов на компьютере, загружаем его в R и лишь после этого используем функции загруженного пакета. Не забывайте загружать пакет при повторном запуске R, если снова собираетесь использовать функции этого пакета.

Создание функций: три наглядных примера!

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

Пример 1: сколько будет 2+2×2?

Создадим простейшую функцию, основанную исключительно на арифметических действиях. Например, вычислим знакомый нам с начальной школы пример: сколько будет 2+2*2? Усложним немного: 12+12*12? Ну и в завершении арифметических упражнений 42+42*42? Как Вы могли заметить, все эти примеры основаны на одной и той же формуле: a+a*a. Создание функции в R будет идеальным решением для подобного рода задач.

school <- function(a){
  b = a+a*a
  print(b)
  }
school(2)
school(12)
school(22)

Результат вычислений функции отобразится на экране консоли, т.к. для вывода информации мы использовали базовую функцию print() внутри нашей функции. Когда же нам требуется сохранить результат в виде отдельного объекта (переменной), следует воспользоваться функцией return(), что мы сделаем в следующем примере.

Пример 2: от горшка два вершка

В детстве мы все читали русские народные сказки. Меня, например, всегда интересовало что значит фраза "от горшка два вершка", а точнее сколько это в сантиметрах. Думаю, пришло время получить ответ: создадим конвертер вершков в R при помощи новой функции convershok().

Один вершок равен 4.445 см. Пусть программа выводит на экран предложение от том, что столько вершков равняется столько-то сантиметров, используя базовую функцию для объединения текстовых и числовых объектов paste(). Также мы хотим, чтобы полученное значение сохранялись как отдельный объект, для чего в конце функции добавим return(vershok).

convershok <- function(n){
  vershok <- n * 4.445
  print(paste(n, "vershok", "=", vershok, "cm"))
  return(vershok)
  }
x <- convershok(2)

Отлично, мы получили заветное сообщение и сохранили 8.89 (см), как объект x. Вот только о каком именно горшке идет речь в поговорке не сказано, поэтому измерьте высоту первого попавшегося горшка, добавьте это значение к переменной x и напишите в комментариях, сколько у Вас получилось;-)

Пример 3: ноутбук в кредит, сколько придется переплатить?

Допустим, у студента сломался ноутбук. На данный момент у него нет свободных денег на покупку нового, и он решил взять его в кредит. В банке ему предложили кредит на сумму 30.000 рублей с процентной ставкой 35% годовых и возможностью преждевременного погашения. Рассчитаем сколько денег нужно выплатить за ноутбук при погашении кредита через месяц, три месяца и год.

Для расчетов я использую формулу для вычисления суммы процентов, начисленных за пользование кредитом в течение n месяцев.

sp = p * (t + 1) / 24, где:

sp - сумма процента
p - годовая процентная ставка
t - срок кредита (месяцев).

Реализуем эту формулу в R, после чего добавим к цене ноутбука (n) высчитанный суммарный процент (sp), помноженный на цену ноутбука товара (n):

result <- function(n, p, t){
  sp <- p*(t + 1)/24
  total <- n + n*sp/100
  print(paste("sp =", round(sp, 2), "%; ", "total price =", total, "rubles")) 

result(30000, 35, 1)
result(30000, 35, 3)
result(30000, 35, 12)

Как Вы видите, 35% годовых отнють не означает, что студент будет платить за кредит 35% от текущей стоимости ноутбука: в реальности за год он переплатит на 19%. Другой интересный вывод в том, что кредитный процент на один месяц гораздо выше, чем усредненный месячный процент на три месяца и тем более на год. То есть брать кредиты на долгий срок "выгодно" :-)

А главное, наш студент может использовать эту же функцию для своих будущих расчетов, если решит брать кредит в другом банке с другой процентной ставкой или выбрать ноутбук в другой ценовой категории. Для этого ему лишь надо изменить значения аргументов в функции.

Заключение

На мой взгляд, создание функций - искусство особого рода, где дерзкие, а порой и совершенно нелепые идеи сочетаются с прагматичным подходом к их реализации. Надеюсь, что эта информация была для Вам полезной. В следующий раз я продолжу рассказ о функцияз, где мы сконцентрируемся на работе со структурами if else, for и while. Если у Вас появились вопросы, задавайте их в комментариях, я всегда рад на них ответить!

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *