Функции в 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 има масив от математически функции.
OperaTor | Descriptйон |
---|---|
абс (x) | Взема абсолютната стойност на x |
log(x,основа=y) | Взема логаритъм от x с основа y; ако основата не е посочена, връща натурален логаритъм |
опит (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 стандартната инсталация съдържа широк набор от статистически функции. В този урок ще разгледаме накратко най-важната функция..
Основни статистически функции
OperaTor | Descriptйон |
---|---|
средно (x) | Средно на x |
медиана (x) | Медиана на x |
променлива (x) | Дисперсия на x |
sd(x) | Стандартно отклонение на x |
мащаб (x) | Стандартни резултати (z-резултати) на x |
квантил(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 нов среда се създава за всяка функция. В горния пример функцията square_function() създава нова среда в глобалната среда.
За да се изясни разликата между в световен мащаб намлява местна среда, нека проучим следния пример
Тази функция приема стойност x като аргумент и я добавя към y, дефинирана извън и вътре във функцията
Функцията f връща резултата 15. Това е така, защото y е дефиниран в глобалната среда. Всяка променлива, дефинирана в глобалната среда, може да се използва локално. Променливата y има стойност 10 по време на всички извиквания на функция и е достъпна по всяко време.
Нека да видим какво се случва, ако променливата y е дефинирана във функцията.
Трябва да изпуснем `y`, преди да стартираме този код с помощта на rm r
Резултатът също е 15, когато извикаме f(5), но връща грешка, когато се опитаме да отпечатаме стойността y. Променливата y не е в глобалната среда.
И накрая, R използва най-новата дефиниция на променлива, за да премине в тялото на функция. Нека разгледаме следния пример:
R игнорира y стойностите, дефинирани извън функцията, защото изрично създадохме ay променлива в тялото на функцията.
Функция с множество аргументи
Можем да напишем функция с повече от един аргумент. Помислете за функцията, наречена "времена". Това е проста функция, умножаваща две променливи.
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 реда от набора от данни. Например, можем да видим, че разделянето на нашата променлива събира стойностите 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. Това се прави с помощта на – пред split.
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) }
Това е, можем да напишем функцията. Трябва само да променим airquality на 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