Documente Academic
Documente Profesional
Documente Cultură
Radu Trı̂mbiţaş
1 Cum lucrează R
Cum lucrează R
• La execuţia R, variabilele, datele, funcţiile, rezultatele, etc., sunt memo-
rate ı̂n memoria calculatorului sub formă de obiecte care au un nume.
• Utilizatorul poate executa acţiuni asupra acestor obiecte cu operatori (arit-
metici, logici, de comparaţie, . . . ) şi funcţii (care sunt la rândul lor obiecte).
Utilizarea operatorilor este relativ intuitivă. O funcţie R poate fi schiţată
astfel:
1
• Fişierele de date pot fi citite de pe discuri locale sau de pe servere prin
internet.
• Funcţiile disponibile utilizatorului sunt memorate ı̂ntr-o bibliotecă loca-
lizată pe disc, ı̂n directorul R HOME/library (R HOME este directorul
unde R este instalat).
• Acest director conţine pachete de funcţii, care la rândul lor sunt structu-
rate ı̂n directori. Pachetul numit base este ı̂ntr-un anumit sens nucleul
lui R şi conţine funcţiile de bază ale limbajului, ı̂n particular cele pen-
tru citirea şi prelucrarea datelor. Fiecare pachet are un director numit R,
cu un fişier cu acelaşi nume ca pachetul (de exemplu, pentru pachetul
base, fişierul R HOME/library/base/R/base). Acest fişier conţine toate
funcţiile pachetului.
2 Esenţa limbajului R
2.1 Expresii, obiecte şi funcţii
Expresii şi obiecte
2
• Expresiile presupun, de regulă, referinţe la variabile, operatori ca +, ape-
luri de funcţii şi alte elemente care vor fi introduse ı̂n continuare.
• Expresiile lucrează pe obiecte. Obiect desemnează orice poate fi atribuit
unei variabile. R are mai multe tipuri de obiecte (ex:vectori numerici).
Exemple
>args(plot)
function (x, y, ...)
NULL
> args(plot.default)
3
function (x, y = NULL, type = "p", xlim = NULL,
ylim = NULL, log = "", main = NULL, sub = NULL,
xlab = NULL, ylab = NULL, ann = par("ann"),
axes = TRUE, frame.plot = axes, panel.first = NULL,
panel.last = NULL, asp = NA, ...)
NULL
> args(ls)
function(name, pos=-1L, envir = as.environment(pos),
all.names = FALSE, pattern, sorted = TRUE)
NULL
2.2 Vectori
Vectori
Funcţii pentru creare de vectori: c, seq, rep.
c - “concatenate”
> c(42,57,12,39,1,3,4)
[1] 42 57 12 39 1 3 4
> x <- c("Huey", "Dewey", "Louie"); x
[1] "Huey" "Dewey" "Louie"
4
> c(FALSE, "abc")
[1] "FALSE" "abc"
> c(1.2, 2, TRUE, "gaga")
[1] "1.2" "2" "TRUE" "gaga"
Vectori - secvenţe
Funcţia seq (“sequence”) se utilizează pentru a genera serii echidistante de
numere.
> seq(4,9)
[1] 4 5 6 7 8 9
> 4:9
[1] 4 5 6 7 8 9
Dacă dorim un pas ̸= 1 scriem
> seq(4,16,2)
[1] 4 6 8 10 12 14 16
Echivalent seq(from=4, to=16, by=2).
Funcţia rep (“replicate”) se utilizează pentru a genera valori repetate; are
două variante, după cum al doilea argument este vector sau număr:
> oops <- c(7,9,13)
> rep(oops,3)
[1] 7 9 13 7 9 13 7 9 13
> rep(oops,1:3)
[1] 7 9 9 13 13 13
Funcţia rep se utilizează şi pentru a genera coduri pentru grupuri: dacă ştim
că primele 10 observaţii aparţin unor bărbaţi şi ultimele 15 unor femei, scriem
> rep(1:2,c(10,15))
[1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
Când avem număr egal de replicări se poate folosi each. E.g., rep(1:2,each=10)
este echivalent cu rep(1:2,c(10,10)).
5
Aici, \n este un exemplu de secvenţă escape. Ea reprezintă un singur caracter,
linefeed (LF), dar se introduce prin două caractere. Backslash \se numeşte es-
cape character.
6
Se pot concatena vectori pe linie sau pe coloane, utilizând funcţiile cbind şi
rbind.
> cbind(A=1:4,B=5:8,C=9:12)
A B C
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
> rbind(A=1:4,B=5:8,C=9:12)
[,1] [,2] [,3] [,4]
A 1 2 3 4
B 5 6 7 8
C 9 10 11 12
O modalitate mai generală de a memora date este tabloul array. Tablourile pot
avea mai mulţi indici şi se pot crea cu funcţia array:
, , 2
2.4 Factori
Factori
• În statistică este o practică comună să avem variabile categoriale, care in-
dică o anumită subdivizare a datelor, cum ar fi clasa socială, diagnosticul
primar, stadiul tumorii, etc. De regulă, acestea se introduc utilizând un
cod numeric.
7
• Astfel de variabile se specifică ı̂n R ca factori. Factorul este o structură
de date care (printre alte lucruri) ne permite să atribuim nume cu sens
categoriilor.
• Sunt analize ı̂n care este esenţial pentru R să facă distincţie ı̂ntre codu-
rile de categorii şi variabilele ale căror valori au o semnificaţie numerică
directă.
• Terminologia este că un factor are o mulţime de niveluri. Intern, un factor
cu k niveluri constă din două elemente: (a) un vector de ı̂ntregi ı̂ntre 1 şi
k şi (b) un vector de şiruri caractere de lungime k ce descrie semnificaţia
celor k niveluri.
> fpain
[1] none severe medium medium mild
Levels: none mild medium severe
> as.numeric(fpain)
[1] 1 4 3 3 2
> levels(fpain)
[1] "none" "mild" "medium" "severe"
Funcţia as.numeric extrage codurile valorilor sub formă de numere iar levels
extrage numele nivelurilor.
R permite să se creeze un tip special de factori ı̂n care nivelurile să fie ordo-
nate. Aceasta se realizează cu funcţia ordered, care lucrează la fel ca factor.
2.5 Liste
Liste
Listele sunt obiecte ce constau din anumite componente (care pot fi de tip
diferit). Iată un exemplu simplu:
> Lst<-list(name="Fred", wife="Mary", no.children=3,
+ child.ages=c(4,7,9))
8
Componentele sunt ı̂ntotdeauna numerotate şi pot fi referite ca atare. Compo-
nentele individuale ale lui Lst pot fi referite ca Lst[[1]], Lst[[2]], Lst[[3]]
şi Lst[[4]].
Componentele unei liste pot avea nume, caz ı̂n care ele pot fi referite fie
dând numele ca un şir de caractere ı̂n locul numărului componentei ı̂ntre pa-
ranteze pătrate sau, mai convenabil, dând o expresie sub forma nume$nume_componenta,
cu acelaşi efect. Exemple:
> Lst[1]
$name
[1] "Fred"
> Lst[[1]]
[1] "Fred"
> Lst[[4]][1]
[1] 4
> Lst$wife
[1] "Mary"
> Lst["wife"]
$wife
[1] "Mary"
> Lst[["wife"]]
[1] "Mary"
Lungimea unei liste (numărul de componente pe nivelul exterior) se obţine cu
length(name).
9
6 6515 4680
7 6805 5265
8 7515 5975
9 7515 6790
10 8230 6900
11 8770 7335
La fel ca la liste, componentele (i.e., variabilele individuale) pot fi accesate cu
notaţia $:
> d$intake.pre
[1] 5260 5470 5640 6180 6390 6515 6805 7515
[9] 7515 8230 8770
10
> intake.pre > 7000 & intake.pre <= 8000
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
[9] TRUE FALSE FALSE
Indexarea cu un vector logic ı̂nseamnă că se aleg valorile pentru care vectorul
logic este TRUE, deci ı̂n cazul precedent a 8-a şi a 9-a valoare din intake.post.
Dacă ı̂n vectorul de indexare apar valori lipsă (NA), atunci R va crea elemen-
tul corespunzător ı̂n rezultat, dar cu valorile NA.
În plus faţă de operatorii relaţionali şi logici, există o serie de funcţii care
returnează valori logice. În particular, is.na(x) se utilizează pentru a deter-
mina care elemente din x au valori lipsă (NA). De notat că este o nevoie reală
de funcţia is.na deoarece nu se pot face comparaţii de forma x==NA. O ast-
fel de comparaţie returnează NA pentru orice valoare a lui x. Rezultatul unei
comparaţii cu o valoare necunoscută este necunoscut!
11
Dacă colecţia de date este mare, este uneori convenabil să examinăm numai
primele câteva cazuri. Aceasta se poate face prin indexare. Deoarece o astfel de
situaţie apare frecvent, s-a implementat funcţia head. Implicit, ea vizualizează
primele şase linii. La fel, tail arată ultima parte.
> #indexing
> d[1:2,]
intake.pre intake.post
1 5260 3910
2 5470 4220
> #head
> head(d)
intake.pre intake.post
1 5260 3910
2 5470 4220
3 5640 3885
4 6180 5160
5 6390 5645
6 6515 4680
> #tail
> tail(d)
intake.pre intake.post
6 6515 4680
7 6805 5265
8 7515 5975
9 7515 6790
10 8230 6900
11 8770 7335
12
12 12.79 obese
13 7.05 lean
14 11.85 obese
15 9.97 obese
16 7.48 lean
17 8.79 obese
18 9.69 obese
19 9.68 obese
20 7.58 lean
21 9.19 obese
22 8.11 lean
Acest format este convenabil deoarece se poate generaliza uşor la date clasifi-
cate după criterii multiple. Totuşi, uneori este de dorit să avem datele ı̂ntr-un
vector separat pentru fiecare grup. Din fericire, este uşor să le extragem dintr-
un data frame:
> exp.lean <- energy$expend[energy$stature=="lean"]
> exp.obese <- energy$expend[energy$stature=="obese"]
Ca alternativă, se poate utiliza funcţia split, care generează o listă de vectori
conform unei grupări.
> l <- split(energy$expend, energy$stature)
> l
$lean
[1] 7.53 7.48 8.08 8.09 10.15 8.40 10.88 6.13 7.90
[10] 7.05 7.48 7.58 8.11
$obese
[1] 9.21 11.51 12.79 11.85 9.97 8.79 9.69 9.68 9.19
13
6 5.3 1.49
> lapply(thuesen, mean, na.rm=T)
$blood.glucose
[1] 10.3
$short.velocity
[1] 1.325652
2.9 Sortare
Sortare
14
Comanda sort este trivială
> intake.post
[1] 3910 4220 3885 5160 5645 4680 5265 5975 6790 6900
[11] 7335
> sort(intake.post)
[1] 3885 3910 4220 4680 5160 5265 5645 5975 6790 6900
[11] 7335
Nu ı̂ntotdeauna sortăm după un vector. Frecvent, avem nevoie să sortăm o se-
rie de variabile conform valorilor unei alte variabile — de exemplu, tensiunea
arterială după sex şi vârstă. În acest scop, trebuie să obţinem ı̂ntâi o ordine a
acestor variabile.
> order(intake$post)
[1] 3 1 2 6 4 7 5 8 9 10 11
Ideea este că, indexând cu acest vector, se pot sorta şi alte variabile după acelaşi
criteriu.
> order(intake$post)->o
> intake$post[o]
[1] 3885 3910 4220 4680 5160 5265 5645 5975 6790 6900
[11] 7335
> intake$pre[o]
[1] 5640 5260 5470 6515 6180 6805 6390 7515 7515 8230
[11] 8770
Putem să sortăm şi un data frame, de exemplu intake
> intake.sorted <- intake[o,]
> intake.sorted
pre post
3 5640 3885
1 5260 3910
2 5470 4220
6 6515 4680
4 6180 5160
7 6805 5265
5 6390 5645
8 7515 5975
9 7515 6790
10 8230 6900
11 8770 7335
Sortarea după mai multe criterii se realizează punând mai multe argumente
ı̂n order; de exemplu, order(sex,age) ne va da ı̂ntâi o ordonare ı̂n bărbaţi şi
femei şi apoi pentru fiecare sex după vârstă. Se utilizează o a doua variabilă
dacă ordinea nu poate fi decisă de prima variabilă. Sortare ı̂n ordine inversă se
poate realiza schimbând semnul variabilei.
15
3 Operatori, matrice şi Algebră liniară
3.1 Operatori
Operatori
Operatori
Aritmetici de comparare Logici
+ adunare < !x not
- scădere > x&y and
* ı̂nmulţire <= x&&y and f.
/ ı̂mpărţire >= x|y or
ˆ putere == x||y or f.
%% modulo != xor(x,y) sau exclusiv
%/% ı̂mpărţire ı̂ntreagă
Caracterele următoare sunt, de asemenea, operatori ı̂n R: $, @, [, [[, :, ?, <-,
<<-, =, ::. Tabela operatorilor şi precedenţa lor se poate obţine cu ?Syntax.
16
nrow(A)
ncol(A)
%*% - ı̂nmulţire de matrice
Dacă x este un vector, atunci x %*% A %*% x este o formă pătratică.
Funcţia crossprod(): crossprod(X,y) este echivalentă cu t(X) %*% y dar
operaţia este mai eficientă. Dacă al doilea argument al lui crossprod() lipseşte
se ia identic cu primul.
Semnificaţia lui diag() depinde de argumentul său. diag(v), unde v este
un vector, construieşte o matrice diagonală formată cu elementele vectorului.
diag(M), unde M este o matrice, dă un vector format din elementele diagonalei
principale a lui M. Se utilizează aceeaşi convenţie ca ı̂n MATLAB. Totuşi, dacă
k este un număr, atunci diag(k) este matricea unitate k pe k!
Pentru a rezolva sistemul Ax = b folosim solve(A,b). Funcţia este ma-
tematic echivalentă cu x = A−1 b. Inversa A−1 a lui A se poate calcula cu
solve(A). Funcţia eig calculează valorile şi vectorii proprii ai unei matrice,
det determinantul, iar svd descompunerea cu valori singulare. Exemple:
> A<-matrix(1:4,2,2)
> A
[,1] [,2]
[1,] 1 3
[2,] 2 4
> b<-c(4,6)
> x<-solve(A,b); x
[1] 1 1
> X<-solve(A)
> A%*%X
[,1] [,2]
[1,] 1 0
[2,] 0 1
> X%*%A
[,1] [,2]
[1,] 1 0
[2,] 0 1
> ev<-eigen(A)
> ev
$values
[1] 5.3722813 -0.3722813
$vectors
[,1] [,2]
[1,] -0.5657675 -0.9093767
[2,] -0.8245648 0.4159736
> det(A)
[1] -2
17
> sd<-svd(A); sd
$d
[1] 5.4649857 0.3659662
$u
[,1] [,2]
[1,] -0.5760484 -0.8174156
[2,] -0.8174156 0.5760484
$v
[,1] [,2]
[1,] -0.4045536 0.9145143
[2,] -0.9145143 -0.4045536
> sd$u%*%diag(sd$d)%*%t(sd$v)
[,1] [,2]
[1,] 1 3
[2,] 2 4
Bibliografie
Bibliografie
[1] W. N. Venables, D. M. Smith and the R Development Core Team, An Intro-
duction to R, 2015
[2] Peter Dalgaard, Introductory Statistics with R, 2nd ed., Springer Verlag, 2008.
18