Funkcje w programowaniu w języku R z przykładem

Co to jest funkcja w R?

A funkcjonowaćw środowisku programistycznym jest zestawem instrukcji. Programista buduje funkcję, której należy unikać powtarzając to samo zadanie lub zmniejszyć złożoność.

Funkcja powinna być

  • napisane w celu wykonania określonego zadania
  • może zawierać argumenty lub nie
  • zawierać ciało
  • może, ale nie musi, zwracać jedną lub więcej wartości.

Ogólne podejście do funkcji polega na użyciu części argumentu jako Wejścia, karmić ciało część i na koniec zwróć wydajność. Składnia funkcji jest następująca:

function (arglist)  {
  #Function body
}

R ważne funkcje wbudowane

W R jest wiele wbudowanych funkcji. R dopasowuje parametry wejściowe do argumentów funkcji, albo według wartości, albo według pozycji, a następnie wykonuje treść funkcji. Argumenty funkcji mogą mieć wartości domyślne: jeśli nie określisz tych argumentów, R przyjmie wartość domyślną.
Note:
Można zobaczyć kod źródłowy funkcji, uruchamiając samą nazwę funkcji w konsoli.

R Ważne wbudowane funkcje

Zobaczymy trzy grupy funkcji w akcji

  • Funkcja ogólna
  • Funkcja matematyczna
  • Funkcja statystyczna

Funkcje ogólne

Znamy już ogólne funkcje takie jak cbind(), rbind(),range(),sort(),order(). Każda z tych funkcji ma określone zadanie, przyjmuje argumenty, aby zwrócić wynik. Poniżej znajdują się ważne funkcje, które należy znać-

funkcja różnicowa().

Jeśli pracujesz nad szereg czasowy, musisz zatrzymać serię, biorąc ich wartości opóźnienia, ZA proces stacjonarny umożliwia stałą średnią, wariancję i autokorelację w czasie. Poprawia to głównie przewidywanie szeregów czasowych. Można to łatwo zrobić za pomocą funkcji diff(). Możemy zbudować losowe dane szeregu czasowego z trendem, a następnie użyć funkcji diff() do unieruchomienia szeregu. Funkcja diff() przyjmuje jeden argument, wektor, i zwraca odpowiednią opóźnioną i iterowaną różnicę.

Note: Często musimy tworzyć losowe dane, ale do nauki i porównań chcemy, aby liczby były identyczne na wszystkich maszynach. Aby mieć pewność, że wszyscy generujemy te same dane, używamy funkcji set.seed() z dowolnymi wartościami 123. Funkcja set.seed() jest generowana poprzez proces generatora liczb pseudolosowych, który sprawia, że ​​wszystkie nowoczesne komputery mają tę samą sekwencję liczb. Jeśli nie użyjemy funkcji set.seed(), wszyscy będziemy mieli inną sekwencję liczb.

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')

Funkcja różnicowa().

funkcja długość().

W wielu przypadkach chcemy wiedzieć długość wektora do obliczeń lub do użycia w pętli for. Funkcja length() zlicza liczbę wierszy w wektorze x. Poniższe kody importują zbiór danych cars i zwracają liczbę wierszy.

Note: długość() zwraca liczbę elementów wektora. Jeśli funkcja zostanie przekazana do macierzy lub ramki danych, zwracana jest liczba kolumn.

dt <- cars
## number columns
length(dt)

Wyjście:

## [1] 1
## number rows
length(dt[,1])

Wyjście:

## [1] 50

Funkcje matematyczne

R ma tablicę funkcji matematycznych.

OperaTor Opis
abs (x) Przyjmuje wartość bezwzględną x
log(x,podstawa=y) Oblicza logarytm z x o podstawie y; jeśli podstawa nie jest określona, ​​zwraca logarytm naturalny
exp (x) Zwraca wykładnik x
sqrt (x) Zwraca pierwiastek kwadratowy z x
silnia(x) Zwraca silnię 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)

Wyjście:

##  [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)

Wyjście:

##  [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)

Wyjście:

##  [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

Funkcje statystyczne

Standardowa instalacja R zawiera szeroką gamę funkcji statystycznych. W tym samouczku krótko przyjrzymy się najważniejszej funkcji.

Podstawowe funkcje statystyczne

OperaTor Opis
znaczy (x) Średnia x
mediana (x) Mediana x
zmienna(x) Wariancja x
SD(x) Odchylenie standardowe x
skala (x) Wyniki standardowe (wyniki Z) x
kwantyl(x) Kwartyle x
podsumowanie(x) Podsumowanie x: średnia, min, max itp.
speed <- dt$speed
speed
# Mean speed of cars dataset
mean(speed)

