Funktioner i R-programmering med eksempel

Hvad er en funktion i R?

A funktion, i et programmeringsmiljรธ, er et sรฆt instruktioner. En programmรธr bygger en funktion, der skal undgรฅs at gentage samme opgave, eller reducere kompleksitet.

En funktion skal vรฆre

  • skrevet til at udfรธre bestemte opgaver
  • kan eller kan ikke indeholde argumenter
  • indeholde en krop
  • kan eller kan ikke returnere en eller flere vรฆrdier.

En generel tilgang til en funktion er at bruge argumentdelen som indgange, fodre krop del og til sidst returnere en output. Syntaksen for en funktion er fรธlgende:

function (arglist)  {
  #Function body
}

R vigtige indbyggede funktioner

Der er mange indbyggede funktioner i R. R matcher dine inputparametre med dets funktionsargumenter, enten efter vรฆrdi eller efter position, og udfรธrer derefter funktionskroppen. Funktionsargumenter kan have standardvรฆrdier: Hvis du ikke angiver disse argumenter, vil R tage standardvรฆrdien.
Bemรฆrk:
Det er muligt at se kildekoden til en funktion ved at kรธre navnet pรฅ selve funktionen i konsollen.

R Vigtige indbyggede funktioner

Vi vil se tre grupper af funktioner i aktion

  • Generel funktion
  • Matematik funktion
  • Statistisk funktion

Generelle funktioner

Vi er allerede bekendt med generelle funktioner som cbind(), rbind(),range(),sort(),order()-funktioner. Hver af disse funktioner har en specifik opgave, tager argumenter for at returnere et output. Fรธlgende er vigtige funktioner, man skal kende-

diff() funktion

Hvis du arbejder pรฅ tidsserier, skal du stationรฆre serien ved at tage deres lag vรฆrdier. En stationรฆr proces tillader konstant middelvรฆrdi, varians og autokorrelation over tid. Dette forbedrer primรฆrt forudsigelsen af โ€‹โ€‹en tidsserie. Det kan nemt gรธres med funktionen diff(). Vi kan bygge tilfรฆldige tidsseriedata med en trend og derefter bruge funktionen diff() til at stationรฆre serien. Funktionen diff() accepterer et argument, en vektor, og returnerer passende lagged og itereret forskel.

Bemรฆrk: Vi skal ofte lave tilfรฆldige data, men til lรฆring og sammenligning รธnsker vi, at tallene skal vรฆre identiske pรฅ tvรฆrs af maskiner. For at sikre, at vi alle genererer de samme data, bruger vi set.seed()-funktionen med vilkรฅrlige vรฆrdier pรฅ 123. Set.seed()-funktionen genereres gennem processen med pseudorandom-talgenerator, der fรฅr alle moderne computere til at have den samme sekvens af tal. Hvis vi ikke bruger set.seed()-funktionen, vil vi alle have forskellig rรฆkkefรธlge af tal.

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

Diff() Funktion

length() funktion

I mange tilfรฆlde vil vi gerne vide lรฆngde af en vektor til beregning eller til brug i en for-lรธkke. Funktionen length() tรฆller antallet af rรฆkker i vektor x. Fรธlgende koder importerer bilernes datasรฆt og returnerer antallet af rรฆkker.

Bemรฆrk: length() returnerer antallet af elementer i en vektor. Hvis funktionen overfรธres til en matrix eller en dataramme, returneres antallet af kolonner.

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

Output:

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

Output:

## [1] 50

Matematiske funktioner

R har en rรฆkke matematiske funktioner.

OperaTor Beskrivelse
abs (x) Tager den absolutte vรฆrdi af x
log(x,base=y) Tager logaritmen af โ€‹โ€‹x med grundtallet y; hvis base ikke er angivet, returnerer den naturlige logaritme
exp (x) Returnerer eksponentialet af x
sqrt (x) Returnerer kvadratroden af โ€‹โ€‹x
fakultet (x) Returnerer fakultetet af 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)

Output:

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

Output:

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

Output:

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

Statistiske funktioner

R standardinstallation indeholder en lang rรฆkke statistiske funktioner. I denne vejledning vil vi kort se pรฅ den vigtigste funktion..

