Функції в програмуванні R із прикладом
Що таке функція в R?
A функція, в середовищі програмування, це набір інструкцій. Програміст створює функцію, якої слід уникати повторення те саме завдання, або зменшити складність.
Функція повинна бути
- написаний для виконання визначених завдань
- може включати або не включати аргументи
- містять тіло
- може повертати або не повертати одне чи декілька значень.
Загальний підхід до функції полягає у використанні частини аргументу як витрати, годувати тіло частину і, нарешті, повернути an вихід. Синтаксис функції такий:
function (arglist) { #Function body }
R важливі вбудовані функції
У R є багато вбудованих функцій. R зіставляє ваші вхідні параметри з аргументами функції за значенням або позицією, а потім виконує тіло функції. Аргументи функції можуть мати значення за замовчуванням: якщо ви не вкажете ці аргументи, R прийме значення за замовчуванням.
Примітка::
Можна побачити вихідний код функції, запустивши назву самої функції в консолі.
Ми побачимо три групи функцій у дії
- Загальна функція
- Математична функція
- Статистична функція
Загальні функції
Ми вже знайомі із загальними функціями, такими як функції cbind(), rbind(),range(),sort(),order(). Кожна з цих функцій має конкретне завдання, приймає аргументи для повернення результату. Нижче наведено важливі функції, які потрібно знати:
функція diff().
Якщо працювати над часовий ряд, вам потрібно стаціонарні ряди, взявши їх значення лагів. стаціонарний процес допускає постійне середнє значення, дисперсію та автокореляцію з часом. Це в основному покращує прогнозування часових рядів. Це можна легко зробити за допомогою функції diff(). Ми можемо побудувати випадковий часовий ряд даних із тенденцією, а потім використовувати функцію diff() для стаціонарного ряду. Функція diff() приймає один аргумент, вектор, і повертає відповідну лаговану та ітеровану різницю.
Примітка:: Нам часто доводиться створювати випадкові дані, але для вивчення та порівняння ми хочемо, щоб числа були ідентичними на різних машинах. Щоб гарантувати, що всі ми генеруємо однакові дані, ми використовуємо функцію set.seed() із довільними значеннями 123. Функція set.seed() генерується за допомогою процесу генератора псевдовипадкових чисел, завдяки якому всі сучасні комп’ютери мають однакову послідовність чисел. Якщо ми не використовуємо функцію set.seed(), усі ми матимемо різну послідовність чисел.
set.seed(123) ## Create the data x = rnorm(1000) ts <- cumsum(x) ## Stationary the serie diff_ts <- diff(ts) par(mfrow=c(1,2)) ## Plot the series plot(ts, type='l') plot(diff(ts), type='l')
функція length().
У багатьох випадках ми хочемо знати вектора для обчислень або для використання в циклі for. Функція length() підраховує кількість рядків у векторі x. Наступні коди імпортують набір даних автомобілів і повертають кількість рядків.
Примітка:: length() повертає кількість елементів у векторі. Якщо функція передається в матрицю або кадр даних, повертається кількість стовпців.
dt <- cars ## number columns length(dt)
вихід:
## [1] 1
## number rows length(dt[,1])
вихід:
## [1] 50
Математичні функції
R має масив математичних функцій.
Operaтор | Опис |
---|---|
абс (х) | Приймає абсолютне значення x |
log(x,основа=y) | Бере логарифм x з основою y; якщо база не вказана, повертає натуральний логарифм |
exp(x) | Повертає експоненцію x |
sqrt (x) | Повертає квадратний корінь з x |
факториал(x) | Повертає факториал x (x!) |
# sequence of number from 44 to 55 both including incremented by 1 x_vector <- seq(45,55, by = 1) #logarithm log(x_vector)
вихід:
## [1] 3.806662 3.828641 3.850148 3.871201 3.891820 3.912023 3.931826 ## [8] 3.951244 3.970292 3.988984 4.007333
#exponential exp(x_vector)
#squared root sqrt(x_vector)
вихід:
## [1] 6.708204 6.782330 6.855655 6.928203 7.000000 7.071068 7.141428 ## [8] 7.211103 7.280110 7.348469 7.416198
#factorial factorial(x_vector)
вихід:
## [1] 1.196222e+56 5.502622e+57 2.586232e+59 1.241392e+61 6.082819e+62 ## [6] 3.041409e+64 1.551119e+66 8.065818e+67 4.274883e+69 2.308437e+71 ## [11] 1.269640e+73
Статистичні функції
Стандартна інсталяція R містить широкий спектр статистичних функцій. У цьому посібнику ми коротко розглянемо найважливішу функцію.
Основні статистичні функції
Operaтор | Опис |
---|---|
середнє (x) | Середнє значення x |
медіана (x) | Медіана x |
змінна (x) | Дисперсія х |
sd(x) | Стандартне відхилення x |
масштаб (x) | Стандартні оцінки (z-показники) x |
квантиль (x) | Квартилі х |
підсумок (x) | Підсумок x: середнє, мінімальне, максимальне тощо. |
speed <- dt$speed speed # Mean speed of cars dataset mean(speed)
вихід:
## [1] 15.4
# Median speed of cars dataset median(speed)
вихід:
## [1] 15
# Variance speed of cars dataset var(speed)
вихід:
## [1] 27.95918
# Standard deviation speed of cars dataset sd(speed)
вихід:
## [1] 5.287644
# Standardize vector speed of cars dataset head(scale(speed), 5)
вихід:
## [,1] ## [1,] -2.155969 ## [2,] -2.155969 ## [3,] -1.588609 ## [4,] -1.588609 ## [5,] -1.399489
# Quantile speed of cars dataset quantile(speed)
вихід:
## 0% 25% 50% 75% 100% ## 4 12 15 19 25
# Summary speed of cars dataset summary(speed)
вихід:
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 4.0 12.0 15.0 15.4 19.0 25.0
До цього моменту ми вивчили багато вбудованих функцій R.
Примітка:: Будьте обережні з класом аргументу, тобто числовим, логічним або рядковим. Наприклад, якщо нам потрібно передати рядкове значення, нам потрібно взяти рядок у лапки: «ABC».
Напишіть функцію в R
У деяких випадках нам потрібно написати власну функцію, тому що ми повинні виконати певне завдання, а готової функції не існує. Визначена користувачем функція передбачає a ім'я, аргументація і тіло.
function.name <- function(arguments) { computations on the arguments some other code }
Примітка:: Хорошою практикою є назвати визначену користувачем функцію, відмінну від вбудованої функції. Це дозволяє уникнути плутанини.
Функція з одним аргументом
У наступному фрагменті ми визначаємо просту квадратичну функцію. Функція приймає значення та повертає квадрат цього значення.
square_function<- function(n) { # compute the square of integer `n` n^2 } # calling the function and passing value 4 square_function(4)
Пояснення коду
- Функція називається square_function; це можна називати як завгодно.
- Він отримує аргумент «n». ми не вказав тип змінної, щоб користувач міг передати ціле число, вектор або матрицю
- Функція отримує вхідне значення «n» і повертає квадрат вхідного значення. Коли ви закінчите використовувати функцію, ми можемо видалити її за допомогою функції rm().
# після створення функції
rm(square_function) square_function
На консолі ми можемо побачити повідомлення про помилку :Error: object 'square_function' not found, вказуючи, що функція не існує.
Визначення середовища
У R, навколишнє середовище це збір таких об’єктів, як функції, змінні, кадри даних тощо.
R відкриває середовище кожного разу, коли з’являється запит Rstudio.
Доступним середовищем верхнього рівня є глобальне середовище, називається R_GlobalEnv. І ми маємо місцеве середовище.
Ми можемо перерахувати вміст поточного середовища.
ls(environment())
Вихід
## [1] "diff_ts" "dt" "speed" "square_function" ## [5] "ts" "x" "x_vector"
Ви можете побачити всі змінні та функції, створені в R_GlobalEnv.
Наведений вище список буде відрізнятися для вас залежно від історичного коду, який ви виконуєте в R Studio.
Зауважте, що n, аргумент функції square_function не в цьому глобальному середовищі.
A new середовище створюється для кожної функції. У наведеному вище прикладі функція square_function() створює нове середовище всередині глобального середовища.
Щоб з'ясувати різницю між в цілому та місцеве середовище, вивчимо наступний приклад
Ця функція приймає значення x як аргумент і додає його до визначення y поза та всередині функції
Функція f повертає результат 15. Це тому, що y визначено в глобальному середовищі. Будь-яку змінну, визначену в глобальному середовищі, можна використовувати локально. Змінна y має значення 10 під час усіх викликів функцій і доступна в будь-який час.
Давайте подивимося, що станеться, якщо змінну y визначити всередині функції.
Нам потрібно відкинути `y` перед тим, як запустити цей код за допомогою rm r
Вихід також дорівнює 15, коли ми викликаємо f(5), але повертає помилку, коли ми намагаємося надрукувати значення y. Змінна y не знаходиться в глобальному середовищі.
Нарешті, R використовує останнє визначення змінної для передачі всередину тіла функції. Розглянемо такий приклад:
R ігнорує значення y, визначені поза функцією, оскільки ми явно створили змінну ay всередині тіла функції.
Функція кількох аргументів
Ми можемо написати функцію з більш ніж одним аргументом. Розглянемо функцію під назвою «times». Це проста функція множення двох змінних.
times <- function(x,y) { x*y } times(2,4)
вихід:
## [1] 8
Коли ми повинні написати функцію?
Фахівцям з даних потрібно виконувати багато повторюваних завдань. У більшості випадків ми копіюємо та вставляємо фрагменти коду повторно. Наприклад, настійно рекомендується нормалізувати змінну перед запуском a навчання за допомогою машини алгоритм. Формула нормалізації змінної така:
Ми вже знаємо, як використовувати функції min() і max() у R. Ми використовуємо бібліотеку tibble для створення кадру даних. Tibble поки що найзручніша функція для створення набору даних з нуля.
library(tibble) # Create a data frame data_frame <- tibble( c1 = rnorm(50, 5, 1.5), c2 = rnorm(50, 5, 1.5), c3 = rnorm(50, 5, 1.5), )
Ми виконаємо два кроки, щоб обчислити функцію, описану вище. На першому кроці ми створимо змінну під назвою c1_norm, яка є змінним масштабом c1. На другому кроці ми просто копіюємо та вставляємо код c1_norm і змінюємо його за допомогою c2 і c3.
Деталі функції зі стовпцем c1:
Номінатор: : data_frame$c1 -min(data_frame$c1))
Знаменник: max(data_frame$c1)-min(data_frame$c1))
Тому ми можемо розділити їх, щоб отримати нормалізоване значення стовпця c1:
(data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1))
Ми можемо створити c1_norm, c2_norm і c3_norm:
Create c1_norm: rescaling of c1 data_frame$c1_norm <- (data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1)) # show the first five values head(data_frame$c1_norm, 5)
вихід:
## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991
Це працює. Ми можемо копіювати та вставляти
data_frame$c1_norm <- (data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1))
потім змініть c1_norm на c2_norm і c1 на c2. Ми робимо те саме, щоб створити c3_norm
data_frame$c2_norm <- (data_frame$c2 - min(data_frame$c2))/(max(data_frame$c2)-min(data_frame$c2)) data_frame$c3_norm <- (data_frame$c3 - min(data_frame$c3))/(max(data_frame$c3)-min(data_frame$c3))
Ми ідеально перемасштабували змінні c1, c2 і c3.
Однак цей метод схильний до помилок. Ми могли скопіювати та забути змінити назву стовпця після вставлення. Тому гарною практикою є написання функції кожного разу, коли вам потрібно вставити той самий код більше двох разів. Ми можемо перебудувати код у формулу та викликати її, коли це буде потрібно. Щоб написати власну функцію, нам потрібно дати:
- Назва: нормалізувати.
- кількість аргументів: нам потрібен лише один аргумент, який є стовпцем, який ми використовуємо в наших обчисленнях.
- Тіло: це просто формула, яку ми хочемо повернути.
Ми будемо крок за кроком створювати функцію normalize.
Крок 1) Ми створюємо номінатор, який . У R ми можемо зберегти номінатор у такій змінній:
nominator <- x-min(x)
Крок 2) Ми обчислюємо знаменник: . Ми можемо відтворити ідею кроку 1 і зберегти обчислення в змінній:
denominator <- max(x)-min(x)
Крок 3) Виконуємо ділення між від’ємником і від’ємником.
normalize <- nominator/denominator
Крок 4) Щоб повернути значення виклику функції, нам потрібно передати normalize у return(), щоб отримати результат функції.
return(normalize)
Крок 5) Ми готові використовувати функцію, загорнувши все в дужку.
normalize <- function(x){ # step 1: create the nominator nominator <- x-min(x) # step 2: create the denominator denominator <- max(x)-min(x) # step 3: divide nominator by denominator normalize <- nominator/denominator # return the value return(normalize) }
Давайте перевіримо нашу функцію зі змінною c1:
normalize(data_frame$c1)
Працює ідеально. Ми створили нашу першу функцію.
Функції є більш комплексним способом виконання повторюваного завдання. Ми можемо використовувати формулу нормалізації для різних стовпців, як показано нижче:
data_frame$c1_norm_function <- normalize (data_frame$c1) data_frame$c2_norm_function <- normalize (data_frame$c2) data_frame$c3_norm_function <- normalize (data_frame$c3)
Незважаючи на те, що приклад простий, ми можемо зробити висновок про силу формули. Наведений вище код легше читати і особливо уникнути помилок під час вставлення кодів.
Функції з умовою
Іноді нам потрібно включити умови у функцію, щоб дозволити коду повертати різні результати.
У завданнях машинного навчання нам потрібно розділити набір даних між набором поїздів і набором тестів. Набір поїздів дозволяє алгоритму навчатися з даних. Щоб перевірити продуктивність нашої моделі, ми можемо використати тестовий набір для повернення показника продуктивності. R не має функції для створення двох наборів даних. Ми можемо написати власну функцію для цього. Наша функція приймає два аргументи і називається split_data(). Ідея проста: ми множимо довжину набору даних (тобто кількість спостережень) на 0.8. Наприклад, якщо ми хочемо розділити набір даних 80/20, а наш набір даних містить 100 рядків, тоді наша функція помножить 0.8*100 = 80. 80 рядків буде вибрано, щоб стати нашими навчальними даними.
Ми використаємо набір даних про якість повітря, щоб перевірити нашу функцію, визначену користувачем. Набір даних про якість повітря містить 153 рядки. Ми можемо побачити це за допомогою коду нижче:
nrow(airquality)
вихід:
## [1] 153
Ми будемо діяти наступним чином:
split_data <- function(df, train = TRUE) Arguments: -df: Define the dataset -train: Specify if the function returns the train set or test set. By default, set to TRUE
Наша функція має два аргументи. Поїзд аргументів є булевим параметром. Якщо встановлено значення TRUE, наша функція створює набір даних потягу, інакше вона створює тестовий набір даних.
Ми можемо продовжити так само, як і з функцією normalise(). Ми пишемо код так, ніби це лише одноразовий код, а потім загортаємо все з умовою в тіло, щоб створити функцію.
Крок 1:
Нам потрібно обчислити довжину набору даних. Це робиться за допомогою функції nrow(). Nrow повертає загальну кількість рядків у наборі даних. Ми називаємо змінну довжину.
length<- nrow(airquality) length
вихід:
## [1] 153
Крок 2:
Довжину множимо на 0.8. Він поверне кількість рядків для вибору. Має бути 153*0.8 = 122.4
total_row <- length*0.8 total_row
вихід:
## [1] 122.4
Ми хочемо вибрати 122 рядки серед 153 рядків у наборі даних якості повітря. Ми створюємо список, що містить значення від 1 до total_row. Ми зберігаємо результат у змінній під назвою split
split <- 1:total_row split[1:5]
вихід:
## [1] 1 2 3 4 5
split вибирає перші 122 рядки з набору даних. Наприклад, ми бачимо, що наша змінна split збирає значення 1, 2, 3, 4, 5 і так далі. Ці значення будуть індексом, коли ми будемо вибирати рядки для повернення.
Крок 3:
Нам потрібно вибрати рядки в наборі даних про якість повітря на основі значень, збережених у змінній розділення. Це робиться так:
train_df <- airquality[split, ] head(train_df)
вихід:
##[1] Ozone Solar.R Wind Temp Month Day ##[2] 51 13 137 10.3 76 6 20 ##[3] 15 18 65 13.2 58 5 15 ##[4] 64 32 236 9.2 81 7 3 ##[5] 27 NA NA 8.0 57 5 27 ##[6] 58 NA 47 10.3 73 6 27 ##[7] 44 23 148 8.0 82 6 13
Крок 4:
Ми можемо створити тестовий набір даних, використовуючи решту рядків, 123:153. Це робиться за допомогою – перед розділенням.
test_df <- airquality[-split, ] head(test_df)
вихід:
##[1] Ozone Solar.R Wind Temp Month Day ##[2] 123 85 188 6.3 94 8 31 ##[3] 124 96 167 6.9 91 9 1 ##[4] 125 78 197 5.1 92 9 2 ##[5] 126 73 183 2.8 93 9 3 ##[6] 127 91 189 4.6 93 9 4 ##[7] 128 47 95 7.4 87 9 5
Крок 5:
Ми можемо створити умову всередині тіла функції. Пам’ятайте, що у нас є набір аргументів, який є логічним значенням TRUE за замовчуванням для повернення набору набору. Щоб створити умову, ми використовуємо синтаксис if:
if (train ==TRUE){ train_df <- airquality[split, ] return(train) } else { test_df <- airquality[-split, ] return(test) }
Ось і все, ми можемо написати функцію. Нам потрібно лише змінити якість повітря на df, тому що ми хочемо спробувати нашу функцію на будь-який кадр даних, не тільки якість повітря:
split_data <- function(df, train = TRUE){ length<- nrow(df) total_row <- length *0.8 split <- 1:total_row if (train ==TRUE){ train_df <- df[split, ] return(train_df) } else { test_df <- df[-split, ] return(test_df) } }
Давайте спробуємо нашу функцію на наборі даних про якість повітря. у нас повинен бути один набір поїздів із 122 рядками та тестовий набір із 31 рядком.
train <- split_data(airquality, train = TRUE) dim(train)
вихід:
## [1] 122 6
test <- split_data(airquality, train = FALSE) dim(test)
вихід:
## [1] 31 6