Wyjście:

## [1] 15.4
# Median speed of cars dataset
median(speed)

Wyjście:

## [1] 15
# Variance speed of cars dataset
var(speed)

Wyjście:

## [1] 27.95918
# Standard deviation speed of cars dataset
sd(speed)

Wyjście:

## [1] 5.287644
# Standardize vector speed of cars dataset		
head(scale(speed), 5)

Wyjście:

##           [,1]
## [1,] -2.155969
## [2,] -2.155969
## [3,] -1.588609
## [4,] -1.588609
## [5,] -1.399489
# Quantile speed of cars dataset
quantile(speed)

Wyjście:

##   0%  25%  50%  75% 100%
##    4   12   15   19   25
# Summary speed of cars dataset
summary(speed)

Wyjście:

##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
##     4.0    12.0    15.0    15.4    19.0    25.0

Do tego momentu poznaliśmy wiele funkcji wbudowanych w język R.

Note: Uważaj na klasę argumentu, tj. numeryczną, logiczną lub łańcuchową. Na przykład, jeśli chcemy przekazać wartość ciągu, musimy ująć go w cudzysłów: „ABC”.

Zapisz funkcję w R

Czasami musimy napisać własną funkcję, ponieważ musimy wykonać określone zadanie, a nie ma gotowej funkcji. Funkcja zdefiniowana przez użytkownika obejmuje a Nazwa, argumenty oraz ciało.

function.name <- function(arguments) 
{
    computations on the arguments	
    some other code
}		

Note: Dobrą praktyką jest nadawanie funkcji zdefiniowanej przez użytkownika innej nazwy niż funkcji wbudowanej. Pozwala uniknąć zamieszania.

Funkcja z jednym argumentem

W następnym fragmencie definiujemy prostą funkcję kwadratową. Funkcja przyjmuje wartość i zwraca kwadrat wartości.

square_function<- function(n) 
{
  # compute the square of integer `n`
  n^2
}  
# calling the function and passing value 4
square_function(4)

Objaśnienie kodu

  • Funkcja nosi nazwę Square_function; można to nazwać jakkolwiek chcemy.
  • Otrzymuje argument „n”. My nie określono typu zmiennej, aby użytkownik mógł przekazać liczbę całkowitą, wektor lub macierz
  • Funkcja pobiera wartość wejściową „n” i zwraca kwadrat wartości wejściowej. Kiedy skończysz korzystać z tej funkcji, możemy ją usunąć za pomocą funkcji rm().

# po utworzeniu funkcji

rm(square_function)
square_function

Na konsoli pojawia się komunikat o błędzie:Error: nie znaleziono obiektu 'square_function' informujący, że funkcja nie istnieje.

Zakres środowiska

W R środowisko jest kolekcja obiektów, takich jak funkcje, zmienne, ramki danych itp.

R otwiera środowisko za każdym razem, gdy zostanie wyświetlony monit Rstudio.

Dostępne środowisko najwyższego poziomu to globalnego Środowiska, zwany R_GlobalEnv. I mamy lokalne środowisko.

Możemy wyświetlić zawartość bieżącego środowiska.

ls(environment())

Wydajność

## [1] "diff_ts"         "dt"              "speed"           "square_function"
## [5] "ts"              "x"               "x_vector"

Możesz zobaczyć wszystkie zmienne i funkcje utworzone w pliku R_GlobalEnv.

Powyższa lista będzie się różnić w zależności od historycznego kodu, który wykonasz w R Studio.

Zauważ, że n, argument funkcji Square_function to nie w tym globalnym środowisku.

A nowa środowisko jest tworzone dla każdej funkcji. W powyższym przykładzie funkcja Square_function() tworzy nowe środowisko wewnątrz środowiska globalnego.

Aby wyjaśnić różnicę między światowy i lokalne środowisko, przyjrzyjmy się następującemu przykładowi

Funkcje te przyjmują wartość x jako argument i dodają ją do definicji y na zewnątrz i wewnątrz funkcji

Zakres środowiska

Funkcja f zwraca wynik 15. Dzieje się tak, ponieważ y jest zdefiniowane w środowisku globalnym. Lokalnie można używać dowolnej zmiennej zdefiniowanej w środowisku globalnym. Zmienna y podczas wszystkich wywołań funkcji ma wartość 10 i jest dostępna w każdej chwili.

Zobaczmy, co się stanie, jeśli wewnątrz funkcji zdefiniowana zostanie zmienna y.

Musimy usunąć `y` przed uruchomieniem tego kodu za pomocą rm r

Zakres środowiska