Grundlรฆggende statistikfunktioner

OperaTor Beskrivelse
middel(x) Gennemsnit af x
median(x) Medianen af โ€‹โ€‹x
var(x) Varians af x
sd(x) Standardafvigelse af x
skala (x) Standardscore (z-score) af x
kvantil (x) Kvartilerne af x
resumรฉ(x) Sammenfatning af x: middel, min, max osv..
speed <- dt$speed
speed
# Mean speed of cars dataset
mean(speed)

Output:

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

Output:

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

Output:

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

Output:

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

Output:

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

Output:

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

Output:

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

Indtil nu har vi lรฆrt en masse R indbyggede funktioner.

Bemรฆrk: Vรฆr forsigtig med argumentets klasse, dvs. numerisk, boolesk eller streng. For eksempel, hvis vi skal sende en strengvรฆrdi, skal vi omslutte strengen i anfรธrselstegn: "ABC" .

Skrivefunktion i R

I nogle tilfรฆlde er vi nรธdt til at skrive vores egen funktion, fordi vi skal udfรธre en bestemt opgave, og der findes ingen fรฆrdiglavet funktion. En brugerdefineret funktion involverer en navn, argumenter og en krop.

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

Bemรฆrk: En god praksis er at navngive en brugerdefineret funktion anderledes end en indbygget funktion. Det undgรฅr forvirring.

En argumentfunktion

I det nรฆste uddrag definerer vi en simpel kvadratisk funktion. Funktionen accepterer en vรฆrdi og returnerer kvadratet af vรฆrdien.

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

Code Forklaring

  • Funktionen hedder square_function; det kan hedde hvad vi vil.
  • Den modtager et argument "n". Vi specificerede ikke typen af โ€‹โ€‹variabel, sรฅ brugeren kan sende et heltal, en vektor eller en matrix
  • Funktionen tager input "n" og returnerer kvadratet af input. Nรฅr du er fรฆrdig med at bruge funktionen, kan vi fjerne den med rm()-funktionen.

# efter du har oprettet funktionen

rm(square_function)
square_function

Pรฅ konsollen kan vi se en fejlmeddelelse: Fejl: objektet 'square_function' blev ikke fundet, der fortรฆller, at funktionen ikke eksisterer.

Miljรธ Scoping

I R, den miljรธ er en samling af objekter som funktioner, variabler, dataramme osv.

R รฅbner et miljรธ hver gang Rstudio bliver spurgt.

Det tilgรฆngelige miljรธ pรฅ รธverste niveau er globale miljรธ, kaldet R_GlobalEnv. Og vi har lokalt miljรธ.

Vi kan liste indholdet af det aktuelle miljรธ.

ls(environment())

Produktion

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

Du kan se alle variabler og funktioner oprettet i R_GlobalEnv.

Ovenstรฅende liste vil variere for dig baseret pรฅ den historiske kode, du udfรธrer i R Studio.

Bemรฆrk, at n, argumentet for square_function-funktionen er ikke i dette globale miljรธ.

A ny miljรธ er skabt for hver funktion. I ovenstรฅende eksempel skaber funktionen square_function() et nyt miljรธ inde i det globale miljรธ.

For at tydeliggรธre forskellen mellem global og lokalmiljรธ, lad os studere fรธlgende eksempel

Disse funktioner tager en vรฆrdi x som et argument og tilfรธjer den til y definere uden for og inde i funktionen

Miljรธ Scoping

Funktionen f returnerer output 15. Dette skyldes, at y er defineret i det globale miljรธ. Enhver variabel defineret i det globale miljรธ kan bruges lokalt. Variablen y har vรฆrdien 10 under alle funktionskald og er tilgรฆngelig til enhver tid.

Lad os se, hvad der sker, hvis variablen y er defineret inde i funktionen.

Vi er nรธdt til at slippe "y", fรธr vi kรธrer denne kode ved hjรฆlp af rm r

Miljรธ Scoping

Outputtet er ogsรฅ 15, nรฅr vi kalder f(5), men returnerer en fejl, nรฅr vi forsรธger at udskrive vรฆrdien y. Variablen y er ikke i det globale miljรธ.

