Funcții în R Programare cu Exemplu

⚡ Rezumat inteligent

Funcțiile din R împachetează un set de instrucțiuni sub un singur nume, astfel încât o sarcină repetată să ruleze dintr-un singur apel. Instrumente de asistență matematică și statistică încorporate, funcții definite de utilizator, funcții de mediu.pingși argumentele condiționale sunt prezentate aici cu exemple concrete.

  • 🔘 Anatomia funcției: O funcție combină un nume, o listă de argumente opționale, un corp și o valoare returnată opțională.
  • 🧮 Acoperire încorporată: R oferă funcții generale precum diff() și length() alături de funcții matematice și statistice.
  • 📐 Rescalare reutilizabilă: Funcția normalize() transformă un bloc de rescalare de tip copiere-lipire într-un singur apel reutilizabil.
  • 🧭 Reguli de mediu: Fiecare apel deschide un mediu local, iar R rezolvă un nume de la definiția cea mai interioară spre exterior.
  • 🧪 Logica condiționată: O ramură if/else din interiorul funcției split_data() returnează fie setul de antrenament, fie setul de test.
  • 🛠️ Practică de denumire: Denumirea unei funcții definite de utilizator diferită de una încorporată evită mascarea și confuzia erorilor.

Funcții în programarea R

Ce este o funcție în R?

A funcţie, într-un mediu de programare, este un set de instrucțiuni. Un programator construiește o funcție de evitat repetarea aceleiași sarcini, sau reduce complexitate.

O funcție ar trebui să fie

  • scris pentru a îndeplini o sarcină specificată
  • poate include sau nu argumente
  • conţin un corp
  • poate sau nu returna una sau mai multe valori.

O abordare generală a unei funcții este de a folosi partea argument ca intrări, hraneste corp parte și în cele din urmă returnează an producție. Sintaxa unei funcții este următoarea:

function (arglist)  {
  #Function body
}

R funcții încorporate importante

Există o mulțime de funcții încorporate în R. R potrivește parametrii de intrare cu argumentele funcției sale, fie după valoare, fie după poziție, apoi execută corpul funcției. Argumentele funcției pot avea valori implicite: dacă nu specificați aceste argumente, R va lua valoarea implicită.
notițe:
Este posibil să vedeți codul sursă al unei funcții rulând numele funcției în sine în consolă.

Typing Un nume de funcție fără paranteze afișează sursa sa, așa cum se arată în consola de mai jos.

Consola R imprimă codul sursă al unei funcții încorporate

Vom vedea trei grupuri de funcții în acțiune

  • Funcția generală
  • Funcția matematică
  • Funcția statistică

Funcții generale

Suntem deja familiarizați cu funcții generale precum cbind(), rbind(), range(), fel()și order(). Fiecare dintre aceste funcții are o sarcină specifică, primește argumente pentru a returna un rezultat. Următoarele sunt funcții importante pe care trebuie să le cunoașteți:

funcția diff().

Dacă lucrezi la serii de timp, trebuie să staționați seria prin luarea lor valori de lag. O proces staționar permite medie, varianță și autocorelație constante în timp. Acest lucru îmbunătățește în principal predicția unei serii temporale. Acest lucru se poate realiza cu funcția diff(). Putem construi o serie temporală aleatorie de date cu o tendință și apoi putem folosi funcția diff() pentru a staționarea seria. Funcția diff() acceptă un argument, un vector, și returnează o diferență iterată și întârziată adecvată.

notițeAdesea trebuie să creăm date aleatorii, dar pentru învățare și comparare dorim ca numerele să fie identice pe toate mașinile. Pentru a ne asigura că generăm aceleași date, folosim funcția set.seed() cu valori arbitrare de 123. set.seed() fixează punctul de pornire al generatorului de numere pseudoaleatoare, astfel încât fiecare mașină să producă aceeași secvență. Fără set.seed(), fiecare rulare returnează o secvență diferită.

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

Cele două panouri de mai jos plasează seria cumulativă originală lângă seria diferențiată, care acum fluctuează în jurul unei medii constante.

Serie cumulativă originală alături de seria staționară diferențiată

funcția length().

În multe cazuri, dorim să cunoaștem lungimea unui vector pentru calcul sau pentru a fi utilizat într-o buclă for. Funcția length() numără numărul de rânduri din vectorul x. Următoarele coduri importă setul de date cars și returnează numărul de rânduri.

notițe: length() returnează numărul de elemente dintr-un vector. Dacă funcția este transmisă într-un matrice sau un cadru de date, se returnează numărul de coloane.

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

ieșire:

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

ieșire:

## [1] 50

Funcții matematice

Dincolo de funcțiile generale, R are o serie de funcții matematice care operează element cu element pe un vector.

OperaTdR Descriere
abs (x) Ia valoarea absolută a lui x
log(x,bază=y) Ia logaritmul lui x cu baza y; dacă baza nu este specificată, returnează logaritmul natural
exp (x) Returnează exponențialul lui x
sqrt (x) Returnează rădăcina pătrată a lui x
factorial(x) Returnează factorialul lui 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)

ieșire:

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

ieșire:

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

ieșire:

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

Funcțiile statistice

În timp ce funcțiile matematice transformă valorile, funcțiile statistice le sintetizează. Instalarea standard a R conține o gamă largă de funcții statistice. În acest tutorial, vom analiza pe scurt cele mai importante.

Funcții statistice de bază

OperaTdR Descriere
medie (x) Media lui x
mediana(x) Mediana lui x
var(x) Varianta lui x
sd(x) Abaterea standard a lui x
scară (x) Scoruri standard (scoruri z) ale lui x
cuantilă (x) Quartilele lui x
rezumat(x) Rezumatul lui x: medie, min, max etc..
speed <- dt$speed
speed
# Mean speed of cars dataset
mean(speed)

ieșire:

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

ieșire:

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

ieșire:

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

ieșire:

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

ieșire:

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

ieșire:

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

ieșire:

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

Până în acest moment, am învățat o mulțime de funcții încorporate R.

notițeFiți atenți cu clasa argumentului, adică numeric, boolean sau șir de caractere. De exemplu, dacă trebuie să transmitem o valoare de tip șir de caractere, trebuie să includem șirul de caractere între ghilimele: „ABC”.

Scrieți funcția în R

În unele ocazii, trebuie să scriem propria noastră funcție, deoarece trebuie să îndeplinim o anumită sarcină și nu există o funcție predefinită. O funcție definită de utilizator implică nume, argumente și corp.

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

notițe: O bună practică este de a numi o funcție definită de utilizator diferită de o funcție încorporată. Evită confuzia.

Funcția cu un singur argument

În următorul fragment, definim o funcție pătrată simplă. Funcția acceptă o valoare și returnează pătratul valorii.

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

Code Explicație

  • Funcția se numește square_function; se poate numi cum vrem noi.
  • Primește un argument „n”. Noi nu a specificat tipul de variabilă, astfel încât utilizatorul să poată transmite un număr întreg, un vector sau o matrice
  • Funcția preia intrarea „n” și returnează pătratul intrării. Când ați terminat de utilizat funcția, o putem elimina cu funcția rm().

# după ce creați funcția

rm(square_function)
square_function

Pe consolă, putem vedea un mesaj de eroare: Eroare: obiectul „square_function” nu a fost găsit, indicând că funcția nu există.

Scoția de mediuping

În R, mediu inconjurator este o colecție de obiecte precum funcții, variabile, cadre de date etc.

R deschide un mediu de fiecare dată când pornește RStudio.

Mediul de nivel superior disponibil este mediu global, numită R_GlobalEnv. Și avem mediul local.

Putem enumera conținutul mediului actual.

ls(environment())

producție

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

Puteți vedea toate variabilele și funcțiile create în R_GlobalEnv.

Lista de mai sus va varia în funcție de codul istoric pe care îl executați în RStudio.

Rețineți că n, argumentul funcției square_function nu se află în acest mediu global.

Un nou mediu este creat pentru fiecare funcție. În exemplul de mai sus, funcția square_function() creează un nou mediu în interiorul mediu global.

Pentru a clarifica diferența dintre global și local mediu, să studiem următorul exemplu

Aceste funcții iau o valoare x ca argument și o adaugă la definiția y în afara și în interiorul funcției

Funcția f folosind variabila y definită în mediul global

Funcția f returnează rezultatul 15. Acest lucru se datorează faptului că y este definit în mediul global. Orice variabilă definită în mediul global poate fi utilizată local. Variabila y are valoarea 10 în timpul tuturor apelurilor de funcții și este accesibilă în orice moment.

Să vedem ce se întâmplă dacă variabila y este definită în interiorul funcției.

Trebuie să aruncăm `y` înainte de a rula acest cod folosind rm r

Funcția f care definește y în propriul mediu local

Ieșirea este, de asemenea, 15 când apelăm f(5), dar returnează o eroare când încercăm să tipărim valoarea y. Variabila y nu se află în mediul global.

În cele din urmă, R folosește cea mai recentă definiție a variabilei pentru a trece în corpul unei funcții. Să luăm în considerare următorul exemplu:

R folosește cea mai interioară definiție a lui y din corpul funcției

R ignoră valorile y definite în afara funcției, deoarece am creat în mod explicit o variabilă ay în corpul funcției.

Funcția cu mai multe argumente