Wynik również wynosi 15, gdy wywołujemy f(5), ale zwraca błąd, gdy próbujemy wydrukować wartość y. Zmienna y nie znajduje się w środowisku globalnym.

Na koniec R używa najnowszej definicji zmiennej do przekazania wewnątrz ciała funkcji. Rozważmy następujący przykład:

Zakres środowiska

R ignoruje wartości y zdefiniowane poza funkcją, ponieważ jawnie utworzyliśmy zmienną y wewnątrz treści funkcji.

Funkcja wielu argumentów

Możemy napisać funkcję z więcej niż jednym argumentem. Rozważmy funkcję zwaną „czasami”. Jest to prosta funkcja mnożąca dwie zmienne.

times <- function(x,y) {
  x*y
	}
times(2,4)

Wyjście:

## [1] 8

Kiedy powinniśmy pisać funkcję?

Analitycy danych muszą wykonywać wiele powtarzalnych zadań. W większości przypadków kopiujemy i wklejamy fragmenty kodu w sposób powtarzalny. Na przykład zdecydowanie zaleca się normalizację zmiennej przed uruchomieniem funkcji a uczenie maszynowe algorytm. Formuła normalizująca zmienną to:

Formuła normalizująca zmienną

Wiemy już, jak używać funkcji min() i max() w R. Do tworzenia ramki danych używamy biblioteki tibble. Tibble jest jak dotąd najwygodniejszą funkcją do tworzenia zestawu danych od zera.

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),    
)

Obliczenie funkcji opisanej powyżej zajmiemy się w dwóch krokach. W pierwszym kroku utworzymy zmienną o nazwie c1_norm, która będzie przeskalowaniem c1. W kroku drugim po prostu kopiujemy i wklejamy kod c1_norm i zmieniamy na c2 i c3.

Szczegóły funkcji z kolumną c1:

Nominator: : ramka_danych$c1 -min(ramka_danych$c1))

Mianownik: max(data_frame$c1)-min(data_frame$c1))

Dlatego możemy je podzielić, aby uzyskać znormalizowaną wartość kolumny c1:

(data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1))

Możemy stworzyć c1_norm, c2_norm i 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)

Wyjście:

## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991

To działa. Możemy kopiować i wklejać

data_frame$c1_norm <- (data_frame$c1 -min(data_frame$c1))/(max(data_frame$c1)-min(data_frame$c1))

następnie zmień c1_norm na c2_norm i c1 na c2. Robimy to samo, aby utworzyć 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))

Doskonale przeskalowaliśmy zmienne c1, c2 i c3.

Jednak ta metoda jest podatna na błędy. Moglibyśmy skopiować i zapomnieć zmienić nazwę kolumny po wklejeniu. Dlatego dobrą praktyką jest pisanie funkcji za każdym razem, gdy zachodzi potrzeba wklejenia tego samego kodu więcej niż dwa razy. Możemy zmienić układ kodu w formułę i wywołać go, kiedy tylko zajdzie taka potrzeba. Aby napisać własną funkcję musimy podać:

  • Nazwa: normalizować.
  • liczba argumentów: Potrzebujemy tylko jednego argumentu, czyli kolumny, której używamy w naszych obliczeniach.
  • Ciało: to po prostu formuła, którą chcemy zwrócić.

Będziemy krok po kroku tworzyć funkcję normalize.

Krok 1) Tworzymy nominator, który jest . W R możemy przechowywać mianownik w zmiennej takiej jak ta:

nominator <- x-min(x)

Krok 2) Obliczamy mianownik: . Możemy powtórzyć pomysł z kroku 1 i zapisać obliczenia w zmiennej:

denominator <- max(x)-min(x)

Krok 3) Dokonujemy podziału między mianownikiem i mianownikiem.

normalize <- nominator/denominator

Krok 4) Aby zwrócić wartość do funkcji wywołującej, musimy przekazać wartość normalize wewnątrz funkcji return() w celu uzyskania wyniku funkcji.

return(normalize)

Krok 5) Jesteśmy gotowi do użycia funkcji zawijając wszystko wewnątrz nawiasu.

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)
}

Przetestujmy naszą funkcję ze zmienną c1:

normalize(data_frame$c1)

Działa idealnie. Stworzyliśmy naszą pierwszą funkcję.

Funkcje są bardziej wszechstronnym sposobem wykonywania powtarzalnych zadań. Możemy użyć formuły normalizującej w różnych kolumnach, jak poniżej:

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)

Chociaż przykład jest prosty, możemy wywnioskować moc formuły. Powyższy kod jest łatwiejszy do odczytania i pozwala uniknąć błędów przy wklejaniu kodów.

