Funksjoner i R-programmering med eksempel

Hva er en funksjon i R?

A funksjon, i et programmeringsmiljø, er et sett med instruksjoner. En programmerer bygger en funksjon for å unngå gjenta samme oppgave, eller redusere kompleksitet.

En funksjon skal være

  • skrevet for å utføre bestemte oppgaver
  • kan eller kan ikke inkludere argumenter
  • inneholde en kropp
  • kan returnere én eller flere verdier.

En generell tilnærming til en funksjon er å bruke argumentdelen som innganger, mate kroppen del og til slutt returnere en produksjon. Syntaksen til en funksjon er følgende:

function (arglist)  {
  #Function body
}

R viktige innebygde funksjoner

Det er mange innebygde funksjoner i R. R matcher inndataparameterne dine med funksjonsargumentene, enten etter verdi eller etter posisjon, og utfører deretter funksjonskroppen. Funksjonsargumenter kan ha standardverdier: hvis du ikke spesifiserer disse argumentene, vil R ta standardverdien.
Merknader:
Det er mulig å se kildekoden til en funksjon ved å kjøre navnet på selve funksjonen i konsollen.

R Viktige innebygde funksjoner

Vi vil se tre funksjonsgrupper i aksjon

  • Generell funksjon
  • Matematikkfunksjon
  • Statistisk funksjon

Generelle funksjoner

Vi er allerede kjent med generelle funksjoner som cbind(), rbind(),range(),sort(),order()-funksjoner. Hver av disse funksjonene har en spesifikk oppgave, tar argumenter for å returnere en utgang. Følgende er viktige funksjoner man må kjenne til-

diff() funksjon

Hvis du jobber med tidsserier, må du stille serien ved å ta deres lagverdier. A stasjonær prosess tillater konstant gjennomsnitt, varians og autokorrelasjon over tid. Dette forbedrer hovedsakelig prediksjonen av en tidsserie. Det kan enkelt gjøres med funksjonen diff(). Vi kan bygge tilfeldige tidsseriedata med en trend og deretter bruke funksjonen diff() for å stille serien. Funksjonen diff() aksepterer ett argument, en vektor, og returnerer passende lagged og iterert forskjell.

Merknader: Vi trenger ofte å lage tilfeldige data, men for læring og sammenligning ønsker vi at tallene skal være identiske på tvers av maskiner. For å sikre at vi alle genererer de samme dataene, bruker vi set.seed()-funksjonen med vilkårlige verdier på 123. Set.seed()-funksjonen genereres gjennom prosessen med pseudotilfeldig tallgenerator som får alle moderne datamaskiner til å ha samme sekvens av tall. Hvis vi ikke bruker funksjonen set.seed(), vil vi alle ha forskjellig rekkefølge av tall.

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() funksjon

length() funksjon

I mange tilfeller ønsker vi å vite lengde av en vektor for beregning eller som skal brukes i en for-løkke. Lengde()-funksjonen teller antall rader i vektor x. Følgende koder importerer bilens datasett og returnerer antall rader.

Merknader: length() returnerer antall elementer i en vektor. Hvis funksjonen sendes inn i en matrise eller en dataramme, returneres antall kolonner.

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

Utgang:

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

Utgang:

## [1] 50

Matematiske funksjoner

R har en rekke matematiske funksjoner.

Operator Tekniske beskrivelser
abs (x) Tar den absolutte verdien av x
log(x,base=y) Tar logaritmen til x med grunntallet y; hvis base ikke er spesifisert, returnerer den naturlige logaritmen
exp (x) Returnerer eksponentialen til x
sqrt (x) Returnerer kvadratroten av x
faktoriell (x) Returnerer faktoren til 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)

Utgang:

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

Utgang:

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

Utgang:

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

R standard installasjon inneholder et bredt spekter av statistiske funksjoner. I denne opplæringen skal vi kort se på den viktigste funksjonen..

Grunnleggende statistikkfunksjoner

Operator Tekniske beskrivelser
gjennomsnitt (x) Gjennomsnitt av x
median(x) Median av x
var(x) Varians av x
sd(x) Standardavvik på x
skala (x) Standard poengsum (z-poeng) av x
kvantil (x) Kvartilene til x
sammendrag (x) Sammendrag av x: gjennomsnitt, min, maks osv..
speed <- dt$speed
speed
# Mean speed of cars dataset
mean(speed)

Utgang:

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

Utgang:

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

Utgang:

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

Utgang:

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

Utgang:

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

Utgang:

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

Utgang:

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

Frem til dette punktet har vi lært mange R innebygde funksjoner.

Merknader: Vær forsiktig med klassen til argumentet, dvs. numerisk, boolsk eller streng. For eksempel, hvis vi trenger å sende en strengverdi, må vi omslutte strengen i anførselstegn: "ABC" .

Skrivefunksjon i R