Putem scrie o funcție cu mai mult de un argument. Luați în considerare funcția numită „timpi”. Este o funcție simplă care înmulțește două variabile.

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

ieșire:

## [1] 8

Când ar trebui să scriem funcția?

Specialiștii în date trebuie să îndeplinească multe sarcini repetitive. De cele mai multe ori, copiem și lipim bucăți de cod în mod repetat. De exemplu, normalizarea unei variabile este foarte recomandată înainte de a rula o masina de învățare algoritm. Formula de normalizare a unei variabile este:

Formula pentru normalizarea unei variabile

Știm deja cum să folosim funcția min() și max() în R. Folosim biblioteca tibble pentru a crea cadrul de date. Tibble este până acum cea mai convenabilă funcție pentru a crea un set de date de la zero.

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

Vom proceda în doi pași pentru a calcula funcția descrisă mai sus. În primul pas, vom crea o variabilă numită c1_norm, care reprezintă rescalarea lui c1. În pasul doi, pur și simplu copiem și lipim codul lui c1_norm și îl modificăm cu c2 și c3.

Detaliu al funcției cu coloana c1:

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

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

Prin urmare, le putem împărți pentru a obține valoarea normalizată a coloanei c1:

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

Putem crea 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)

ieșire:

## [1] 0.3400113 0.4198788 0.8524394 0.4925860 0.5067991

Funcționează. Putem copia și lipi

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

apoi schimbați c1_norm în c2_norm și c1 în c2. Facem același lucru pentru a crea 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))

Am redimensionat perfect variabilele c1, c2 și c3.

Totuși, această metodă este predispusă la greșeli. Am putea copia și uita să schimbăm numele coloanei după lipire. Prin urmare, o practică bună este să scriem o funcție de fiecare dată când trebuie să lipim același cod de mai mult de două ori. Putem rearanja codul într-o formulă și o putem apela ori de câte ori este nevoie. Pentru a scrie propria noastră funcție, trebuie să dăm:

  • Nume: normalizare.
  • numărul de argumente: avem nevoie de un singur argument, care este coloana pe care o folosim în calcul.
  • Corpul: aceasta este pur și simplu formula pe care vrem să o întoarcem.

Vom proceda pas cu pas pentru a crea funcția normalize.

Pas 1) Creăm numitorul, care este x – min(x). În R, putem stoca numitorul într-o variabilă de genul:

nominator <- x-min(x)

Pas 2) Calculăm numitorul: max(x) – min(x). Putem replica ideea de la pasul 1 și stoca calculul într-o variabilă:

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

Pas 3) Efectuăm împărțirea între numitor și numitor.

normalize <- nominator/denominator

Pas 4) Pentru a returna valoarea funcției de apelare, trebuie să trecem normalize în interiorul return() pentru a obține rezultatul funcției.

return(normalize)

Pas 5) Suntem gata să folosim funcția prin wrapping tot ce se află în interiorul parantezei.

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

Să testăm funcția noastră cu variabila c1:

normalize(data_frame$c1)

Functioneaza perfect. Am creat prima noastră funcție.

O funcție este o modalitate mai cuprinzătoare de a efectua o sarcină repetitivă. Putem folosi formula de normalizare pe diferite coloane, ca mai jos:

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)

Chiar dacă exemplul este simplu, putem deduce puterea unei formule. Codul de mai sus este mai ușor de citit și evită greșelile care apar odată cu lipirea codului.

Funcționează cu condiție

Funcția normalize() face întotdeauna același lucru. Uneori, trebuie să includem condiții într-o funcție pentru a permite codului să returneze ieșiri diferite.

În sarcinile de învățare automată, trebuie să împărțim setul de date între un set de tren și un set de testare. Setul de tren permite algoritmului să învețe din date. Pentru a testa performanța modelului nostru, putem folosi setul de testare pentru a returna măsura de performanță. R nu are o funcție pentru a crea două seturi de date. Putem scrie propria noastră funcție pentru a face asta. Funcția noastră ia două argumente și se numește split_data(). Ideea din spate este simplă, înmulțim lungimea setului de date (adică numărul de observații) cu 0.8. De exemplu, dacă dorim să împărțim setul de date 80/20, iar setul nostru de date conține 100 de rânduri, atunci funcția noastră va înmulți 0.8*100 = 80. 80 de rânduri vor fi selectate pentru a deveni datele noastre de antrenament.

Vom folosi setul de date privind calitatea aerului pentru a testa funcția noastră definită de utilizator. Setul de date privind calitatea aerului are 153 de rânduri. O putem vedea cu codul de mai jos:

nrow(airquality)

ieșire:

## [1] 153

Vom proceda astfel:

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