Funkcje z warunkiem

Czasami musimy dołączyć warunki do funkcji, aby kod mógł zwracać różne wyniki.

W zadaniach uczenia maszynowego musimy podzielić zbiór danych pomiędzy zestaw pociągowy i zestaw testowy. Zestaw pociągów pozwala algorytmowi uczyć się na podstawie danych. Aby przetestować wydajność naszego modelu, możemy użyć zestawu testowego do zwrócenia miary wydajności. R nie ma funkcji umożliwiającej utworzenie dwóch zbiorów danych. Możemy napisać własną funkcję, która to zrobi. Nasza funkcja przyjmuje dwa argumenty i nosi nazwę split_data(). Pomysł jest prosty, mnożymy długość zbioru danych (tj. liczbę obserwacji) przez 0.8. Na przykład, jeśli chcemy podzielić zbiór danych 80/20, a nasz zbiór danych zawiera 100 wierszy, to nasza funkcja pomnoży 0.8*100 = 80. 80 wierszy zostanie wybranych jako dane szkoleniowe.

Wykorzystamy zbiór danych o jakości powietrza do przetestowania naszej funkcji zdefiniowanej przez użytkownika. Zbiór danych o jakości powietrza składa się ze 153 wierszy. Możemy to zobaczyć za pomocą poniższego kodu:

nrow(airquality)

Wyjście:

## [1] 153

Postępujemy następująco:

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

Nasza funkcja ma dwa argumenty. Argument train jest parametrem boolowskim. Jeśli jest ustawiony na TRUE, nasza funkcja tworzy zestaw danych train, w przeciwnym razie tworzy zestaw danych testowych.

Możemy postępować tak samo, jak w przypadku funkcji normalise(). Piszemy kod tak, jakby był to tylko kod jednorazowy, a następnie owijamy wszystko wraz z warunkiem w treść, aby utworzyć funkcję.

Krok 1:

Musimy obliczyć długość zbioru danych. Robi się to za pomocą funkcji nrow(). Nrow zwraca całkowitą liczbę wierszy w zbiorze danych. Nazywamy zmienną długość.

length<- nrow(airquality)
length

Wyjście:

## [1] 153

Krok 2:

Mnożymy długość przez 0.8. Zwróci liczbę wierszy do wybrania. Powinno być 153*0.8 = 122.4

total_row <- length*0.8
total_row

Wyjście:

## [1] 122.4

Chcemy wybrać 122 wiersze spośród 153 wierszy w zestawie danych o jakości powietrza. Tworzymy listę zawierającą wartości od 1 do total_row. Wynik przechowujemy w zmiennej zwanej split

split <- 1:total_row
split[1:5]

Wyjście:

## [1] 1 2 3 4 5

split wybiera pierwsze 122 wiersze ze zbioru danych. Na przykład widzimy, że nasza zmienna split gromadzi wartości 1, 2, 3, 4, 5 i tak dalej. Wartości te będą indeksem, gdy wybierzemy wiersze do zwrócenia.

Krok 3:

Musimy wybrać wiersze w zestawie danych o jakości powietrza na podstawie wartości przechowywanych w zmiennej podziału. Odbywa się to w następujący sposób:

train_df <- airquality[split, ] 
head(train_df)

Wyjście:

##[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

Krok 4:

Możemy utworzyć testowy zbiór danych, korzystając z pozostałych wierszy, 123:153. Odbywa się to za pomocą – przed podziałem.

test_df <- airquality[-split, ] 
head(test_df)

Wyjście:

##[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

Krok 5:

Możemy stworzyć warunek wewnątrz treści funkcji. Pamiętaj, że mamy ciąg argumentów, który jest domyślnie ustawioną wartością logiczną na TRUE, aby zwrócić zestaw. Aby utworzyć warunek, używamy składni if:

  if (train ==TRUE){ 
    train_df <- airquality[split, ] 
      return(train)		
  } else {
    test_df <- airquality[-split, ] 
      return(test)		
  }

To wszystko, możemy napisać funkcję. Musimy tylko zmienić jakość powietrza na df, ponieważ chcemy wypróbować naszą funkcję na dowolnej ramka danych, nie tylko jakość powietrza:

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)		
  }
}

Wypróbujmy naszą funkcję na zbiorze danych o jakości powietrza. powinniśmy mieć jeden zestaw składający się ze 122 rzędów i zestaw testowy z 31 rzędami.

train <- split_data(airquality, train = TRUE)
dim(train)

Wyjście:

## [1] 122   6
test <- split_data(airquality, train = FALSE)
dim(test)

Wyjście:

## [1] 31  6