I noen tilfeller må vi skrive vår egen funksjon fordi vi må utføre en bestemt oppgave og ingen ferdige funksjoner eksisterer. En brukerdefinert funksjon innebærer en navn, argumenter og en kroppen.

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

Merknader: En god praksis er å navngi en brukerdefinert funksjon som er forskjellig fra en innebygd funksjon. Det unngår forvirring.

En argumentfunksjon

I neste utdrag definerer vi en enkel kvadratisk funksjon. Funksjonen aksepterer en verdi og returnerer kvadratet av verdien.

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

Kode Forklaring

  • Funksjonen heter square_function; det kan kalles hva vi vil.
  • Den mottar et argument "n". Vi spesifiserte ikke typen variabel slik at brukeren kan sende et heltall, en vektor eller en matrise
  • Funksjonen tar input "n" og returnerer kvadratet av input. Når du er ferdig med å bruke funksjonen, kan vi fjerne den med rm()-funksjonen.

# etter at du har opprettet funksjonen

rm(square_function)
square_function

På konsollen kan vi se en feilmelding: Feil: objektet 'square_function' ble ikke funnet som forteller at funksjonen ikke eksisterer.

Miljøavgrensning

I R, den miljø er en samling av objekter som funksjoner, variabler, dataramme, etc.

R åpner et miljø hver gang Rstudio blir spurt.

Det tilgjengelige miljøet på øverste nivå er globalt miljø, kalt R_GlobalEnv. Og vi har lokalmiljø.

Vi kan liste opp innholdet i det nåværende miljøet.

ls(environment())

Produksjon

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

Du kan se alle variablene og funksjonene som er opprettet i R_GlobalEnv.

Listen ovenfor vil variere for deg basert på den historiske koden du kjører i R Studio.

Legg merke til at n, argumentet til square_function-funksjonen er ikke i dette globale miljøet.

A nytt miljøet er opprettet for hver funksjon. I eksemplet ovenfor skaper funksjonen square_function() et nytt miljø inne i det globale miljøet.

For å tydeliggjøre forskjellen mellom global og lokalmiljø, la oss studere følgende eksempel

Disse funksjonene tar en verdi x som et argument og legger den til y definere utenfor og inne i funksjonen

Miljøavgrensning

Funksjonen f returnerer utdata 15. Dette er fordi y er definert i det globale miljøet. Enhver variabel definert i det globale miljøet kan brukes lokalt. Variabelen y har verdien 10 under alle funksjonsanrop og er tilgjengelig når som helst.

La oss se hva som skjer hvis variabelen y er definert inne i funksjonen.

Vi må slippe "y" før vi kjører denne koden med rm r

Miljøavgrensning

Utgangen er også 15 når vi kaller f(5), men returnerer en feil når vi prøver å skrive ut verdien y. Variabelen y er ikke i det globale miljøet.

Til slutt bruker R den nyeste variabeldefinisjonen for å passere inne i kroppen til en funksjon. La oss vurdere følgende eksempel:

Miljøavgrensning

R ignorerer y-verdiene definert utenfor funksjonen fordi vi eksplisitt opprettet en ay-variabel inne i funksjonens kropp.

Multi argument funksjon

Vi kan skrive en funksjon med mer enn ett argument. Tenk på funksjonen kalt "tider". Det er en enkel funksjon som multipliserer to variabler.

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

Utgang:

## [1] 8

Når skal vi skrive funksjon?

Dataforsker må gjøre mange repeterende oppgaver. Mesteparten av tiden kopierer og limer vi inn biter av kode gjentatte ganger. Normalisering av en variabel er for eksempel sterkt anbefalt før vi kjører en maskinlæring algoritme. Formelen for å normalisere en variabel er:

Formel for å normalisere en variabel

Vi vet allerede hvordan vi bruker funksjonene min() og max() i R. Vi bruker tibble-biblioteket til å lage datarammen. Tibble er så langt den mest praktiske funksjonen for å lage et datasett fra bunnen av.

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 fortsette i to trinn for å beregne funksjonen beskrevet ovenfor. I det første trinnet vil vi lage en variabel kalt c1_norm som er reskalering av c1. I trinn to kopierer og limer vi bare inn koden til c1_norm og endrer med c2 og c3.

Detalj av funksjonen med kolonnen c1:

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

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

Derfor kan vi dele dem for å få den normaliserte verdien av kolonne c1:

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

Vi kan lage 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)

Utgang:

## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991

Det fungerer. Vi kan kopiere og lime inn

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

endre deretter c1_norm til c2_norm og c1 til c2. Vi gjør det samme for å lage 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 omskalerte variablene c1, c2 og c3 perfekt.

Imidlertid er denne metoden utsatt for feil. Vi kan kopiere og glemme å endre kolonnenavnet etter innliming. Derfor er en god praksis å skrive en funksjon hver gang du trenger å lime inn samme kode mer enn to ganger. Vi kan omorganisere koden til en formel og kalle den når det er nødvendig. For å skrive vår egen funksjon, må vi gi:

  • Navn: normalisere.
  • antall argumenter: Vi trenger bare ett argument, som er kolonnen vi bruker i vår beregning.
  • Kroppen: dette er rett og slett formelen vi ønsker å returnere.