Endelig bruger R den seneste variabeldefinition til at passere inde i en funktions krop. Lad os overveje fรธlgende eksempel:

Miljรธ Scoping

R ignorerer y-vรฆrdierne defineret uden for funktionen, fordi vi eksplicit oprettede en ay-variabel inde i funktionens krop.

Multi argument funktion

Vi kan skrive en funktion med mere end et argument. Overvej funktionen kaldet "tider". Det er en ligetil funktion, der multiplicerer to variable.

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

Output:

## [1] 8

Hvornรฅr skal vi skrive funktion?

Data scientist skal udfรธre mange gentagne opgaver. Det meste af tiden kopierer og indsรฆtter vi bidder af kode gentagne gange. For eksempel anbefales normalisering af en variabel stรฆrkt, fรธr vi kรธrer en machine learning algoritme. Formlen til at normalisere en variabel er:

Formel til at normalisere en variabel

Vi ved allerede, hvordan man bruger funktionen min() og max() i R. Vi bruger tibble-biblioteket til at oprette datarammen. Tibble er indtil videre den mest bekvemme funktion til at oprette et datasรฆt fra bunden.

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

Vi vil fortsรฆtte i to trin for at beregne funktionen beskrevet ovenfor. I det fรธrste trin vil vi oprette en variabel kaldet c1_norm, som er reskalering af c1. I trin to kopierer og indsรฆtter vi bare koden for c1_norm og รฆndrer med c2 og c3.

Detalje af funktionen med kolonnen c1:

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

Nรฆvner: max(data_frame$c1)-min(data_frame$c1))

Derfor kan vi dividere dem for at fรฅ den normaliserede vรฆrdi af kolonne c1:

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

Vi kan oprette c1_norm, c2_norm og 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)

Output:

## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991

Det virker. Vi kan kopiere og indsรฆtte

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

skift derefter c1_norm til c2_norm og c1 til c2. Vi gรธr det samme for at skabe 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))

Vi omskalerede variablerne c1, c2 og c3 perfekt.

Denne metode er dog tilbรธjelig til at tage fejl. Vi kunne kopiere og glemme at รฆndre kolonnenavnet efter indsรฆttelse. Derfor er en god praksis at skrive en funktion, hver gang du skal indsรฆtte den samme kode mere end to gange. Vi kan omarrangere koden til en formel og kalde den, nรฅr det er nรธdvendigt. For at skrive vores egen funktion skal vi give:

  • Navn: normalisere.
  • antallet af argumenter: Vi behรธver kun et argument, som er den kolonne, vi bruger i vores beregning.
  • Kroppen: dette er simpelthen den formel, vi รธnsker at returnere.

Vi vil fortsรฆtte trin for trin for at oprette funktionen normalisere.

Trin 1) Vi skaber nominator, som er . I R kan vi gemme nominatoren i en variabel som denne:

nominator <- x-min(x)

Trin 2) Vi beregner nรฆvner: . Vi kan replikere ideen fra trin 1 og gemme beregningen i en variabel:

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

Trin 3) Vi udfรธrer opdelingen mellem nรฆvner og nรฆvner.

normalize <- nominator/denominator

Trin 4) For at returnere vรฆrdi til kaldende funktion skal vi sende normalize inde i return() for at fรฅ output fra funktionen.

return(normalize)

Trin 5) Vi er klar til at bruge funktionen ved at wrapping alt inden for parentesen.

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

Lad os teste vores funktion med variablen c1:

normalize(data_frame$c1)

Det fungerer perfekt. Vi lavede vores fรธrste funktion.

Funktioner er en mere omfattende mรฅde at udfรธre en gentagne opgave pรฅ. Vi kan bruge normaliseringsformlen over forskellige kolonner, som nedenfor:

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)

Selvom eksemplet er enkelt, kan vi udlede styrken af โ€‹โ€‹en formel. Ovenstรฅende kode er lettere at lรฆse og undgรฅr isรฆr fejl ved indsรฆttelse af koder.

Fungerer med stand

