Introduzione a R Cinzia Viroli Dipartimento di Scienze Statistiche Università di Bologna [email protected] Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 1 0. Premessa R è uno dei software statistici più utilizzati dalla comunità scientifica. La sua grande diffusione nasce dal fatto che si tratta di un ambiente di tipo open source ovvero disponibile gratuitamente sotto i vincoli della GPL (General Public Licence) per diversi sistemi operativi. Si tratta di un ambiente molto versatile e potente che permette di gestire basi di dati, di effettuare analisi statistiche e di produrre grafici di alto livello. Inoltre esso rappresenta un vero e proprio linguaggio di programmazione orientato ad oggetti che consente l'uso di strutture condizionali e cicliche, nonché di funzioni create dall'utente. Per informazioni sull'installazione del programma: http://cran.r-project.org/ Queste semplici note rappresentano uno schema molto sintetico e non esaustivo degli argomenti trattati a lezione. Per maggiori dettagli sull'uso di R si faccia riferimento al volume: A first course in Statistical programming with R, Braun and Murdoch, Cambridge University Press, 2008 (in inglese) oppure ai tanti manuali gratuiti scaricabili dal sito di R http://cran.r-project.org sotto la voce Contributed Documentation. 1. Introduzione al linguaggio R R è un linguaggio di programmazione ad oggetti. I possibili oggetti sono vettori, matrici, liste, basi di dati (dataframe), funzioni ecc. Sia in windows che in linux non esiste una interfaccia grafica al programma. Quando si apre R per la prima volta appare una semplice finestra bianca (chiamata console) con un cursore che indica la posizione in cui inserire un qualche comando. L'area di lavoro iniziale di R (chiamata workspace) è vuota. Per verificarlo si digiti: > ls() oppure > objects() Se si costruisce un semplice oggetto di nome pluto a cui si assegna il valore 3: > pluto=3 l'area di lavoro ora conterrà il nuovo oggetto. Si immagini ora di lavorare in R e alla fine della sessione di lavoro si vogliano salvare gli oggetti costruiti. Occorre quindi salvare il workspace in una determinata directory di lavoro. Alcuni comandi utili: > getwd() per conoscere la directory di lavoro > setwd(“directory”) per impostare la directory di lavoro > save.image(“nome.RData”) per salvare il workspace > load(“nome.RData”) per caricare il workspace > savehistory(“nome”) e loadhistory(“nome”) per salvare l'elenco dei comandi digitati nella console. e caricare Per uscire da R: q() Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 2 1.1 Lavorare con gli oggetti > x=2+(3-4*5)/2 #costruisci un oggetto > x #guardalo [1] -6.5 > x-2 #...utilizzalo [1] -8.5 > x=5 #...sovrascrivilo > y=2.5 #crea un altro oggetto > x/y #fai qualsiasi operazione con gli oggetti [1] 2 Il simbolo # è il commento e viene ignorato dall’ambiente. 1.1 Operatori logici > 2*2==4 [1] TRUE > 2*3==4 [1] FALSE > 2*2>=4 [1] TRUE > 2*3>4 [1] TRUE > 2*3>=4 [1] TRUE > 2*3!=4 [1] TRUE 1.2 Vettori > x=c(2,5,9.5,-3) #costruisci un vettore > x[2] #seleziona il suo secondo elemento [1] 5 > x[c(2,4)] #seleziona i suoi elementi nella posizione 2 e 4 [1] 5 -3 > x[x>0] #seleziona i sui elementi positivi [1] 2.0 5.0 9.5 > x[x>0]-1 [1] 1.0 4.0 8.5 > x[x>0][2] [1] 5 > x=1:10 > x [1] 1 2 3 4 5 6 7 8 9 10 > x1=seq(1,1000, length=10) #vettore da 1 a 1000 di ampiezza 10 > x1 [1] 1 112 223 334 445 556 667 778 889 1000 > x2=rep(2,times=10) #ripeti 2 10 volte > x2 [1] 2 2 2 2 2 2 2 2 2 2 > rep(c(1,3),times=4) #ripeti (1,3) 4 volte [1] 1 3 1 3 1 3 1 3 > rep(c(1,9),c(3,1)) #ripeti (1,9) 3 e 1 volta rispettivamente [1] 1 1 1 9 > length(c(x,x1,x2,3)) Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 3 [1] 31 1.3 Matrici > x=matrix(1:10,ncol=5) #costruisci una matrice > x [,1] [,2] [,3] [,4] [,5] [1,] 1 3 5 7 9 [2,] 2 4 6 8 10 > xx=t(x) #trasponila > x[,1] #seleziona la prima colonna [1] 1 2 > x[2,] #seleziona la seconda riga [1] 2 4 6 8 10 > x[3,2] #seleziona l’elemento [3,2] Error: subscript out of bounds > x[2,3] #...e quello [2,3] [1] 6 > x[,4:5] #seleziona solo le colonne 4 e 5 [,1] [,2] [1,] 7 9 [2,] 8 10 > x[,-c(2,4)] #seleziona le colonne 1, 3 e 5 [,1] [,2] [,3] [1,] 1 5 9 [2,] 2 6 10 > cbind(1:2,c(1,-2),c(0,9)) #dispone per colonne [,1] [,2] [,3] [1,] 1 1 0 [2,] 2 -2 9 > rbind(1:4,c(0,5,-4,6)) #dispone per righe [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 0 5 -4 6 > diag(x[,4:5]) #estrae la diagonale principale [1] 7 10 > D=diag(1:3) #costruisce una matrice diagonale > A=matrix(0,3,3) # crea una matrice di zeri > A=edit(A) # inserisci dei valori nella matrice 1.4 Dataframe > X=data.frame(a=1:4, sesso=c("M","F","F","M")) #crea un dataframe #con una variabile ‘quantitativa’ e una ‘qualitativa’. > X a sesso 1 1 M 2 2 F 3 3 F 4 4 M > dim(X) [1] 4 2 > X$eta=c(2.5,3,5,6.2) #aggiungi una variabile > X Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 4 a 1 2 3 4 sesso eta 1 M 2.5 2 F 3.0 3 F 5.0 4 M 6.2 > X[X$sesso=="M","eta"] #guarda eta per i maschi [1] 2.5 6.2 > X$sesso[X$eta<=3] #guarda sesso per cui eta<=3 1.4 Array > a=array(1:24,c(3,4,2)) #crea un array > a #guardalo 1.4 Liste > lista=list(oggetto1=a,oggetto2=X) #crea una lista > lista$oggetto2 #guarda un oggetto della lista Esercizio Calcolare la media aritmetica e la varianza 1 n ( x i − x )2 s2 = ∑ n − 1 i=1 delle vendite di un certo quotidiano di un edicolante in una settimana: lunedì martedì mercoledì giovedì venerdì sabato 50 84 44 43 40 65 2. Le funzioni In R esistono tantissime funzioni diverse. Ad esempio mean() summary() sum() var() Altre possono essere costruite e caricate. Per fare questo è comodo utilizzare un editor. In linux esistono diverse possibilità fra cui KATE e Emacs Speack Statistics (ESS). Proviamo a costruire la funzione che calcola la varianza. varianza=function(vettore) { numobs=length(vettore) varianza=sum((vettore-mean(vettore))^2) varianza=varianza/(numobs-1) return(varianza) } Una volta che la funzione è stata scritta su un editor per compilarla e quindi renderla disponibile in R si Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 5 può procedere in due modi: o con copia ed incolla, oppure occorre salvarla in un file chiamato ad esempio “varianza.R” e digitare nella console: source(“varianza.R”) Si può costruire anche una funzione che riporti in uscita più oggetti attraverso le liste. Vogliamo costruire una funzione che restituisca in output media e varianza: media.var=function(vettore) { numobs=length(vettore) media=mean(vettore) varianza=sum((vettore-media)^2) varianza=varianza/(numobs-1) return(list(media=media,var=varianza)) } Oppure si può costruire una funzione che prenda in entrata più oggetti. Ad esempio dato un certo capitale e un certo tasso di interesse mensile si vuole calcolare il montante dopo 6 mesi (capitalizzazione semplice) M=C(1+6i): calcola.montante=function(capitale,interesse,mesi=6) { montante=capitale*(1+interesse*mesi) return(montante) } Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 6 3. La programmazione in R Il ciclo for: for (name in vector) {commands} Esempio: i numeri di Fibonacci Calcolare i primi 12 numeri di Fibonacci. Fibonacci=rep(0,12) Fibonacci[1]=1 Fibonacci[2]=1 for (i in 3:12) Fibonacci[i]=Fibonacci[i-2]+Fibonacci[i-1] La condizione if: if (condition) {commands when TRUE} if (condition) {commands when TRUE} else {commands when FALSE} L'istruzione while: while (condition) {statements} L'istruzione repeat: repeat {statements} if (condition) break Esempio: il metodo di Newton per trovare le radici di una funzione Si tratta di un algoritmo per determinare le radici di una funzione f(x)=0 sulla base dell'approssimazione di Taylor. Se f'(x) è la derivata prima di f(x) allora l'algoritmo consiste nell'iterare (x0 scelta iniziale) xn=xn-1 – f(xn-1)/f'(xn-1) sino a convergenza. Esempio Si applichi l’algoritmo di Newton per determinare le radici della funzione f ( x) = x 3 + 2 x 2 − 7 ### Newton con while### newton.1=function(x0,tolerance=0.000001) { x=x0 f=x^3+2*x^2-7 while (abs(f)>tolerance) { f.prime=3*x^2+4*x x=x-(f/f.prime) f=x^3+2*x^2-7 Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 7 } return(x) } ### Newton con repeat### newton.2=function(x0,tolerance=0.000001) { x=x0 repeat { f=x^3+2*x^2-7 if (abs(f) < tolerance) break f.prime=3*x^2+4*x x=x-(f/f.prime) } return(x) } Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 8 4. Simulazione 4.1 Generazione di numeri casuali Generazione di numeri pseudo-casuali Esistono diversi modi per generare una sequenza di numeri nell’intervallo [0,1] che ha tutte le caratteristiche di una sequenza casuale (ma non lo è perciò la si definisce pseudo-casuale). Un algoritmo molto semplice è il seguente. Si fissi un numero intero m e un numero intero b<m, non uno fra i divisori di m. Si scelga un valore di partenza indicato con x0 chiamato seed. Per generare una sequenza di numeri pseudo-casuali (u1,u2,…,un) si può procedere come segue: x1 = b x0 mod m u1 = x1/m dove u1 è il primo numero pseudo-casuale. Il secondo lo si ottiene come: x2 = b x1 mod m u2 = x2/m e così via. Esempio Costruire il programma che generi una sequenza di numeri casuali dati un seme (seed) e i valori per b ed m. Eseguire il programma con m=7 e b=3. genera.random=function(n,seme=1,m=100000,b=trunc(sqrt(m))) { num.casuali=rep(0,n) for (i in 1:n) {seme=(b*seme)%%m num.casuali[i]=seme/m } return(num.casuali) } Cosa succede se b è un divisore di m? Quale problema si può riscontrare quando m è un numero non elevato? Generazione di numeri (pseudo-)casuali da una uniforme runif(n,min=a,max=b) Esempio Generare 1000 osservazioni da due variabili aleatorie X1 e X2 distribuite secondo una uniforme in [0,1]. Farne uno scatterplot. Sono indipendenti? Costruirne poi la variabile somma e la variabile differenza e farne uno scatterplot. Misurare la correlazione fra le due coppie di variabili. set.seed(1) ## per fissare un punto di partenza comune x1=runif(1000) x2=runif(1000) plot(x1~x2) S=x1+x2 Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 9 D=x1-x2 plot(S~D) cor(x1,x2) cor(S,D) Generazione di numeri casuali da una bernoulli Una variabile aleatoria di Bernoulli ha due esiti possibili con probabilità rispettivamente p e (1-p). Esempio Una prova di esame consiste di 20 domande alle quali la mia preparazione mi consente di rispondere correttamente con una probabilità del 20%. Generare uno fra i possibili risultati all'esame. risposte=runif(20) risposte.corrette=(risposte<0.2) table(risposte.corrette) pie(table(risposte.corrette),col=c("red","green")) La variabile aleatoria binomiale La somma X di n prove indipendenti di Bernoulli ciascuna con probabilità p è la variabile binomiale. X rappresenta il numero di successi in n prove. dbinom(x,size,prob) # calcola la probabilità di avere “x” successi in # “size” prove ciascuna con probabilità “prob” pbinom(x,size,prob) # calcola la probabilità di avere al massimo “x” # successi ovvero P(X≤x) rbinom(n,size,prob) # genera n variabili binomiali Esempio Quale è la probabilità che in 100 lanci di una moneta non truccata si ottengano esattamente 50 teste e 50 croci? Sorprendentemente questa probabilità è alquanto bassa: dbinom(50,100,0.5) [1] 0.07958924 E in 20 lanci quale è la probabilità di ottenere 10 teste e 10 croci? Costruire il grafico che associa ad ogni possibile numero di teste in 20 lanci la sua probabilità. x=0:20 prob=rep(0,21) for (i in 1:21) prob[i]=dbinom(x[i],20,0.5) barplot(prob,names.arg=x) Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 10 Esempio Si sa che in un processo industriale il 10% delle tubi prodotte da una vecchia macchina risultano difettose. Si sa inoltre che vengono prodotti 15 tubi ogni ora. Si definisce un processo fuori controllo quando più di 4 tubi escono difettosi ogni ora. Simulare il numero di pezzi difettosi prodotti ogni ora nell'arco di 24 ore e contare i processi fuori controllo. pezzi.dif=rbinom(24,15,0.1) sum(pezzi.dif>4) La variabile aleatoria normale La variabile aleatoria normale è caratterizzata da due parametri: la media e la standard deviation. dnorm(x,mean,sd) # calcola la densità di probabilità pnorm(x,mean,sd) # calcola P(X≤x) chiamata funzione di ripartizione rnorm(n,mean,sd) # genera n variabili normali qnorm(p,mean,sd) # restituisce il valore di ascissa (quantile) in # corrispondenza del valore dell'integrale p Esempio Simulare 10000 realizzazioni da una distribuzione normale con media 50 e deviazione standard 5.2 e costruirne l'istogramma. x=rnorm(10000,50,5.2) hist(x,probability=TRUE) lines(density(x)) Esempio Calcolare la probabilità che le realizzazioni di una variabile aleatoria 'standardizzata' (ovvero con media zero e standard deviation 1) siano comprese nell'intervallo [-1.946, 1.946]. ## Primo modo ## prob=pnorm(-1.946) 1-2*prob ## in virtù della simmetria della distribuzione ## Secondo modo ## n=10000000 x=rnorm(n) compresi=(x>-1.946 & x<1.946) sum(compresi)/n Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 11 4.2 Integrazione di Monte Carlo Le realizzazioni dalle varie leggi distributive possono essere utilizzate per approssimare gli integrali del tipo: ∫ b a g (u )du Siano u1,u2,…,un n realizzazioni indipendenti da variabili aleatorie uniformi nell’intervallo [a,b]. Allora per la definizione di valore atteso di una variabile aleatoria si sa E [g (u )] = ∫ g (u ) b a 1 du b−a da cui, per la legge dei grandi numeri ∫ b a 1 n g (u )du = E [g (u )](b − a ) ≅ ∑ u i (b − a ) n i =1 Esempio Approssimare l’integrale 5 ∫ sin( x)dx (vero valore –0.7) 2 u=runif(10000,2,5) mean(sin(u))*(5-2) Esempio Approssimare l’integrale doppio 10 7 ∫ ∫ sin( x − y)dxdy 3 1 u=runif(10000,1,7) v=runif(10000,3,10) mean(sin(u-v))*(10-3)*(7-1) Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 12 5. Alcuni elementi di algebra lineare Prendiamo una matrice quadrata A: A=matrix(c(1,2,1.5,0.5),2,2) Alcune proprietà: det(A) # calcola il determinante di A dim(A) # restituisce le dimensioni della matrice diag(A) # restituisce gli elementi sulla diagonale principale di A sum(diag(A)) # calcola la traccia di A t(A) # restituisce la trasposta di A diag(diag(A)) # restituisce una matrice diagonale con gli elementi della diagonale principale di A eigen(A) # calcola autovalori e autovettori di A solve(A) # calcola l’inversa della matrice Prendiamo 2 matrici con le stesse dimensioni: A=matrix(c(1,2,1.5,0.5),2,2) B=matrix(c(0.3,1,1,-0.5),2,2) A+B A*B A%*%B # somma gli elementi delle due matrici # moltiplica a due a due fra gli elementi delle due matrici # fa il prodotto matriciale Esempio La funzione solve(A,b) restituisce la soluzione del sistema lineare Ax=b. Determinare x tale che H3 x=b con b=[1 2 3]T e H3 la matrice di Hilbert di ordine 3: H3=1/cbind(seq(1,3),seq(2,4),seq(3,5)) b=c(1,2,3) x=solve(H3,b) Esempio Trovare la scomposizione di Choleski e la scomposizione in valori singolari della matrice di Hilbert di ordine 3. H3.chol=chol(H3) t(H3.chol)%*%H3.chol H3.svd=svd(H3) H3.svd$u%*%diag(H3.svd$d)%*%t(H3.svd$v) Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected] 13