Vi vil fortsette trinn for trinn for å lage funksjonen normalisere.

Trinn 1) Vi skaper nominator, som er . I R kan vi lagre nominatoren i en variabel som dette:

nominator <- x-min(x)

Trinn 2) Vi beregner nevner: . Vi kan replikere ideen til trinn 1 og lagre beregningen i en variabel:

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

Trinn 3) Vi utfører delingen mellom nevneren og nevneren.

normalize <- nominator/denominator

Trinn 4) For å returnere verdi til å kalle funksjonen må vi sende normalize inside return() for å få utdata fra funksjonen.

return(normalize)

Trinn 5) Vi er klare til å bruke funksjonen ved å pakke alt inn i braketten.

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

La oss teste funksjonen vår med variabelen c1:

normalize(data_frame$c1)

Det fungerer perfekt. Vi opprettet vår første funksjon.

Funksjoner er en mer omfattende måte å utføre en repeterende oppgave på. Vi kan bruke normaliseringsformelen over forskjellige 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)

Selv om eksemplet er enkelt, kan vi utlede kraften til en formel. Koden ovenfor er lettere å lese og unngår spesielt feil når du limer inn koder.

Fungerer med tilstand

Noen ganger må vi inkludere betingelser i en funksjon for å la koden returnere forskjellige utdata.

I maskinlæringsoppgaver må vi dele datasettet mellom et togsett og et testsett. Togsettet lar algoritmen lære av dataene. For å teste ytelsen til modellen vår, kan vi bruke testsettet til å returnere ytelsesmålet. R har ikke en funksjon for å lage to datasett. Vi kan skrive vår egen funksjon for å gjøre det. Vår funksjon tar to argumenter og kalles split_data(). Tanken bak er enkel, vi multipliserer lengden på datasettet (dvs. antall observasjoner) med 0.8. For eksempel, hvis vi ønsker å dele datasettet 80/20, og datasettet vårt inneholder 100 rader, vil funksjonen vår multiplisere 0.8*100 = 80. 80 rader vil bli valgt for å bli treningsdataene våre.

Vi vil bruke luftkvalitetsdatasettet til å teste vår brukerdefinerte funksjon. Luftkvalitetsdatasettet har 153 rader. Vi kan se det med koden nedenfor:

nrow(airquality)

Utgang:

## [1] 153

Vi vil gå frem 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

Vår funksjon har to argumenter. Argumenttoget er en boolsk parameter. Hvis den er satt til TRUE, oppretter funksjonen vår togdatasettet, ellers oppretter den testdatasettet.

Vi kan fortsette som vi gjorde med normalise()-funksjonen. Vi skriver koden som om det bare var engangskode og pakker så alt med betingelsen inn i kroppen for å lage funksjonen.

Trinn 1:

Vi må beregne lengden på datasettet. Dette gjøres med funksjonen nrow(). Nrow returnerer det totale antallet rader i datasettet. Vi kaller den variable lengden.

length<- nrow(airquality)
length

Utgang:

## [1] 153

Steg XNUMX:

Vi multipliserer lengden med 0.8. Det vil returnere antall rader å velge. Det skal være 153*0.8 = 122.4

total_row <- length*0.8
total_row

Utgang:

## [1] 122.4

Vi ønsker å velge 122 rader blant de 153 radene i luftkvalitetsdatasettet. Vi lager en liste som inneholder verdier fra 1 til total_row. Vi lagrer resultatet i variabelen kalt split

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

Utgang:

## [1] 1 2 3 4 5

split velger de første 122 radene fra datasettet. For eksempel kan vi se at vår variabeldeling samler verdiene 1, 2, 3, 4, 5 og så videre. Disse verdiene vil være indeksen når vi velger radene som skal returneres.

Steg XNUMX:

Vi må velge radene i luftkvalitetsdatasettet basert på verdiene som er lagret i den delte variabelen. Dette gjøres slik:

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

Utgang:

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

Trinn 4:

Vi kan lage testdatasettet ved å bruke de resterende radene, 123:153. Dette gjøres ved å bruke – foran split.

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

Utgang:

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

Trinn 5:

Vi kan skape tilstanden inne i funksjonens kropp. Husk at vi har et argumenttog som er et boolsk satt til TRUE som standard for å returnere togsettet. For å lage betingelsen bruker 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 funksjonen. Vi trenger kun å endre luftkvalitet til df fordi vi ønsker å prøve vår funksjon til evt Dataramme, ikke bare 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)		
  }
}

La oss prøve funksjonen vår på luftkvalitetsdatasettet. vi bør ha ett togsett med 122 rader og et testsett med 31 rader.

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

Utgang:

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

Utgang:

## [1] 31  6