Nogle gange er vi nรธdt til at inkludere betingelser i en funktion for at tillade koden at returnere forskellige output.

I Machine Learning-opgaver skal vi opdele datasรฆttet mellem et togsรฆt og et testsรฆt. Togsรฆttet gรธr det muligt for algoritmen at lรฆre af dataene. For at teste vores models ydeevne kan vi bruge testsรฆttet til at returnere ydeevnemรฅlet. R har ikke en funktion til at oprette to datasรฆt. Vi kan skrive vores egen funktion til at gรธre det. Vores funktion tager to argumenter og kaldes split_data(). Ideen bag er enkel, vi multiplicerer lรฆngden af โ€‹โ€‹datasรฆttet (dvs. antallet af observationer) med 0.8. For eksempel, hvis vi รธnsker at opdele datasรฆttet 80/20, og vores datasรฆt indeholder 100 rรฆkker, sรฅ vil vores funktion gange 0.8*100 = 80. 80 rรฆkker vil blive udvalgt til at blive vores trรฆningsdata.

Vi vil bruge luftkvalitetsdatasรฆttet til at teste vores brugerdefinerede funktion. Luftkvalitetsdatasรฆttet har 153 rรฆkker. Vi kan se det med koden nedenfor:

nrow(airquality)

Output:

## [1] 153

Vi fortsรฆtter som fรธlger:

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

Vores funktion har to argumenter. Argumenttoget er en boolesk parameter. Hvis den er sat til TRUE, opretter vores funktion togdatasรฆttet, ellers opretter den testdatasรฆttet.

Vi kan fortsรฆtte, som vi gjorde med normalise()-funktionen. Vi skriver koden, som om det kun var engangskode og pakker derefter alt med betingelsen ind i kroppen for at skabe funktionen.

Trin 1:

Vi skal beregne lรฆngden af โ€‹โ€‹datasรฆttet. Dette gรธres med funktionen nrow(). Nrow returnerer det samlede antal rรฆkker i datasรฆttet. Vi kalder den variable lรฆngde.

length<- nrow(airquality)
length

Output:

## [1] 153

Trin 2:

Vi gange lรฆngden med 0.8. Det vil returnere antallet af rรฆkker at vรฆlge. Det skal vรฆre 153*0.8 = 122.4

total_row <- length*0.8
total_row

Output:

## [1] 122.4

Vi รธnsker at vรฆlge 122 rรฆkker blandt de 153 rรฆkker i luftkvalitetsdatasรฆttet. Vi opretter en liste med vรฆrdier fra 1 til total_row. Vi gemmer resultatet i den variabel kaldet split

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

Output:

## [1] 1 2 3 4 5

split vรฆlger de fรธrste 122 rรฆkker fra datasรฆttet. For eksempel kan vi se, at vores variabelopdeling samler vรฆrdierne 1, 2, 3, 4, 5 og sรฅ videre. Disse vรฆrdier vil vรฆre indekset, nรฅr vi vรฆlger de rรฆkker, der skal returneres.

Trin 3:

Vi skal vรฆlge rรฆkkerne i luftkvalitetsdatasรฆttet baseret pรฅ de vรฆrdier, der er gemt i splitvariablen. Dette gรธres sรฅdan:

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

Output:

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

Trin 4:

Vi kan oprette testdatasรฆttet ved at bruge de resterende rรฆkker, 123:153. Dette gรธres ved at bruge โ€“ foran split.

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

Output:

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

Trin 5:

Vi kan skabe tilstanden inde i funktionens krop. Husk, vi har et argumenttog, der er et boolesk sรฆt til TRUE som standard for at returnere togsรฆttet. For at oprette betingelsen bruger vi if-syntaksen:

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

Dette er det, vi kan skrive funktionen. Vi skal kun รฆndre luftkvaliteten til df, fordi vi vil prรธve vores funktion til evt dataramme, ikke kun luftkvalitet:

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

Lad os prรธve vores funktion pรฅ luftkvalitetsdatasรฆttet. vi skulle have et togsรฆt med 122 rรฆkker og et testsรฆt med 31 rรฆkker.

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

Output:

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

Output:

## [1] 31  6

Opsummer dette indlรฆg med: