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