Funcția noastră are două argumente. Trainul de argumente este un parametru boolean. Dacă este setată la TRUE, funcția noastră creează setul de date tren, în caz contrar, creează setul de date de testare.

Putem continua așa cum am făcut cu funcția normalize(). Scriem codul ca și cum ar fi cod de unică folosință și apoi încapsulăm totul cu condiția în corpul funcției pentru a crea funcția.

Pasul 1:

Trebuie să calculăm lungimea setului de date. Acest lucru se face cu funcția nrow(). Nrow returnează numărul total de rânduri din setul de date. Numim lungimea variabilă.

length<- nrow(airquality)
length

ieșire:

## [1] 153

Pasul 2:

Înmulțim lungimea cu 0.8. Va returna numărul de rânduri de selectat. Ar trebui să fie 153*0.8 = 122.4

total_row <- length*0.8
total_row

ieșire:

## [1] 122.4

Dorim să selectăm 122 de rânduri dintre cele 153 de rânduri din setul de date privind calitatea aerului. Creăm o listă care conține valori de la 1 la total_row. Stocăm rezultatul în variabila numită split

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

ieșire:

## [1] 1 2 3 4 5

split alege primele 122 de rânduri din setul de date. De exemplu, putem vedea că împărțirea noastră variabilă adună valorile 1, 2, 3, 4, 5 și așa mai departe. Aceste valori vor fi indexul când vom selecta rândurile de returnat.

Pasul 3:

Trebuie să selectăm rândurile din setul de date privind calitatea aerului pe baza valorilor stocate în variabila divizată. Acest lucru se face astfel:

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

ieșire:

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

Pasul 4:

Putem crea setul de date de testare utilizând rândurile rămase, 123:153. Acest lucru se face prin utilizarea – în fața split-ului.

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

ieșire:

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

Pasul 5:

Putem crea condiția în interiorul corpului funcției. Amintiți-vă, avem un tren de argumente care este un set boolean la TRUE în mod implicit pentru a returna setul de tren. Pentru a crea condiția, folosim sintaxa if:

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

Asta este, putem scrie funcția. Trebuie doar să schimbăm calitatea aerului în df pentru că vrem să încercăm funcția noastră la oricare cadru de date, nu numai calitatea aerului:

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

Să încercăm funcția noastră pe setul de date privind calitatea aerului. Ar trebui să avem un set de trenuri cu 122 de rânduri și un set de test cu 31 de rânduri.

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

ieșire:

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

ieșire:

## [1] 31  6

Întrebări frecvente

Atribuiți o valoare în definiție, cum ar fi function(df, train = TRUE). Dacă apelantul omite acel argument, R folosește valoarea implicită. Valorile implicite sunt evaluate în mod alene, astfel încât o valoare implicită se poate referi chiar și la un alt argument al aceleiași funcții.

Da. O funcție se poate apela singură atâta timp cât este un stopping condiția încheie lanțul — de exemplu, un factorial care returnează 1 când n ajunge la 1. Recursivitatea profundă poate atinge limita de imbricare a expresiilor, deci iterația este adesea mai sigură.

Nu. R returnează automat valoarea ultimei expresii evaluate, motiv pentru care square_function() funcționează fără return(). Folosește return() atunci când este necesară o ieșire anticipată sau când un rezultat explicit face funcția mai ușor de citit.

R caută mai întâi după numele exact, apoi după numele parțial și apoi după poziție pentru restul argumentelor. Denumirea explicită a argumentelor, ca în seq(45, 55, by = 1), menține apelul lizibil și ferit de reordonarea accidentală.

O funcție creată fără a i se atribui un nume, de obicei transmisă direct către sapply() sau lapply(). R 4.1 a adăugat o formă prescurtată de backslash, astfel încât \(x) x^2 face aceeași treabă ca funcția(x) x^2 într-un timp mult mai scurt.ping.

Noua definiție maschează elementele încorporate în acel mediu, așa că apelarea funcției length() ar putea rula versiunea dvs. în loc de cea de bază. Eliminați copia cu rm() sau alegeți un nume distinct de la început.

Asistenții inteligenți artificiali creează schelete de funcții pornind de la un comentariu în limba engleză simplă, sugerează valori implicite rezonabile ale argumentelor și generează teste unitare. Rulați întotdeauna codul generat pe baza datelor reale, deoarece o funcție R cu aspect plauzibil poate returna în continuare valori greșite, fără a fi nevoie să vă faceți griji.

Da. RStudio Versiunea Desktop 2023.09.0 și versiunile ulterioare includ o opțiune de înscriere Copilotul GitHub integrare. Completează corpurile funcțiilor dintr-un comentariu, dar revizuiți fiecare sugestie, deoarece nu poate vedea datele dvs.

Rezumați această postare cu: