laboratorio informatico-statistico con r
Transcript
laboratorio informatico-statistico con r
LABORATORIO INFORMATICO-STATISTICO CON R Mariantonietta Ruggieri Dipartimento di Scienze statistiche e matematiche “S.Vianelli” Università degli studi di Palermo Prefazione Questa dispensa è stata creata per gli studenti di “Laboratorio informatico-statistico” del Corso di laurea in S.I.G.A.D. (Statistica e Informatica per la Gestione e l’Analisi dei Dati) della Facoltà di Economia di Palermo. Il corso di “Laboratorio informatico-statistico” si propone di fornire agli studenti strumenti informatici di supporto agli argomenti trattati nei corsi istituzionali di Statistica descrittiva (MODULO 1) e inferenziale (MODULO 2), pertanto prevede che tali conoscenze siano preliminari. In Appendice si riportano alcuni esercizi con le relative soluzioni. Gli studenti del S.I.G.A.D. possono scaricare i dataset utilizzati collegandosi con il sito del Corso di laurea, il cui indirizzo è: http://dssm.unipa.it/sigad, cliccando sul link “Ruggieri” e scegliendo la cartella “DATASET_R”. Si ricorda che per poter scaricare il materiale didattico bisogna prima effettuare il login. 2 INDICE MODULO 1 5 1 L’ambiente R 6 1.1 Cosa è R 1.1.1 Introduzione all’ambiente statistico R 1.1.2 Come iniziare con R 1.2 Gli oggetti 1.2.1 Vettori e variabili 1.2.2 Matrici 1.3 Matematica con R 1.3.1 Operazioni con vettori e matrici 1.3.2 Risoluzione di equazioni e sistemi 1.3.3 Massimi e minimi di una funzione 1.4 La gestione degli oggetti 1.4.1 Estrarre elementi da vettori o matrici 1.4.2 Il workspace 1.4.3 Tipologie di oggetti 1.5 Funzioni, script o programmi 1.6 Test e cicli 1.7 Input ed Output 1.7.1 Come salvare l’output 1.7.2 Importare dati in formato testo 1.8 Packages di R 2 Statistica descrittiva con R 6 6 6 7 7 9 10 10 12 14 15 15 16 18 20 21 23 23 23 24 25 2.1 Immissione dei dati 2.1.1 Classificazione delle variabili 2.1.2 Dataset statistici 2.2 Serie di dati e distribuzioni di frequenza 2.2.1 Distribuzioni di frequenza per valori singoli 2.2.2 Distribuzioni di frequenza per classi di valori 2.3 Rappresentazioni grafiche 2.3.1 Grafico a colonne 2.3.2 Grafico a torta 2.3.3 Diagramma cartesiano 2.3.4 Istogramma e poligono di frequenza 2.3.5 Funzione di ripartizione 2.3.6 Boxplot 2.4 Indici di sintesi 2.4.1 Le medie 2.4.2 Gli indici di eterogeneità 2.4.3 Gli indici di variabilità 2.4.4 Gli indici di asimmetria e di curtosi 3 25 25 26 29 29 30 32 32 33 33 34 36 39 40 40 42 43 45 3 Relazioni tra variabili 47 3.1 L’analisi delle tabelle di contingenza 3.2 La regressione lineare semplice 3.3 La dipendenza in media: il rapporto di correlazione 47 52 58 MODULO 2 59 4 Calcolo delle probabilità con R 60 4.1 Esperimenti casuali 4.2 Calcolo combinatorio 4.3 Valore atteso e varianza di variabili casuali 4.4 Variabili casuali discrete 4.4.1 v.c. binomiale 4.4.2 v.c. bernoulliana 4.4.3 v.c. geometrica 4.4.4 v.c. binomiale negativa 4.4.5 v.c. ipergeometrica 4.4.6 v.c. di Poisson 4.5 Variabili casuali continue 4.5.1 v.c. normale o di Gauss 4.5.2 v.c. uniforme 4.5.3 v.c. chi-quadrato 4.5.4 v.c. t di Student 4.5.5 v.c. F 4.5.6 v.c. esponenziale 4.5.7 v.c. gamma 4.5.8 v.c. beta 4.6 Simulazione di variabili casuali 5 Campionamento e inferenza 60 60 61 65 65 66 67 68 69 69 70 70 74 75 76 77 78 78 80 81 83 5.1 Legge dei grandi numeri 5.2 Teorema centrale del limite 5.3 Funzione di (log)verosimiglianza 5.4 Intervalli di confidenza 5.4.1 IC per la media 5.4.2 IC per una proporzione 5.4.3 IC per la varianza 5.5 Verifica di ipotesi 5.5.1 Verifica di ipotesi per la media 5.5.2 Verifica di ipotesi per una proporzione 5.5.3 Verifica di ipotesi per la varianza Appendice Esercizi modulo 1 Esercizi modulo 2 Soluzioni esercizi modulo 1 Soluzioni esercizi modulo 2 83 85 87 90 90 93 94 95 96 97 98 101 102 105 109 124 4 MODULO 1 5 1 L’ambiente R 1.1 Cosa è R 1.1.1 Introduzione all’ambiente statistico R R più che un software si può definire un ambiente statistico di programmazione ad oggetti1, che consente di manipolare quantità di dati consistenti, effettuare calcoli, visualizzare informazioni e grafici, trattare modelli statistici anche complessi. Come S-PLUS ha origine dal linguaggio S2. Il nome “R” deriva probabilmente dalle iniziali del nome dei due sviluppatori originari: Robert Gentleman e Ross Ihaka. R è un linguaggio free, sotto la licenza GNU - General Pubblic Licence - della Free Software Foundation, dunque si può scaricare gratuitamente da Internet all’indirizzo: http://cran.r-project.org/ E’ curato da statistici ed esperti di informatica soprattutto di fama internazionale ed è in costante sviluppo. Il gruppo di sviluppatori di R costituisce l’R Development Core Team. R è cross-platform, ossia è compatibile con vari processori e sistemi operativi ed è open-source, cioè è possibile accedere al codice interno e proporne modifiche. 1.1.2 Come iniziare con R Se R è stato installato correttamente, al suo avvio si apre una finestra, chiamata “R Console”, che fornisce le seguenti informazioni: R : Copyright 2004, The R Foundation for Statistical Computing Version 2.0.1 (2004-11-15), ISBN 3-900051-07-0 R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for a HTML browser interface to help. Type 'q()' to quit R. > Quest’ultimo è il “prompt” di R, dopo il quale possono essere inseriti tutti i comandi. I comandi possono essere separati da un punto e virgola o semplicemente essere immessi in una nuova linea, digitando il tasto “Invio”. Il carattere + sta ad indicare che il comando continua nella linea successiva. I comandi già eseguiti possono essere richiamati da tastiera mediante i tasti freccia verticali ( ↑, ↓) e modificati mediante i tasti freccia orizzontali (←, →). Bisogna tener presente che R è case-sensitive, cioè i caratteri minuscoli sono considerati diversi dai caratteri maiuscoli. 1 2 vettori, funzioni, tabelle, grafici il nome deriva dal linguaggio C, in inglese "SEE" 6 All’avvio di R vengono fornite alcune indicazioni. Ad esempio viene suggerito il comando per uscire dall'ambiente R: >q() Tale procedura è consentita anche dal menu dell’interfaccia grafica (File – Exit oppure ×). E’ possibile ottenere istruzioni sui comandi, attraverso l’help on-line, fortemente consigliato. Le due istruzioni sono equivalenti: >help(nome comando) >?nome comando esempi: >help(q) >?q Alcuni comandi necessitano delle virgolette, come ad esempio for: >help("for") >?"for" Informazioni più dettagliate su come utilizzare l’help, si possono ottenere digitando il comando: >?help E’ possibile aprire una pagina di help in formato html attraverso il comando: >help.start() Per alcune dimostrazioni si può utilizzare il comando: >demo() ad esempio >demo(graphics) mostra una serie di grafici che è possibile costruire con R. 1.2 Gli oggetti 1.2.1 Vettori e variabili Gli elementi che R consente di creare e gestire sono gli oggetti. Gli oggetti più semplici sono gli scalari e i vettori. L’istruzione di assegnazione è <-; il simbolo = è consentito, ma fortemente sconsigliato. Dunque, volendo assegnare ad una variabile x il valore 7, il comando da utilizzare è il seguente: 7 > x<-7 Per visualizzare il contenuto dell’oggetto x, basta richiamare x: >x [1] 7 L’output è preceduto da [1], che sta ad indicare la posizione del primo elemento del vettore x. x, sebbene sia uno scalare, viene interpretato come vettore di lunghezza 1. Creiamo un vettore con più elementi. Le seguenti tre istruzioni sono equivalenti, ma la seconda e la terza non sono consigliate: > y<-c(2,6,8,9,3) > c(2,6,8,9,3)->y > assign("y",c(2,6,8,9,3)) Il comando "c" viene utilizzato per concatenare gli elementi. Gli elementi possono anche essere inseriti uno per volta con l’istruzione “scan()”, separati da spazio o da un Invio, di cui l’ultimo deve essere a vuoto: > y<-scan() 1: 2 6 8 9 3 6: Read 5 items > y<-scan() 1: 2 2: 6 3: 8 4: 9 5: 3 6: Read 5 items Se richiamiamo y, otteniamo i valori in esso contenuti: >y [1] 2 6 8 9 3 Per creare un vettore x che contiene i primi 7 numeri naturali, utilizziamo la seguente istruzione: > x<-1:7 >x [1] 1 2 3 4 5 6 7 Una successione di numeri può anche essere creata col comando “seq”, che consente di specificare anche il passo o il numero n (length) degli elementi della successione3: 3 Ricordiamo che il passo di una successione è dato da: (x(n)-x(1))/(n-1), dove x(1) ed x(n) sono i valori estremi della serie ordinata. 8 > x<-seq(1,7) >x [1] 1 2 3 4 5 6 7 > x<-seq(-2,8,2) >x [1] -2 0 2 4 6 8 > y<-seq(0,1,length=11) >y [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.2.2 Matrici Costruiamo un vettore z che contiene i primi 20 numeri naturali: > z<-1:20 >z [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Volendo creare una matrice A, che contiene gli stessi elementi del vettore z, organizzati in 5 righe e 4 colonne, il comando da utilizzare è “matrix”: > A<-matrix(z,5,4) >A [,1] [,2] [,3] [,4] [1,] 1 6 11 16 [2,] 2 7 12 17 [3,] 3 8 13 18 [4,] 4 9 14 19 [5,] 5 10 15 20 Si noti come R riempia le matrici per colonna. Per riempire la matrice per riga, bisogna aggiungere l’opzione “byrow=TRUE”: > B<-matrix(z,5,4,byrow=TRUE) # riempimento per riga >B [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 5 6 7 8 [3,] 9 10 11 12 [4,] 13 14 15 16 [5,] 17 18 19 20 Il cancelletto # è indicatore di commento; tutto ciò che segue a questo simbolo non viene interpretato da R come comando. Se si vuole creare una matrice di elementi tutti uguali a 0 oppure ad 1, basta inserire come primo argomento, rispettivamente, i valori 0 e 1 una sola volta: 9 > C<-matrix(0,4,3) >C [,1] [,2] [,3] [1,] 0 0 0 [2,] 0 0 0 [3,] 0 0 0 [4,] 0 0 0 > C<-matrix(1,4,3) >C [,1] [,2] [,3] [1,] 1 1 1 [2,] 1 1 1 [3,] 1 1 1 [4,] 1 1 1 Se il primo argomento non viene specificato, R creerà una matrice di elementi NA, dove NA, acronimo di “not available”, definisce i valori mancanti: > C<-matrix(,4,3) >C [,1] [,2] [,3] [1,] NA NA NA [2,] NA NA NA [3,] NA NA NA [4,] NA NA NA 1.3 Matematica con R 1.3.1 Operazioni con vettori e matrici Se x è uno scalare e y un vettore: >x [1] 7 >y [1] 2 6 8 9 3 il comando > x*y [1] 14 42 56 63 21 darà come risultato il prodotto di uno scalare per un vettore, mentre un vettore moltiplicato per se stesso: > y*y [1] 4 36 64 81 9 fornirà un vettore che ha come elementi gli elementi al quadrato di y. L’istruzione “t”, serve per effettuare la trasposizione di un vettore/matrice: 10 > t(y) [,1] [,2] [,3] [,4] [,5] [1,] 2 6 8 9 3 > A<-matrix(1:20,5,4) > t(A) [,1] [,2] [,3] [,4] [,5] [1,] 1 2 3 4 5 [2,] 6 7 8 9 10 [3,] 11 12 13 14 15 [4,] 16 17 18 19 20 Volendo utilizzare l’algebra lineare, per effettuare un prodotto matriciale, si utilizza l’istruzione “%*%”, dunque per eseguire le operazioni - y'×y - y×y' i comandi da utilizzare sono rispettivamente: > t(y)%*%y [,1] [1,] 194 > y%*%y [,1] [1,] 194 > y%*%t(y) [,1] [,2] [,3] [,4] [,5] [1,] 4 12 16 18 6 [2,] 12 36 48 54 18 [3,] 16 48 64 72 24 [4,] 18 54 72 81 27 [5,] 6 18 24 27 9 Come si può notare, per convenzione, le istruzioni > t(y)%*%y > y%*%y sono equivalenti. Per moltiplicare ciascun elemento di un vettore x > x<-c(5,8,2,1,4) per ciascun elemento di un altro vettore y, è possibile utilizzare l’istruzione “%o%”: > x%o%y [,1] [,2] [,3] [,4] [,5] [1,] 10 30 40 45 15 11 [2,] [3,] [4,] [5,] 16 4 2 8 48 12 6 24 64 72 24 16 18 6 8 9 3 32 36 12 che è equivalente all’istruzione > x%*%t(y) [,1] [,2] [,3] [,4] [,5] [1,] 10 30 40 45 15 [2,] 16 48 64 72 24 [3,] 4 12 16 18 6 [4,] 2 6 8 9 3 [5,] 8 24 32 36 12 Lo stesso risultato dà l’istruzione “%x%”: > x%x%y [1] 10 30 40 45 15 16 48 64 72 24 4 12 16 18 6 2 6 8 9 3 8 24 32 36 12 ma sotto forma di vettore. I vettori che hanno come elementi la somma, la differenza, il prodotto ed il rapporto degli elementi corrispondenti dei vettori x ed y, possono essere determinati, rispettivamente, con le seguenti istruzioni: > x+y [1] 7 14 10 10 7 > x-y [1] 3 2 -6 -8 1 > x*y [1] 10 48 16 9 12 > x/y [1] 2.5000000 1.3333333 0.2500000 0.1111111 1.3333333 E’ possibile eseguire altre operazioni con i vettori. Per ulteriori approfondimenti si può utilizzare l’help on-line: > ?"+" > example("+") 1.3.2 Risoluzione di equazioni e sistemi Per risolvere l'equazione p(x)=0, dove p(x)=a0+a1x+…+anxn, l’istruzione da utilizzare è “polyroot”, che ha come argomento il vettore dei coefficienti. Supponiamo, ad esempio, di voler risolvere l’equazione 1-4x+4x2=0: > x<-c(1,-4,4) > polyroot(x) [1] 0.5+0i 0.5-0i 12 In questo caso, essendo il discriminante uguale a zero, le due radici sono reali e coincidenti. In generale, comunque, R fornisce tutte le n soluzioni possibili, anche quelle non reali. Un’altra istruzione che consente di determinare le radici di un’equazione, quando p(x) è una funzione generica qualsiasi, ma sempre di una sola variabile, è “uniroot”. Per i dettagli si utilizzi l’help on-line: > ?uniroot Per la risoluzione di un sistema lineare del tipo Ax=b si utilizza la funzione “solve”. Ad esempio: > A<-matrix(c(4,2,-5,7),2,2) > b<-c(5,3) > x<-solve(A,b) >x [1] 1.31578947 0.05263158 > A<-matrix(c(2,3,4,1,2,-5,8,-1,7),3,3) > b<-c(2,3,1) > x<-solve(A,b) >x [1] 0.73298429 0.40837696 0.01570681 Se b è una matrice: > A<-matrix(c(4,2,-5,7),2,2) > b<-matrix(c(5,-3,1,4),2,2) > x<-solve(A,b) >x [,1] [,2] [1,] 0.5263158 0.7105263 [2,] -0.5789474 0.3684211 Per calcolare l’inversa di A, dunque, basta che b sia la matrice identità; in tal caso, non è neanche necessario specificarlo: > solve(A) [,1] [,2] [1,] 0.18421053 0.1315789 [2,] -0.05263158 0.1052632 L’istruzione “eigen”, invece, consente di calcolare gli autovalori e gli autovettori di una matrice: > A<-matrix(c(1,-1,-1,1),2) >A [,1] [,2] [1,] 1 -1 [2,] -1 1 13 > eigen(A) $values [1] 2 0 $vectors [,1] [,2] [1,] -0.7071068 -0.7071068 [2,] 0.7071068 -0.7071068 Si noti come nella definizione della matrice A è sufficiente specificare solo il numero delle righe. 1.3.3 Massimi e minimi di una funzione Come vedremo più avanti (cfr.par.1.5), l’istruzione “function” definisce una funzione. Consideriamo ad esempio la funzione f(x)=1-3x+2x2, di cui vogliamo calcolare il minimo. L’istruzione “nlm” applica il metodo di Newton, dunque necessita di un valore iniziale per la ricerca del minimo, mentre l’istruzione “optimize” usa metodi non lineari e necessita di un intervallo di valori in cui effettuare la ricerca: > f<-function(x) 1-3*x+2*x^2 > nlm(f,1) $minimum [1] -0.125 $estimate [1] 0.7499997 $gradient [1] 9.994228e-07 $code [1] 1 $iterations [1] 1 > optimize(f,c(-4,3)) $minimum [1] 0.75 $objective [1] -0.125 > f(0.75) # valore della funzione nel punto di ascissa 0.75 [1] -0.125 > plot(f,-4,3) 14 40 30 f (x) 20 10 0 -4 -3 -2 -1 0 1 2 3 x L’istruzione “plot” consente di rappresentare graficamente la funzione nell’intervallo [–4, 3]. Questa istruzione verrà analizzata nei dettagli più avanti (cfr.par. 2.3). 1.4 La gestione degli oggetti 1.4.1 Estrarre elementi da vettori o matrici Se si vuole accedere agli elementi di un vettore, basta richiamare il vettore seguito dalla posizione dell’elemento che si vuole estrarre, racchiusa entro parentesi quadre: > x<-seq(-2,8,2) >x [1] -2 0 2 4 6 8 > x[5] [1] 6 Il comando “which” estrae le posizioni degli elementi di un vettore che soddisfano a determinate condizioni: > which(x<2) [1] 1 2 > which((x>=2)&(x<7)) [1] 3 4 5 > z<-which((x<2)|(x>=5)) >z [1] 1 2 5 6 > x[z] [1] -2 0 6 8 Quest’ultimo comando richiama gli elementi che occupano, rispettivamente, le posizioni contenute in z. Gli operatori & e | sono gli operatori logici “and” e “or”. Per accedere agli elementi di una matrice, bisogna specificare la riga e la colonna in cui si trova l’elemento: > A<-matrix(x,2,2) >A [,1] [,2] 15 [1,] -2 2 [2,] 0 4 > A[1,2] [1] 2 > A<-matrix(x,2,3) >A [,1] [,2] [,3] [1,] -2 2 6 [2,] 0 4 8 > A[2,2] [1] 4 per estrarre un’intera riga o colonna, bisogna specificare la riga o la colonna cui si è interessati, rispettivamente, prima e dopo la virgola: > A[1,] [1] -2 2 6 > A[,2] [1] 2 4 1.4.2 Il workspace L’elenco degli oggetti creati durante una o più sessioni di R costituiscono lo spazio di lavoro (workspace); per visualizzarlo si possono utilizzare le seguenti due equivalenti istruzioni: > ls() > objects() oppure è possibile ricorrere al menu dell’interfaccia grafica (Misc-List objects). Per eliminare gli oggetti dal workspace, si utilizza il comando “rm”, seguito da parentesi tonde, che racchiudono l’elenco degli oggetti da eliminare separati da virgola, ad esempio: > rm(x,y,z,A,B) Per eliminare tutti gli oggetti contemporaneamente, è possibile utilizzare il comando: > rm(list=ls()) oppure il menu dell’interfaccia grafica (Misc-Remove all objects). Per conoscere la cartella di lavoro corrente l’istruzione è: > getwd() Se si desidera cambiarla, ciò è possibile attraverso il menu dell’interfaccia grafica (File-Change dir) oppure attraverso l’istruzione > setwd() in tal caso, bisogna specificare il percorso, all’interno delle parentesi tonde e fra virgolette, ricordandosi di utilizzare tra una cartella e un’altra il back slash o il doppio slash. 16 E’ conveniente creare, prima di aprire una sessione, una propria cartella di lavoro e configurarla direttamente, posizionandosi sull’icona che compare nel desktop per avviare R e cliccando sul tasto destro del mouse (scegliere la voce proprietà). Per conoscere i file contenuti nella cartella di lavoro l’istruzione è > dir() oppure dal menu: File-Display file(s) E’ possibile salvare tutte le istruzioni utilizzate in una sessione di lavoro. Dal menu: File-Save History. Il nome del file che contiene le istruzioni salvate avrà estensione “Rhistory”. Queste ultime possono essere richiamate sempre attraverso il menu: File-Load History Gli oggetti creati possono essere salvati in un file che avrà estensione “Rdata”. L’istruzione è: > save(elenco oggetti separati da virgola, file="nome file"). E’ possibile salvare tutti gli oggetti dal menu: File-Save Workspace e richiamarli: File-Load Workspace. L’istruzione equivalente, in quest’ultimo caso è: > load("nome file"). Alla chiusura di una sessione di R si può scegliere, comunque, di salvare istruzioni e oggetti contemporaneamente (Save workspace image). E’ possibile anche salvare l’intera schermata, in formato testo. Dal menu: File-Save to File. Se, invece, si vuole pulire la schermata, durante una sessione di lavoro, dal menu: Edit-Clear console. Dalle situazioni di "empasse" si può uscire digitando "." 17 oppure ")" o semplicemente pigiando il tasto “ESC” o, ancora, dal menu dell’interfaccia grafica: Misc-Stop current computation. 1.4.3 Tipologie di oggetti Il nome di un oggetto può essere un carattere alfanumerico e può contenere il punto, ma non deve mai iniziare con un numero. E’ consigliabile non utilizzare alcuni nomi riservati, nomi di funzioni od operatori, quali: FALSE, TRUE, Inf, NA, NaN, NULL, break, else, for, function, if, in, next, repeat, while. Non è conveniente, anche se ammesso,definire con "q" o "c" un oggetto. I nomi delle funzioni non possono contenere caratteri particolari come, ad esempio, l’underscore. Le diverse tipologie di oggetti che R può maneggiare sono: character: integer: numeric: complex: logical: stringhe o sequenze di caratteri; numeri interi, con o senza segno; numeri reali; numeri complessi; assumono i valori TRUE, FALSE, NA. Questi oggetti possono essere scalari, vettori, matrici a due o più vie. Esiste poi in R la cosiddetta “lista”, che è un insieme di oggetti di tipo diverso. Consideriamo, ad esempio, i seguenti oggetti: > ogg1<-c("anna","marco","luca") > ogg1 [1] "anna" "marco" "luca" > ogg2<-complex(real=1:7,imaginary=-1:5) > ogg2 [1] 1-1i 2+0i 3+1i 4+2i 5+3i 6+4i 7+5i > ogg3<-c(TRUE,FALSE,FALSE,TRUE,FALSE) > ogg3 [1] TRUE FALSE FALSE TRUE FALSE > A<-matrix(c(1,-1,-1,1),2) >A [,1] [,2] [1,] 1 -1 [2,] -1 1 > ogg4<-eigen(A) #autovalori e autovettori della matrice A > ogg4 $values [1] 2 0 $vectors [,1] [,2] 18 [1,] -0.7071068 -0.7071068 [2,] 0.7071068 -0.7071068 Creiamo una lista con l’istruzione “list”: > lista<-list(ogg1,ogg2,ogg3,ogg4) > lista [[1]] [1] "anna" "marco" "luca" [[2]] [1] 1-1i 2+0i 3+1i 4+2i 5+3i 6+4i 7+5i [[3]] [1] TRUE FALSE FALSE TRUE FALSE [[4]] [[4]]$values [1] 2.000000e+00 9.860761e-32 [[4]]$vectors [,1] [,2] [1,] 0.7071068 0.7071068 [2,] -0.7071068 0.7071068 Per richiamare una componente della lista “lista”, ad esempio la 2°, specificare il nome della lista, seguito dalla posizione della componente cui si è interessati, racchiusa tra parentesi quadre: > lista[2] [[1]] [1] 1-1i 2+0i 3+1i 4+2i 5+3i 6+4i 7+5i Per richiamare una componente di una componente, ad esempio la 1° componente della 4° componente, l’istruzione è: > lista[4][[1]]$values [1] 2.000000e+00 9.860761e-32 Gli oggetti contenuti in una lista possono anche essere nominati nel seguente modo, in modo tale da rendere più semplice l’accesso agli elementi della lista stessa: > lista2<-list(n1=ogg1,n2=ogg2,n3=ogg3,n4=ogg4) > lista2 $n1 [1] "anna" "marco" "luca" $n2 [1] 1-1i 2+0i 3+1i 4+2i 5+3i 6+4i 7+5i $n3 [1] TRUE FALSE FALSE TRUE FALSE 19 $n4 $n4$values [1] 2.000000e+00 9.860761e-32 $n4$vectors [,1] [,2] [1,] 0.7071068 0.7071068 [2,] -0.7071068 0.7071068 Così, per richiamare la 3° componente della lista “lista2”, si utilizza l’istruzione: > lista2$n3 [1] TRUE FALSE FALSE TRUE FALSE mentre per richiamare la 1° componente della 4° componente, l’istruzione da utilizzare è: > lista2$n4$values [1] 2.000000e+00 9.860761e-32 E’ possibile interrogare R sulla tipologia, la classe e la struttura di un oggetto. Chiediamo, ad esempio, informazioni sull’oggetto di nome “lista”: > is.list(lista) [1] TRUE > class(lista) [1] "list" > str(lista) List of 4 $ : chr [1:3] "anna" "marco" "luca" $ : cplx [1:7] 1-1i 2+0i 3+1i ... $ : logi [1:5] TRUE FALSE FALSE TRUE FALSE $ :List of 2 ..$ values : num [1:2] 2.00e+00 9.86e-32 ..$ vectors: num [1:2, 1:2] 0.707 -0.707 0.707 0.707 1.5 Funzioni, script o programmi Costruire una funzione con R è abbastanza semplice; il comando da utilizzare è “function”, che ha come argomenti, racchiusi tra parentesi tonde, i nomi delle variabili. Supponiamo di voler costruire una funzione che calcoli il prodotto fra due numeri x e y; tale funzione la chiamiamo “per”: > per<-function(x,y) x*y Volendo, dunque, calcolare il prodotto di due numeri qualsiasi, basta richiamare la funzione e specificare i due valori: > per(5,2) [1] 10 20 Per conoscere gli argomenti di una funzione si può utilizzare il comando “args” o “str”: > args(per) > str(per) oppure il comando “help” se la funzione è già presente in R: > help(nome funzione) Il comando “body” consente di conoscere il codice di una funzione, mentre il comando “fix” apre una finestra, che consente di modificarlo: > body(per) x*y > fix(per) Ovviamente, via via che si acquisirà dimestichezza, si costruiranno funzioni sempre più complesse, che è conveniente salvare, per poi poterle all’occorrenza riutilizzare. Una funzione si può salvare in un file di testo e successivamente richiamare dal menu: File-Source R code o digitando il comando “source”: > source("nome file") Gli script, o programmi, possono essere memorizzati e poi richiamati dal menù: File-Nuovo script File-Apri script Per richiamare uno script si può anche cliccare semplicemente sulla finestrella gialla in alto a sinistra. 1.6 Test e cicli Un test tipico di un algoritmo verifica alcune condizioni ed è così strutturato: if (condizione) istruzione else istruzione Supponiamo, ad esempio, di voler modificare la funzione precedente, in modo tale che calcoli il prodotto di due numeri x e y solo se (if) x>2 e (&) y<7, altrimenti (else) visualizzi la parola “errore”: > per<-function(x,y) >{ > if ((x>2)&(y<7)) > x*y > else 21 > "errore" >} > per(4,3) > per(3,8) Come si può notare, il corpo di una funzione più complessa va inserito all’interno di parentesi graffe. La parte relativa ad “else”, se non è necessaria, può essere omessa. Abbiamo già incontrato gli operatori logici “&” e “|”; altri operatori logici sono “&&” e “||”. I primi due eseguono un controllo logico termine a termine tra due vettori, mentre gli ultimi due eseguono il controllo in sequenza da sinistra a destra e si arrestano fornendo il primo risultato valido. Ad esempio: > x<-c(FALSE,TRUE,TRUE,FALSE,TRUE) > y<-c(TRUE,FALSE,TRUE,FALSE,FALSE) > x&y [1] FALSE FALSE TRUE FALSE FALSE > x&&y [1] FALSE n.b. NA&TRUE ha come risultato NA, invece NA&FALSE restituisce FALSE. Supponiamo di voler visualizzare sullo schermo (print) i valori da 1 ad i, dove i varia (for) da 1 a 5. L’istruzione che consente di creare un ciclo è “for”: > for(i in 1:5) print(1:i) Altri comandi analoghi sono “while” e “repeat”, i cui dettagli sono disponibili nell’help on-line. I cicli in R, se è possibile, sono da evitare, perchè troppo dispendiosi in termini di tempo macchina. Ad esempio, l’istruzione “sum” consente di sommare gli elementi di un vettore, che supponiamo contenga i primi 50000 numeri naturali: > sum(1:50000) [1] 1250025000 Le istruzioni che seguono, consentono di pervenire allo stesso risultato, utilizzando un ciclo for, ma in tempi più lunghi: > x<-0 > for(i in 1:50000) x<-x+i >x [1] 1250025000 22 1.7 Input ed Output 1.7.1 Come salvare l’output E’ possibile memorizzare l'output di una sessione di lavoro in un file di testo attraverso il comando “sink”. L’output da memorizzare va specificato all’interno del comando “cat”. Supponiamo, ad esempio di voler memorizzare la stringa “ciao” nel file di testo “prip.txt”. Le istruzioni da eseguire sono le seguenti: > sink("prip.txt") > cat("ciao") > sink() Il comando “ sink()” serve per chiudere il file di output. E’ possibile visualizzare il contenuto del file di output "prip.txt" dal menu: File-Display file(s) Le istruzioni più utilizzate per salvare l’output sono comunque “write” e “write.table”. L’istruzione “write” memorizza il contenuto di matrici, mentre l’istruzione “write.table” consente di memorizzare dataframe. La differenza fra una matrice e un dataframe consiste nel fatto che la matrice è un oggetto atomico, ossia ha elementi tutti dello stesso tipo (numeri o stringhe), mentre il dataframe contiene elementi misti. Le istruzioni “write” e “write.table” hanno come argomenti fondamentali: l’oggetto x da inviare nel file di output e il file di output. Ad esempio: > x<-1:9 > write(x, file=”nome file”) Per maggiori dettagli si può consultare l’help on-line. Gli oggetti inviati in un file di output possono essere successivamente importati con le istruzioni di cui si parlerà nel prossimo paragrafo. 1.7.2 Importare dati in formato testo I principali comandi per importare dati in formato testo sono “scan” e “read.table”. Il comando “scan” consente di importare un vettore di dati, che si può poi organizzare sotto forma di matrice a due o più vie. Ad esempio: > x<-scan("nome file") > z<-matrix(x, ncol=3, byrow=TRUE) > is.matrix(z) > [1] TRUE Il comando “read.table” consente di importare un dataframe. Volendo importare un dataframe in cui la prima riga è di intestazione, al nome del file deve seguire l’opzione “ header=TRUE ”: > z<-read.table("nome file", header=TRUE) > is.data.frame(z) 23 > [1] TRUE Le colonne di un dataframe non sono direttamente accessibili; per renderle accessibili bisogna utilizzare il comando “attach”: > attach(z) Vi sono dei dataset disponibili nella versione base di R, il cui elenco si può visualizzare con il seguente comando: > data() Per caricare un determinato dataset, per esempio il dataset “cars”, basta specificare il suo nome all’interno delle parentesi tonde, quindi richiamarlo: > data(cars) > cars Per avere informazioni sul dataset, il comando è “help”: > help(cars) Il dataset “cars” è un dataframe, infatti: > is.data.frame(cars) [1] TRUE 1.8 Packages di R Per conoscere l’elenco dei packages contenuti in R, il comando è: > library() Per avere informazioni sul contenuto di un determinato package, si utilizza la seguente istruzione: > library(help=nome package) Per potere essere utilizzato, un package deve essere prima caricato dal menu: Packages-Load package oppure richiamato con l’istruzione: > library(nome package) Esempio: > library(help=nls) > library(nls) 24 2 Statistica descrittiva con R 2.1 Immissione dei dati 2.1.1 Classificazione delle variabili Come è noto, i dati statistici si suddividono in qualitativi e quantitativi. I dati qualitativi sono espressi da attributi e in R vengono elegantemente rappresentati come “factor”; inoltre, se fra di essi è possibile stabilire un ordinamento, è necessario utilizzare il comando “ordered”. Supponiamo di aver rilevato su un gruppo di soggetti il sesso (variabile qualitativa sconnessa) e l’età (variabile quantitativa); supponiamo che quest’ultima sia stata riportata su una scala ordinale a tre livelli (B –bambino, G –giovane, A –anziano): > sesso<-c("M","M","F","M","F","F","F","M") > sesso [1] "M" "M" "F" "M" "F" "F" "F" "M" > str(sesso) chr [1:8] "M" "M" "F" "M" "F" "F" "F" "M" Il sesso viene automaticamente memorizzato come chr (character), ma il comando “factor” rappresenta in R un modo più corretto per definire una variabile qualitativa: > sesso<-factor(sesso) > sesso [1] M M F M F F F M Levels: F M > str(sesso) Factor w/ 2 levels "F","M": 2 2 1 2 1 1 1 2 Se consideriamo una variabile qualitativa ordinabile, dobbiamo tener conto che R utilizza un ordinamento alfabetico: > età<-c("A","G","B","A","G","A","B","A") > età [1] "A" "G" "B" "A" "G" "A" "B" "A" > str(età) chr [1:8] "A" "G" "B" "A" "G" "A" "B" "A" > età2<-factor(età) > età2 [1] A G B A G A B A Levels: A B G > str(età2) Factor w/ 3 levels "A","B","G": 1 3 2 1 3 1 2 1 Per imporre un particolare ordinamento, si può considerare l’opzione, o direttamente il comando, “ordered”; entrambi necessitano dei livelli (levels) ordinati. Le due seguenti istruzioni sono equivalenti: > età2<-factor(età,levels=c("B","G","A"),ordered=TRUE) > età2 25 [1] A G B A G A B A Levels: B < G < A > età3<-ordered(età,levels=c("B","G","A")) > età3 [1] A G B A G A B A Levels: B < G < A Per ragioni di praticità, spesso è utile codificare le modalità di una variabile; per attribuire le etichette ai codici si utilizza il comando "levels": > sesso<-c(1,1,2,1,2,2,2,1) > sesso [1] 1 1 2 1 2 2 2 1 > sesso<-factor(sesso) > sesso [1] 1 1 2 1 2 2 2 1 Levels: 1 2 > levels(sesso)<-c("M","F") > sesso [1] M M F M F F F M Levels: M F Per quanto riguarda i dati quantitativi, non c’è distinzione in R fra dati quantitativi discreti e continui. Supponiamo di aver rilevato su 8 soggetti la statura (variabile quantitativa continua): > statura<-c(150,170,145,168,175,163,172,167) > statura [1] 150 170 145 168 175 163 172 167 > str(statura) num [1:8] 150 170 145 168 175 163 172 167 R memorizza la statura come oggetto di tipo num (numeric). Volendo essere precisi, una variabile quantitativa discreta può essere memorizzata come un oggetto di tipo int (integer). 2.1.2 Dataset statistici Supponiamo di aver rilevato k=4 variabili di tipologia diversa (stato civile, grado di istruzione, numero di figli, peso) su n=25 soggetti. In R è possibile organizzare i dati statistici sotto forma di dataset con il comando “data.frame”. Vediamo come. x: stato civile4 - variabile qualitativa sconnessa > x<-c(1,2,1,3,1,2,4,1,3,4,3,4,1,2,3,4,2,3,3,4,1,2,1,1,2) > x<-factor(x) > levels(x)<-c("N","C","V","S") >x [1] N C N V N C S N V S V S N C V S C V V S N C N N C 4 N: nubile/celibe, C: coniugato, V: vedovo, S: separato/divorziato 26 Levels: N C V S y: grado di istruzione5 - variabile qualitativa ordinabile > y<-c(1,3,1,2,1,2,4,1,3,2,3,4,1,2,3,1,2,3,3,1,4,2,1,3,2) > y<-factor(y) > levels(y)<-c("LE","LM","M","L") > y<-ordered(y) >y [1] LE M LE LM LE LM L LE M LM M L LE LM M LE LM M M LE L LM LE M LM Levels: LE < LM < M < L z: n. di figli – variabile quantitativa discreta > z<-c(0,2,1,3,0,2,4,1,3,4,3,0,1,2,3,4,2,0,3,4,1,2,1,0,2) >z [1] 0 2 1 3 0 2 4 1 3 4 3 0 1 2 3 4 2 0 3 4 1 2 1 0 2 w: peso – variabile quantitativa continua >w<-c(59.20,71.20,80.10,58.89,65.12,82.14,75.20,64.00, + 68.23,72.10,49.00,65.63,68.14,74.30,49.51,72.14,68.25, + 67.14,69.00,70.80,74.34,58.15,57.23,56.22,48.00) >w [1] 59.20 71.20 80.10 58.89 65.12 82.14 75.20 64.00 68.23 72.10 49.00 65.63 [13] 68.14 74.30 49.51 72.14 68.25 67.14 69.00 70.80 74.34 58.15 57.23 56.22 [25] 48.00 Per facilitare l’immissione dei dati, quando questi non vengono direttamente importati da file, può anche essere utilizzato il comando “scan()” (cfr.par. 1.2.1), che però accetta in input solo valori numerici. Rilevate tutte le variabili, i dati possono essere organizzati sotto forma di “dataframe” che, a differenza di una matrice, può contenere variabili miste (cfr.par. 1.7.2): > dataset<-data.frame(x,y,z,w) > dataset x yz w 1 N LE 0 59.20 2 C M 2 71.20 3 N LE 1 80.10 4 V LM 3 58.89 5 N LE 0 65.12 6 C LM 2 82.14 7 S L 4 75.20 8 N LE 1 64.00 9 V M 3 68.23 10 S LM 4 72.10 11 V M 3 49.00 5 LE: analfabeta/licenza elementare, LM: licenza media, M: maturità, L: laurea/oltre 27 12 S L 0 65.63 13 N LE 1 68.14 14 C LM 2 74.30 15 V M 3 49.51 16 S LE 4 72.14 17 C LM 2 68.25 18 V M 0 67.14 19 V M 3 69.00 20 S LE 4 70.80 21 N L 1 74.34 22 C LM 2 58.15 23 N LE 1 57.23 24 N M 0 56.22 25 C LM 2 48.00 Alle variabili può anche essere attribuito un nome nel seguente modo: > dataset<-data.frame(X=x,Y=y,Z=z,W=w) Una volta creato il dataframe di nome “dataset”, le singole variabili possono essere rimosse dal workspace con il comando “rm” (cfr.par. 1.4.2): > rm(x,y,z,w) E’ ovviamente utile salvare (save) il dataset creato, affinché possa essere ricaricato (load) in un secondo momento (cfr.par. 1.4.2): > save(dataset,file="nome file") > load("nome file") E’ stato già detto che le colonne di un dataframe non sono direttamente accessibili (cfr.par. 1.7.2). Per poter utilizzare una variabile, è necessario far seguire al nome del dataframe il nome della variabile preceduto dal dollaro: > dataset$Y se, invece, si vogliono rendere disponibili tutte le variabili del dataset, si può utilizzare il seguente comando: > attach(dataset) la cui funzione contraria è: > detach(dataset) La funzione “attach” consente anche di richiamare un dataframe salvato su un file e poi rimosso dal workspace, senza caricarlo in memoria: > attach("nome file") 28 In questo caso, se utilizziamo il comando “ls()”, vedremo che il workspace non conterrà il dataframe “dataset”. Il comando “detach()” chiude l’accesso al dataframe “dataset”. Poiché un dataframe è comunque una matrice, anche se non contiene dati tutti dello stesso tipo, è possibile estrarre da esso righe e colonne. Ad esempio, se si vuole estrarre dal dataframe “dataset” la quarta riga, il comando è: > dataset[4,] 2.2 Serie di dati e distribuzioni di frequenza 2.2.1 Distribuzioni di frequenza per valori singoli Se abbiamo salvato il dataframe di nome “dataset” in un file di nome “prova.rda”, possiamo richiamarlo col seguente comando: > attach("prova.rda") e rendere accessibili le variabili col comando: > attach(dataset). Costruiamo adesso le distribuzioni di frequenza delle variabili X, Y, Z. L’istruzione è “table”: > table(X) X NCVS 8665 > table(Y) Y LE LM M L 8 7 7 3 > table(Z) Z 01234 55654 Per calcolare le frequenze relative, basta dividere per il totale delle osservazioni, ossia per la lunghezza (length) di ciascun vettore: > table(X)/length(X) X N C V S 0.32 0.24 0.24 0.20 > table(Y)/length(Y) Y LE LM M L 0.32 0.28 0.28 0.12 > table(Z)/length(Z) 29 Z 0 1 2 3 4 0.20 0.20 0.24 0.20 0.16 per calcolare le frequenze relative percentuali, basta moltiplicare le frequenze relative per 100: > table(X)/length(X)*100 X N C V S 32 24 24 20 > table(Y)/length(Y)*100 Y LE LM M L 32 28 28 12 > table(Z)/length(Z)*100 Z 0 1 2 3 4 20 20 24 20 16 Per calcolare le frequenze cumulate, utilizziamo il comando “cumsum”. Ovviamente, ha un senso calcolare le frequenze cumulate solo a partire da una variabile qualitativa ordinabile. Calcoliamo, dunque, le frequenze cumulate assolute, relative e percentuali per le variabili Y e Z: > cumsum(table(Y)) LE LM M L 8 15 22 25 > cumsum(table(Y)/length(Y)) LE LM M L 0.32 0.60 0.88 1.00 > cumsum(table(Y)/length(Y)*100) LE LM M L 32 60 88 100 > cumsum(table(Z)) 0 1 2 3 4 5 10 16 21 25 > cumsum(table(Z)/length(Z)) 0 1 2 3 4 0.20 0.40 0.64 0.84 1.00 > cumsum(table(Z)/length(Z)*100) 0 1 2 3 4 20 40 64 84 100 2.2.2 Distribuzioni di frequenza per classi di valori La variabile W (peso) è una variabile quantitativa continua, per cui, in questo caso, è opportuno costruire una distribuzione di frequenza per classi. A tal fine, R dispone di due comandi: ”cut” ed “hist”. Il comando “cut” ha come argomento fondamentale “breaks”, in cui bisogna specificare gli estremi delle classi o il numero delle classi. Ovviamente, prima di scegliere gli estremi delle classi, occorre ordinare i dati. L’ordinamento degli elementi di un vettore è possibile in R con il comando “sort”: 30 >W [1] 59.20 71.20 80.10 58.89 65.12 82.14 75.20 64.00 68.23 72.10 49.00 65.63 [13] 68.14 74.30 49.51 72.14 68.25 67.14 69.00 70.80 74.34 58.15 57.23 56.22 [25] 48.00 > sort(W) [1] 48.00 49.00 49.51 56.22 57.23 58.15 58.89 59.20 64.00 65.12 65.63 67.14 [13] 68.14 68.23 68.25 69.00 70.80 71.20 72.10 72.14 74.30 74.34 75.20 80.10 [25] 82.14 > e<-c(45,55,65,75,85) > dati<-cut(W,breaks=e) > dati [1] (55,65] (65,75] (75,85] (55,65] (65,75] (75,85] (75,85] (55,65] (65,75] [10] (65,75] (45,55] (65,75] (65,75] (65,75] (45,55] (65,75] (65,75] (65,75] [19] (65,75] (65,75] (65,75] (55,65] (55,65] (55,65] (45,55] Levels: (45,55] (55,65] (65,75] (75,85] Per default R costruisce classi chiuse a destra, altrimenti bisogna aggiungere l’opzione “right=FALSE”: > dati<-cut(W,breaks=e, right=FALSE) > dati [1] [55,65) [65,75) [75,85) [55,65) [65,75) [75,85) [75,85) [55,65) [65,75) [10] [65,75) [45,55) [65,75) [65,75) [65,75) [45,55) [65,75) [65,75) [65,75) [19] [65,75) [65,75) [65,75) [55,65) [55,65) [55,65) [45,55) Levels: [45,55) [55,65) [65,75) [75,85) Il comando "cut" crea un oggetto di tipo "factor", cioè è come se trasformasse la variabile da quantitativa in qualitativa, perché ad ogni dato associa la classe cui appartiene, che costituisce un livello: > str(dati) Factor w/ 4 levels "[45,55)","[55,65)",..: 2 3 4 2 3 4 4 2 3 3 ... Per cui, per costruire una distribuzione di frequenza (per classi), è possibile adesso utilizzare il comando “table”: > table(dati) dati [45,55) [55,65) [65,75) [75,85) 3 6 13 3 Un’altra istruzione che consente di determinare una distribuzione di frequenza per classi è “hist”. Il secondo argomento è “breaks”, la cui funzione è analoga a quella già vista per il comando “cut”; se non si vuole costruire un’istogramma, è necessaria anche l’opzione “plot=FALSE”: > hist(W,e,plot=FALSE) $breaks [1] 45 55 65 75 85 $counts 31 [1] 3 6 13 3 $intensities [1] 0.01200000 0.02400000 0.05200000 0.01200000 $density [1] 0.01200000 0.02400000 0.05200000 0.01200000 $mids [1] 50 60 70 80 $xname [1] "W" $equidist [1] TRUE attr(,"class") [1] "histogram" Il comando “hist” crea un oggetto con struttura di lista, dove: i “breaks” sono gli estremi delle classi; i “counts” le frequenze assolute, le “intensities o density” le densità di frequenza6, i “mids” i valori centrali delle classi; “xname” il nome della variabile ed “equidist” una variabile logica, che vale TRUE se le classi hanno ampiezza costante. L’oggetto creato da “hist” appartiene alla classe “histogram”. 2.3 Rappresentazioni grafiche 2.3.1 Grafico a colonne Il grafico a colonne, come è noto, è tipico delle variabili qualitative. Se la variabile qualitativa è ordinabile va, ovviamente, precedentemente ordinata. Il comando che consente di rappresentare un grafico a colonne è “plot”. Il comando “plot” ha una serie di argomenti, i cui dettagli sono disponibili consultando l’help on-line. Ad esempio, è possibile attribuire un’etichetta ai due assi cartesiani (xlab e ylab), inserire un titolo (main) e un sottotitolo (sub), scegliere il colore (col) e così via: > help(plot) > plot(X, xlab="stato civile", ylab="frequenze assolute", main="grafico a colonne", sub="fonte:....", col="red") 6 4 2 0 frequenze assolute 8 grafico a colonne N 6 C V S stato civile fonte:.... Le densità di frequenza vengono calcolate da R come rapporto fra le frequenze relative e le ampiezze delle classi 32 E’ possibile rappresentare, in ordinata, le frequenze relative; l’istruzione è: > plot(table(X)/length(X), lwd=50) L’opzione “lwd” consente di modificare la larghezza delle colonne. 2.3.2 Grafico a torta Anche il grafico a torta è tipico delle variabili qualitative, quando il numero delle modalità non è troppo elevato. Il comando è “pie”: > pie(table(X), col=c(2,3,4,7), main="grafico a torta") grafico a torta N C S V > pie(table(X), density=c(3,5,10,15), main="grafico a torta") Le opzioni “col” e “density” consentono, rispettivamente, di scegliere il colore o lo spessore del tratteggio dei settori. 2.3.3 Diagramma cartesiano Il diagramma cartesiano è tipico delle variabili quantitative discrete, quale è Z. Il comando è: 3 2 1 0 table(Z) 4 5 6 > plot(table(Z)) 0 1 2 3 4 Z 33 2.3.4 Istogramma e poligono di frequenza L’istogramma è la rappresentazione grafica tipica di una variabile quantitativa continua, quale è W. All’istogramma viene in genere sovrapposto il poligono di frequenza, che come è noto, è una spezzata che passa per i punti medi delle basi superiori dei rettangoli. L’istruzione per rappresentare un istogramma è “hist”, già utilizzata per la costruzione di una distribuzione di frequenza per classi: > e<-c(45,50,65,70,85) > hist(W, e) 0.02 0.00 Density 0.04 Histogram of W 50 60 70 80 W Come si può notare, R rappresenta, giustamente, in ordinata le densità di frequenza, quando le classi scelte non hanno, come in questo caso, tutte la stessa ampiezza. Se, erroneamente, si vogliono rappresentare in ordinata le frequenze assolute, bisogna aggiungere l’opzione “freq=TRUE”: > hist(W,e,freq=TRUE) Per default R costruisce classi di ampiezza uguale, secondo i criteri di alcuni statistici (consultare l’help on-line), riportando in ordinata frequenze assolute. In questo caso, infatti, la base agisce solo come fattore di scala. Per avere in ordinata densità di frequenza si può aggiungere l'opzione “freq=FALSE”. Si noti come il numero delle classi per R è un suggerimento e non un ordine: > op<-par(mfrow=c(2,2)) > hist(W,main="Sturges") > hist(W,breaks="Scott",main="Scott") > hist(W,breaks="FD",main="Freedman-Diaconis") > hist(W,breaks=7,main="7 classi") > par(op) 34 Scott 50 60 70 4 0 Frequency 0 2 4 6 Frequency 8 Sturges 80 40 60 80 W Freedman-Diaconis 7 classi 40 60 0 2 4 6 Frequency 4 0 Frequency 8 W 80 W 50 60 70 80 W Le istruzioni > op<-par(mfrow=c(2,2)) > par(op) consentono, rispettivamente, di aprire e chiudere una finestra grafica suddivisa in sottofinestre, secondo le indicazioni dell’opzione “mfrow” (in questo caso le sottofinestre sono 2×2). In tal modo, è possibile rappresentare più grafici in un’unica finestra. Volendo sovrapporre un poligono di frequenza ad un istogramma, potremmo costruire la seguente funzione: pf<-function(x, e) { if(missing(e)) ist<-hist(x) else ist<-hist(x,breaks=e) xc<-ist$mids xe<-ist$breaks e1<-min(xe)-(min(xc)-min(xe)) e2<-max(xe)+(max(xe)-max(xc)) n<-ist$counts d<-ist$intensities if(ist$equidist) lines(c(e1, xc, e2), c(0, n, 0)) else lines(c(e1, xc, e2), c(0, d, 0)) } Analizziamo la funzione creata nei dettagli. 35 “pf” è funzione di “x” e di “e”, vettori che contengono, rispettivamente, i valori della variabile rilevata e gli estremi delle classi. Il primo test (if) verifica se “e” è stato omesso (missing); in tal caso, R sceglierà per noi il numero, quindi gli estremi, delle classi. Il secondo test verifica se le classi hanno tutte la stessa ampiezza (if(ist$equidist)); in tal caso, verranno riportate in ordinata le frequenze assolute, viceversa saranno considerate le densità di frequenza. Il comando “lines” traccia, su un grafico preesistente, segmenti fra punti, dunque richiede in input due vettori che contengono le coordinate dei punti. Gli oggetti “xc, xe, e1, e2, n, d” definiscono le coordinate di tali punti. Ricordiamo che “ist” è un oggetto di classe “hist” ed ha struttura di lista, di cui “ist$mids, ist$breaks, ist$counts, ist$intensities, ist$equidist“ sono elementi. I comandi “min” e “max” consentono di determinare, rispettivamente, il valore minimo e il valore massimo di un vettore. Per costruire un poligono di frequenza non resta, dunque, che richiamare la funzione “pf”. Vediamo alcuni esempi: op<-par(mfrow=c(2,2)) pf(W) pf(W,"Scott") pf(W,"FD") pf(W,5) par(op) e<-c(45,50,65,70,85) pf(W,e) 0.02 0.00 Density 0.04 Histogram of x 50 60 70 80 x Un comando utile per costruire un poligono di frequenza è anche “polygon”, di cui parleremo più avanti (cfr. par. 4.5.1). 2.3.5 Funzione di ripartizione Il package “stats” di R contiene la funzione “ecdf”, che consente di rappresentare la f.r. (funzione di ripartizione) nel caso discreto: > library() > library(help=stats) > library(stats) > str(ecdf) function (x) 36 Tracciamo il grafico della f.r. per Z, che avrà un andamento a gradini, essendo Z una variabile quantitativa discreta. Il comando è: > plot(ecdf(Z), xlab="z", ylab="F(z)", main="funzione di ripartizione") 0.6 0.4 0.0 0.2 F(z) 0.8 1.0 funzione di ripartizione 0 1 2 3 4 z Per calcolare il valore della f.r. in un punto, ad esempio per calcolare F(2.5), utilizziamo il comando: > ecdf(Z)(2.5) [1] 0.64 Infatti, calcolando le frequenze relative cumulate: > cumsum(table(Z)/length(Z)) 0 1 2 3 4 0.20 0.40 0.64 0.84 1.00 risulta: F(z) = 0 F(z) = 0.20 F(z) = 0.40 F(z) = 0.64 F(z) = 0.84 F(z) = 1 x<0 0 ≤ x<1 1 ≤ x<2 2 ≤ x<3 3 ≤ x<4 x≥4 Se X è una variabile quantitativa continua, la f.r. assumerà la forma di una spezzata. In particolare: F(x) = 0 F(x) = Fi F(x) = 1 x ≤ x1 x = xi+1 x > xn 37 dove x1 e xn sono, rispettivamente, l’estremo inferiore della prima classe e l’estremo superiore dell’ultima classe. Tra xi e xi+1 la f.r. coincide col segmento passante per i punti [xi,Fi-1] e [xi+1,Fi]. Volendo costruire, dunque un programmino, per rappresentare la f.r. di W, che è una variabile quantitativa continua, possiamo procedere come segue. Ordiniamo innanzitutto il vettore W: > sort(W) [1] 48.00 49.00 49.51 56.22 57.23 58.15 58.89 59.20 64.00 65.12 65.63 67.14 [13] 68.14 68.23 68.25 69.00 70.80 71.20 72.10 72.14 74.30 74.34 75.20 80.10 [25] 82.14 Scegliamo come estremi delle classi i seguenti valori: > e<-c(45,55,65,75,85) Per comodità inseriamo un valore più piccolo di 45 e un valore più grande di 85: > e<-c(35,45,55,65,75,85,95) Costruiamo la distribuzione di frequenza per classi: > dati<-cut(W,breaks=e) > dati [1] (55,65] (65,75] (75,85] (55,65] (65,75] (75,85] (75,85] (55,65] (65,75] [10] (65,75] (45,55] (65,75] (65,75] (65,75] (45,55] (65,75] (65,75] (65,75] [19] (65,75] (65,75] (65,75] (55,65] (55,65] (55,65] (45,55] Levels: (35,45] (45,55] (55,65] (65,75] (75,85] (85,95] > table(dati) dati (35,45] (45,55] (55,65] (65,75] (75,85] (85,95] 0 3 6 13 3 0 La distribuzione delle frequenze relative cumulate è: > Fi<-cumsum(table(dati)/length(dati)) > Fi (35,45] (45,55] (55,65] (65,75] (75,85] (85,95] 0.00 0.12 0.36 0.88 1.00 1.00 Aggiungiamo ad Fi uno zero, poiché la f.r. inizialmente vale proprio 0: > Fi<-c(0,Fi) > Fi (35,45] (45,55] (55,65] (65,75] (75,85] (85,95] 0.00 0.00 0.12 0.36 0.88 1.00 1.00 Utilizziamo il comando “plot”, già utilizzato in altre occasioni, per rappresentare questa volta coppie di punti. In particolare, vogliamo rappresentare le coppie di punti (xi, Fi-1), contenute nei vettori ordinati “e” ed “Fi”: 38 > plot(e, Fi, type="b", xlab="w", ylab="F(w)", main="funzione di ripartizione") 0.6 0.4 0.0 0.2 F(w) 0.8 1.0 funzione di ripartizione 40 50 60 70 80 90 w L’opzione type="b" consente di congiungere i punti con un segmento, creando una spezzata. 2.3.6 Boxplot Il boxplot è costituito da una scatola, i cui estremi sono il I ed il III quartile (Q1, Q3), sezionata dalla mediana (Q2), avente dei baffi in corrispondenza dei valori minimo e massimo. In presenza di outliers (valori anomali), che per R sono quei valori che stanno al di fuori dell’intervallo [Q1-1.5DI, Q3+1.5DI]7, i baffi vengono posti in corrispondenza delle osservazioni più vicine agli estremi di tale intervallo e interne ad esso. Gli outliers vengono evidenziati da R con dei puntini. Il boxplot dà indicazioni sulla simmetria o asimmetria di una distribuzione. Dal boxplot della variabile W sembrerebbe che la distribuzione è asimmetrica negativamente, in quanto (Q3Q2)<(Q2-Q1), e non presenta outliers. Tuttavia bisogna ricordare che per una distribuzione simmetrica è (Q3-Q2)=(Q2-Q1), ma non è detto il contrario (condizione necessaria, ma non sufficiente). 50 55 60 65 70 75 80 > boxplot(W) 7 DI=Q3-Q1 è la differenza interquartile 39 2.4 Indici di sintesi 2.4.1 Le medie I QUANTILI In R è possibile calcolare i quantili con il comando “quantile”; in particolare, per la mediana esiste un comando specifico, che è “median”. Questi comandi, però, sono validi solo su dati numerici. Consideriamo nuovamente le variabili del dataframe “dataset”; ricordiamo che ha senso calcolare i quantili a partire da una variabile qualitativa ordinabile: > median(Y) Error in median(Y) : need numeric data > median(Z) [1] 2 > median(W) [1] 68.14 Come si può notare, R dà errore per la variabile Y, poiché questa non è espressa da numeri. Si può ovviare a questo inconveniente calcolando i quantili sulla variabile inizialmente codificata, facendo attenzione ai casi di indeterminazione. Ad esempio, supponiamo di aver rilevato le seguenti modalità (già ordinate) su 10 soggetti: Licenza elementare, Licenza elementare, Licenza media, Licenza media, Licenza media, Maturità, Maturità, Maturità, Maturità, Laurea. Codificando la variabile, si ha: > x<-c(1,1,2,2,2,3,3,3,3,4) > median(x) [1] 2.5 ma, in questo caso, la mediana non può essere data dalla semisomma dei due valori centrali. Il comando “quantile” vuole anch’esso, come primo argomento, un vettore di numeri e ne restituisce il valore minimo, i tre quartili (o ciò che è lo stesso il 25°, il 50° e il 75° percentile) e il valore massimo: > quantile(Z) 0% 25% 50% 75% 100% 0 1 2 3 4 > quantile(W) 0% 25% 50% 75% 100% 48.00 58.89 68.14 72.10 82.14 E’ possibile far calcolare ad R quantili particolari; in tal caso, è necessario inserire, come secondo argomento, un vettore di numeri compresi tra 0 ed 1. Se, ad esempio, vogliamo calcolare il 10° e il 90° percentile di Z e W, i comandi sono: 40 > quantile(Z, c(.10,.90)) 10% 90% 0 4 > quantile(W, c(.10,.90)) 10% 90% 52.194 74.856 LE MEDIE POTENZIATE DI ORDINE R Fra le medie potenziate di ordine r: ⎛ x Mr= ⎜⎜ ∑ ⎝ i =1 n n r i ⎞ ⎟ ⎟ ⎠ 1 r r = -1 media armonica r = 0 media geometrica r = 1 media aritmetica r = 2 media quadratica r = 3 media cubica sussiste, come è noto, la seguente relazione: M-1≤M0≤M1≤M2≤M3 Una funzione generica per poterle calcolare è la seguente: mr<-function(x, r) { n<-length(x) sum((x^r)/n)^(1/r) } Due semplici funzioni per poter calcolare, rispettivamente, la media armonica e la media geometrica sono: #media armonica mean.a<-function(x) { length(x)/sum(1/x) } # media geometrica mean.g<-function(x) { prod(x)^(1/length(x)) } I comandi “sum” e “prod” sommano e moltiplicano, rispettivamente, gli elementi di un vettore. 41 In R esiste il comando “mean”, che consente di calcolare direttamente la media aritmetica. Facciamo degli esempi: > mr(W,1) [1] 65.7612 > mean(W) [1] 65.7612 Il comando “weighted.mean” consente di calcolare la media aritmetica ponderata; in tal caso, è necessario specificare il vettore dei pesi. Il comando “summary”, consente di ottenere il minimo, Q1, Q2, la media aritmetica, Q3 e il massimo di un vettore numerico: > summary(W) Min. 1st Qu. Median Mean 3rd Qu. Max. 48.00 58.89 68.14 65.76 72.10 82.14 Lo stesso comando, applicato ad un dataframe, restituisce gli stessi indici di sintesi per tutte le variabili numeriche, mentre per le variabili espresse da attributi fornisce l’unica sintesi possibile, ossia la distribuzione di frequenza: > summary(dataset) X Y Z N:8 LE:8 Min. :0.00 C:6 LM:7 1st Qu.:1.00 V:6 M :7 Median :2.00 S:5 L :3 Mean :1.92 3rd Qu.:3.00 Max. :4.00 W Min. :48.00 1st Qu.:58.89 Median :68.14 Mean :65.76 3rd Qu.:72.10 Max. :82.14 2.4.2 Gli indici di etererogeneità Come è noto, per una variabile qualitativa si parla più propriamente di eterogeneità, piuttosto che di variabilità. Un indice di eterogeneità è quello proposto da Gini: k G = 1 − ∑ fi2 i =1 che in R si può calcolare costruendo la seguente funzione: gini<-function(x) { n<-length(x) f<-table(x)/n k<-length(f) if(k==1) return(0) 1-sum(f^2) } 42 Tale indice restituisce (return) 0, se (if) il numero k delle modalità della variabile è pari a 1 (massima omogeneità). Se, invece, il totale delle frequenze n è equiripartito fra le k modalità (massima eterogeneità), l’indice assumerà il valore massimo (k-1)/k. Rapportando G a (k-1)/k, dunque, si ottiene un indice di eterogeneità relativo, che varia tra 0 ed 1: ginirel<-function(x) { n<-length(x) f<-table(x)/n k<-length(f) if(k==1) return(0) g<-1-sum(f^2) g*k/(k-1) } Una funzione equivalente a “ginirel”, e che tiene conto della funzione “gini” già costruita, è: ginirel2<-function(x,k) { gini(x)*k/(k-1) } esempi: > gini(X) [1] 0.7424 > ginirel(X) [1] 0.9898667 > ginirel2(X,4) [1] 0.9898667 > gini(Y) [1] 0.7264 > ginirel(Y) [1] 0.9685333 > ginirel2(Y,4) [1] 0.9685333 2.4.3 Gli indici di variabilità Gli indici di eterogeneità si possono calcolare ovviamente anche per variabili quantitative, anche se per quest’ultime esistono degli indici più informativi come, ad esempio, lo scarto quadratico medio. Volendo calcolare l’intervallo di variazione, l’istruzione “range” restituisce il minimo e il massimo di un vettore numerico: > range(W) [1] 48.00 82.14 > min(W) [1] 48 > max(W) [1] 82.14 43 Il range, però, non tiene conto dei valori centrali di una serie ordinata. Lo scarto quadratico medio si può calcolare come radice (sqrt) della varianza, la cui istruzione in R è: > var(W) [1] 85.48671 oppure con il comando “sd”, che sta per “standard deviation”. I comandi “var” ed “sd” restituiscono gli indici campionari; bisogna dunque moltiplicarlarli per (n1)/n o per la radice di tale rapporto per ottenere, rispettivamente, la varianza e la deviazione standard della popolazione: > n<-length(W) > var(W)*(n-1)/n [1] 82.06724 Un’alternativa è costruire una funzione apposita: varianza<-function(x) { m<-mean(x) n<-length(x) sum((x-m)^2)/n } varianza2<-function(x) { m<-mean(x) n<-length(x) sum(x^2)/n-m^2 } La funzione “varianza2” calcola la varianza con la formula ridotta. Esempi: > varianza(W) [1] 82.06724 > varianza2(W) [1] 82.06724 Volendo calcolare un indice di variabilità relativa, ad esempio il coefficiente di variazione, che consente di confrontare la variabilità di due variabili rilevate con diversa unità di misura o aventi ordine medio di grandezza diverso, si può utilizzare la seguente funzione: CV<-function(x) { m<-mean(x) sqrt(varianza(x))/abs(m) } 44 > CV(W) [1] 0.1377575 2.4.4 Indici di asimmetria e curtosi Supponiamo di aver rilevato la statura e il peso su un gruppo di soggetti: > peso<-c(45,45,76,48,70,60,90,85,90,49.5,45,85,60,60,70,78,66,77,61,56,48,53,67,71,62,50,75) >statura<-c(160,165,165,161,183,160,186,186,174,160,165,177,170,170,168,181,172,180,177,165, +160,172,169,178,169,162,170) Creiamo un dataframe di nome ‘’quest’’ : 40 60 80 100 120 140 160 180 > quest<-data.frame(X=peso,Y=statura) > attach(quest) > boxplot(X,Y,names=c("peso","statura")) statura peso Come si può notare, è possibile comparare boxplot relativi a più variabili, inserendoli in un’unica finestra. L’opzione “names” consente di attribuire un etichetta a ciascun boxplot. I boxplot danno indicazioni sulla simmetria/asimmetria di una distribuzione, basandosi sulla differenza tra quartili. Un indice di asimmetria più informativo è dato da: β = 1 µ3 σ3 che è possibile calcolare con la seguente funzione: beta1<-function(x) { n<-length(x) s3<-sqrt(var(x)*(n-1)/n)^3 mx<-mean(x) m3<-sum((x-mx)^3)/n m3/s3 } 45 L’indice β1 calcolato sul peso e sulla statura conferma quanto già si evince dai boxplot e cioè un’asimmetria positiva per entrambe le variabili: > beta1(X) [1] 0.2386716 > beta1(Y) [1] 0.386686 Una funzione che consente di valutare la curtosi, tenendo conto dell’indice β2 = µ4 , σ4 è la seguente: beta2<-function(x) { n<-length(x) s4<-sqrt(var(x)*(n-1)/n)^4 mx<-mean(x) m4<-sum((x-mx)^4)/n m4/s4 } esempi: > beta2(X) [1] 1.956912 > beta2(Y) [1] 2.087023 46 3 Relazioni tra variabili 3.1 L’analisi delle tabelle di contingenza Supponiamo di aver rilevato, in una classe di 28 studenti universitari, due variabili: il sesso (x) e la scuola di provenienza (y). Per facilitare l’immissione dei dati, le modalità di ciascuna variabile sono state così codificate: sesso Femmina Maschio 1 2 scuola di provenienza Liceo classico (LC) Liceo scientifico (LS) Ist. Tecnico commerciale (ITC) Ist. Tecnico Industriale (ITI) Ist. Tecnico per geometri (ITG) Altro (A) 1 2 3 4 5 6 > x<-c(1,1,1,1,2,1,2,2,2,1,1,2,1,1,2,2,2,2,2,1,1,1,2,2,1,1,2,1) > y<-c(2,2,3,2,2,2,2,7,6,2,2,5,2,2,3,7,3,2,2,1,2,3,3,6,2,3,3,3) Essendo x e y due variabili qualitative, dobbiamo memorizzarle come “factor”, quindi possiamo attribuire i livelli ai codici: > x<-factor(x) > levels(x)<-c("F","M") > y<-factor(y) > levels(y)<-c("LC","LS","ITC","ITI","ITG","A") Il comando per costruire una distribuzione di frequenza congiunta è “table”, già incontrato per costruire la distribuzione di frequenza di una variabile singola. In questo caso, “table” ha come argomento entrambe le variabili in esame: > tab1<-table(x,y) > tab1 y x LC LS ITC ITI ITG A F 1 10 4 0 0 0 M 0 4 4 1 22 “tab1” è un oggetto di classe “table”: > class(tab1) [1] "table" 47 Per conoscere il totale generale n dei soggetti su cui sono state rilevate le due variabili, basta applicare il comando “sum” all’oggetto “table”: > sum(tab1) [1] 28 mentre “dim” informa sul numero di righe e colonne della tabella: > dim(tab1) [1] 2 6 Il comando “dimnames” consente di conoscere le modalità delle due variabili: > dimnames(tab1) $x [1] "F" "M" $y [1] "LC" "LS" "ITC" "ITI" "ITG" "A" Attraverso la seguente istruzione, invece, si può risalire al nome delle due variabili: > names(dimnames(tab1)) [1] "x" "y" Supponiamo di disporre già di una tabella doppia di frequenza. Si consideri, ad esempio, la distribuzione dei laureati del 1991 per gruppo di corso di laurea e condizione occupazionale nel 1993: X\Y Medicina Economia Lettere Occupato stabilmente 681 732 770 Occupato precariamente 466 72 585 Disoccupato 118 18 147 La tabella sopra può essere memorizzata in R attraverso il comando “matrix”, già noto: > vett<-c(681,466,118,732,72,18,770,585,147) > tab2<-matrix(vett,3,3,byrow=TRUE) > tab2 [,1] [,2] [,3] [1,] 681 466 118 [2,] 732 72 18 [3,] 770 585 147 Le modalità delle due variabili, X (laurea) ed Y (occupazione), si possono inserire attraverso i comandi “rownames” e “colnames”: > rownames(tab2)<-c("Medicina","Economia","Lettere") > colnames(tab2)<-c("Occupato stab.","Occupato prec.","Disoccupato") > tab2 48 Occupato stab. Occupato prec. Disoccupato Medicina 681 466 118 Economia 732 72 18 Lettere 770 585 147 > sum(tab2) # totale generale [1] 3589 > dim(tab2) # n. righe e colonne [1] 3 3 Essendo “tab2” un oggetto di tipo “matrix”, è possibile estrarre righe e colonne (cfr.par.1.4.1), che rappresentano, rispettivamente, le distribuzioni condizionate di Y rispetto a X e di X rispetto a Y: > tab2[1,] Occupato stab. Occupato prec. Disoccupato 681 466 118 > tab2[2,] Occupato stab. Occupato prec. Disoccupato 732 72 18 > tab2[3,] Occupato stab. Occupato prec. Disoccupato 770 585 147 > tab2[,1] Medicina Economia Lettere 681 732 770 > tab2[,2] Medicina Economia Lettere 466 72 585 > tab2[,3] Medicina Economia Lettere 118 18 147 E’ possibile con R individuare anche le distribuzioni marginali di X e di Y, attraverso il comando “margin.table”: > margin.table(tab2,1) Medicina Economia Lettere 1265 822 1502 > margin.table(tab2,2) Occupato stab. Occupato prec. Disoccupato 2183 1123 283 E’ infatti: > sum(tab2[1,]) [1] 1265 > sum(tab2[2,]) [1] 822 > sum(tab2[3,]) [1] 1502 49 > sum(tab2[,1]) [1] 2183 > sum(tab2[,2]) [1] 1123 > sum(tab2[,3]) [1] 283 Le distribuzioni relative condizionate possono essere determinate con il comando “prop.table”: > prop.table(tab2,1) Occupato stab. Occupato prec. Disoccupato Medicina 0.5383399 0.36837945 0.09328063 Economia 0.8905109 0.08759124 0.02189781 Lettere 0.5126498 0.38948069 0.09786951 > prop.table(tab2,2) Occupato stab. Occupato prec. Disoccupato Medicina 0.3119560 0.41495993 0.41696113 Economia 0.3353184 0.06411398 0.06360424 Lettere 0.3527256 0.52092609 0.51943463 Infatti: > # frequenze relative rispetto ai totali di riga > tabr<-tab2 > tabr[1,]<-tab2[1,]/sum(tab2[1,]) > tabr[2,]<-tab2[2,]/sum(tab2[2,]) > tabr[3,]<-tab2[3,]/sum(tab2[3,]) > tabr Occupato stab. Occupato prec. Disoccupato Medicina 0.5383399 0.36837945 0.09328063 Economia 0.8905109 0.08759124 0.02189781 Lettere 0.5126498 0.38948069 0.09786951 > print.table(tabr,digits=2) Occupato stab. Occupato prec. Disoccupato Medicina 0.54 0.368 0.093 Economia 0.89 0.088 0.022 Lettere 0.51 0.389 0.098 > # frequenze relative rispetto ai totali di colonna > tabc<-tab2 > tabc[,1]<-tab2[,1]/sum(tab2[,1]) > tabc[,2]<-tab2[,2]/sum(tab2[,2]) > tabc[,3]<-tab2[,3]/sum(tab2[,3]) > tabc Occupato stab. Occupato prec. Disoccupato Medicina 0.3119560 0.41495993 0.41696113 Economia 0.3353184 0.06411398 0.06360424 Lettere 0.3527256 0.52092609 0.51943463 > print.table(tabc,digits=2) Occupato stab. Occupato prec. Disoccupato 50 Medicina Economia Lettere 0.31 0.34 0.35 0.415 0.417 0.064 0.064 0.521 0.519 Il comando “print.table” serve a visualizzare una tabella, mentre l’opzione “digits” stabilisce il numero di cifre decimali significative dopo la virgola. La distribuzione relativa rispetto al totale generale si può così determinare: > prop.table(tab2) Occupato stab. Occupato prec. Disoccupato Medicina 0.1897464 0.1298412 0.032878239 Economia 0.2039565 0.0200613 0.005015325 Lettere 0.2145444 0.1629980 0.040958484 infatti: > tabt<-tab2/sum(tab2) > tabt Occupato stab. Occupato prec. Disoccupato Medicina 0.1897464 0.1298412 0.032878239 Economia 0.2039565 0.0200613 0.005015325 Lettere 0.2145444 0.1629980 0.040958484 > tabt<-tab2/sum(tab2) dove, ovviamente, è: > sum(tabt) [1] 1 INDICI DI ASSOCIAZIONE E’ noto che se le distribuzioni relative condizionate sono tutte uguali fra di loro, si parla di “indipendenza in distribuzione” fra le due variabili. In tal caso, le frequenze congiunte osservate sono uguali alle frequenze teoriche di indipendenza: nij = nij*, dove nij* = ni.×n.j/n L’indice X = ∑∑ 2 i j (n ij − nij* nij* ) 2 di Pearson, basandosi sulla differenza fra frequenze osservate e frequenze teoriche, consente di verificare se fra due variabili c’è indipendenza in distribuzione. Il comando “summary”, applicato ad un oggetto di classe “table”, calcola, fra le altre cose, anche l’indice X2 (Chisq): > summary(tab1) Number of cases in table: 28 Number of factors: 2 Test for independence of all factors: Chisq = 8.472, df = 5, p-value = 0.1321 Chi-squared approximation may be incorrect 51 Il comando “summary”, applicato all’oggetto “tab2”, non restituisce X2, non avendo questi classe “table”. L’oggetto “tab2” può però essere trasformato in un oggetto di classe “table” con il comando “as.table”: > ntab<-as.table(tab2) > summary(ntab) Number of cases in table: 3589 Number of factors: 2 Test for independence of all factors: Chisq = 358.4, df = 4, p-value = 2.691e-76 L’oggetto che restituisce l’istruzione “summary” ha la struttura di una lista, per cui il valore di X2 può essere estratto e rapportato al suo valore massimo (maxX2=nmin[(r-1),(c-1)]), in modo da ottenere un indice normalizzato: > ris<-summary(tab1) > str(ris) List of 7 $ n.vars : int 2 $ n.cases : int 28 $ statistic: num 8.47 $ parameter: num 5 $ approx.ok: logi FALSE $ p.value : num 0.132 $ call : NULL - attr(*, "class")= chr "summary.table" > ris$statistic [1] 8.471795 L’indice X2 si può calcolare anche con il comando “chisq.test”: > chisq.test(tab2) 3.2 La regressione lineare semplice Su un campione di 81 docenti americani è stato rilevato il reddito annuo (in dollari), l’età e gli anni di servizio. I dati sono riportati nel file "regr.txt". Si vuole stabilire se esiste una relazione fra le prime due variabili ed individuare la funzione che rappresenti al meglio tale relazione. Inoltre, si vuole verificare, inoltre, attraverso l’uso di un indice appropriato, se la suddetta funzione si adatta bene ai dati osservati. Importiamo i dati con l’istruzione “read.table” e rendiamo accessibili le colonne del dataframe: > z<-read.table("regr.txt", header=TRUE) > attach(z) Attribuiamo la variabile “reddito” (variabile dipendente) all’oggetto “y” e la variabile “età” (variabile indipendente) all’oggetto “x”: > y<-reddito 52 > x<-eta Rappresentiamo graficamente (scatterplot) le coppie di punti (x,y), utilizzando il comando “plot”, già visto in precedenza (cfr.par.2.3.5): > plot(x,y,xlab="età",ylab="reddito",main="grafico lineare") reddito-età",sub="regressione semplice 30000 20000 reddito 40000 grafico reddito-età 30 40 50 60 età regressione semplice lineare Dall’andamento della nuvola di punti sembrerebbe che fra le due variabili sussista una relazione di tipo lineare. Proviamo, dunque, ad adattare una retta, stimandone i parametri con il metodo dei minimi quadrati: yˆ = αˆ + βˆ x, αˆ = M y − βˆM x βˆ = σ xy σ x2 Occorre calcolare le due medie Mx ed My, la varianza σx2 per la variabile “età” e la covarianza fra le n due variabili σ xy = ∑ (x i =1 i − M x )( y i − M y ) n = M xy − M x M y : > mx<-mean(x) > mx [1] 45.62963 > my<-mean(y) > my [1] 30027.51 > n<-length(x) >n [1] 81 > varx<-(sum((x-mx)^2))/n > varx [1] 90.48011 > covxy<-sum((x-mx)*(y-my))/n > covxy [1] 46402.82 La varianza e la covarianza possono essere calcolate anche con le formule ridotte: 53 > varx<-sum(x^2)/n-mx^2 > varx [1] 90.48011 > covxy<-sum(x*y)/n-mx*my > covxy [1] 46402.82 oppure, rispettivamente, con le funzioni “var” e “cov”, già presenti in R; bisogna tener presente, però, che i comandi “var” e “cov” dividono la devianza e la codevianza per “n-1” e non per “n”: > varx<-var(x)*(n-1)/n > varx [1] 90.48011 > covxy<-cov(x,y)*(n-1)/n > covxy [1] 46402.82 Le stime dei due parametri sono: > b<-covxy/varx >b [1] 512.851 > a<-my-b*mx >a [1] 6626.304 La retta di regressione può essere rappresentata su un grafico preesistente, lo scatterplot in questo caso, con il comando “abline”, che vuole in input le stime dei due parametri: > abline(a,b) 30000 20000 reddito 40000 grafico reddito-età 30 40 50 60 età regressione semplice lineare Un indice di bontà di adattamento della retta ai dati osservati è il coefficiente di determinazione devreg devres = 1− che, come è noto, è uguale al quadrato del coefficiente di correlazione R2 = 2 nο y nο y2 lineare r = σ xy . σ xσ y 54 Occorre, dunque, calcolare dapprima gli scarti quadratici medi σx (sx) e σy (sy) delle due variabili: > sx<-sqrt(varx) > sx [1] 9.512103 > vary<-var(y)*(n-1)/n > vary [1] 37268494 > sy<-sqrt(vary) > sy [1] 6104.793 > r<-covxy/(sx*sy) >r [1] 0.7990922 > R2<-r^2 > R2 [1] 0.6385483 Esiste, comunque, in R il comando “cor”, che consente di calcolare direttamente il coefficiente r: > r<-cor(x,y) >r [1] 0.7990922 Volendo calcolare R2 tramite la devianza di regressione (devreg) o tramite la devianza residua (devres), si può procedere nel seguente modo: > ystim<-a+b*x# valori stimati > res<-y-ystim# residui > devres<-sum(res^2) > devy<-n*vary > R2<-1-devres/devy > R2 [1] 0.6385483 > > devreg<-sum((ystim-my)^2) > R2<-devreg/devy > R2 [1] 0.6385483 Molto semplicemente, per condurre una completa analisi di regressione, si può utilizzare il comando “summary” che ha come argomento un oggetto prodotto dal comando “lm”. Il comando “lm” richiede in input la variabile dipendente (y) e la variabile indipendente (x), separati da una tilde (alt+126), e restituisce le stime dei parametri di regressione: > retta<-lm(y~x) > retta Call: lm(formula = y ~ x) Coefficients: (Intercept) x 55 6626.3 512.9 > summary(retta) Call: lm(formula = y ~ x) Residuals: Min 1Q Median 3Q Max -8340.20 -2719.05 -84.43 2891.00 9400.59 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 6626.30 2023.44 3.275 0.00157 ** x 512.85 43.41 11.814 < 2e-16 *** --Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1 Residual standard error: 3716 on 79 degrees of freedom Multiple R-Squared: 0.6385, Adjusted R-squared: 0.634 F-statistic: 139.6 on 1 and 79 DF, p-value: < 2.2e-16 Per calcolare i valori stimati, si può anche far uso del comando "predict", che però richiede come secondo argomento un oggetto di tipo "data.frame", anche per predire un solo valore: > ystim<-predict(retta,data.frame(x)) > predict(retta,data.frame(x=27)) [1] 20473.28 > predict(retta,data.frame(x=c(27,62))) 1 2 20473.28 38423.07 opzioni grafico Poiché l’oggetto che restituisce il comando “lm” contiene le stime dei due parametri, questi può essere inserito come primo argomento nel comando “abline”: > plot(x,y,xlab="età",ylab="reddito",main="grafico reddito-età") > abline(retta,lty=3,lwd=5,col="red") > text(40,40000,"la retta di regressione") > text(40,38000,expression(y[i]==hat(beta)[0]+hat(beta)[1]*x)) 40000 grafico reddito-età la retta di regressione ^ +β ^ x y=β 0 1 30000 25000 20000 reddito 35000 i 56 30 40 50 età 60 Gli argomenti “lty”, “lwd” e “col” definiscono, rispettivamente, il tipo di tratteggio, lo spessore e il colore del tratto. Il comando “text” aggiunge testi e notazioni a grafici preesistenti; vuole in input le coordinate del punto in cui inserire il testo, quindi il testo. Il comando “expression”, all’interno di “text”, consente di scrivere formule e simboli matematici, il cui elenco si può visionare consultando l’help di “plotmath”: > help(plotmath) A volte si rende necessario ampliare o ridurre il range di ciascun asse cartesiano. All’interno del comando “plot” ciò è possibile con le opzioni “xlim” e “ylim”, che per default considerano l’intero range dei due vettori in input (in questo caso x e y): 30000 50000 y 30000 10000 20000 25000 y 35000 70000 40000 > op<-par(mfrow=c(1,2)) > plot(x,y,xlim=range(x),ylim=range(y)) > plot(x,y,xlim=c(10,100),ylim=c(10000,80000)) > par(op) 30 40 50 x 60 20 40 60 80 x E’ possibile costruire a proprio piacimento gli assi. In tal caso, aggiungere l’opzione ‘’axes=FALSE’’ all’interno del comando ‘’plot’’ e utilizzare i comandi ‘’axis(1)’’ e ‘’axis(2)’’ per costruire, rispettivamente, l’asse X e l’asse Y. Gli altri argomenti di “axis” sono due vettori: il primo visualizza delle tacche sull’asse, il secondo visualizza dei valori in corrispondenza delle tacche tracciate. Il comando “expression”, già incontrato all’interno del comando “text”, e qui inserito all’interno del comando “axis”, consente di visualizzare un’espressione in corrispondenza di una determinata coordinata, in questo caso Mx prima ed My poi. Il comando ‘’box()’’, infine, racchiude il grafico in un riquadro: > plot(x,y,axes=FALSE) > sequenzax<-seq(20,70,10) > axis(1,c(mx,sequenzax),c(expression(bar(x)),sequenzax)) > sequenzay<-seq(19000,45000,5000) > axis(2,c(my,sequenzay),c(expression(bar(y)),sequenzay)) > box() 57 44000 39000 34000 yi = 6626.304 + 512.851xi 19000 24000 y 29000 y (xn, yn) 30 40 x 50 60 x Volendo tracciare dei segmenti paralleli ai due assi, che si incontrano nel punto di coordinate (Mx, My) si può procedere nel seguente modo: > lines(c(mx,mx,0),c(0,my,my),lty=3) > text(46,31000,expression((list(bar(x)[n],bar(y)[n])))) > points(mx,my,pch=4,cex=3,col="red") Il comando “points”, che è l’unico non ancora analizzato, consente di evidenziare determinati punti su un grafico preesistente. Le opzioni “pch” e “cex” consentono di scegliere, rispettivamente, il tipo di simbolo e la sua dimensione. I seguenti comandi tracceranno la retta e definiranno la sua espressione: > abline(retta,col="yellow",lwd=2) > text(40,38000,expression(y[i]==6626.304+512.851*x[i])) Val la pena, infine, di provare la seguente istruzione, che restituisce n.4 grafici utili per l’analisi dei residui: > plot(retta) 3.3 La dipendenza in media: il rapporto di correlazione data(chickwts); z<-chickwts; attach(z); x<-feed; y<-weight e<-seq(100,450,50) y2<-cut(y,breaks=e) tab<-table(x,y2) xt<-margin.table(tab,1); yt<-margin.table(tab,2) yc<-hist(y,plot=FALSE)$mids mc<-numeric() for (i in 1:6) mc[i]<-weighted.mean(yc,tab[i,]) # mc: contiene le medie condizionate di Y|X varmc<-weighted.mean(mc^2,xt)-(weighted.mean(mc,xt))^2 vary<-weighted.mean(yc^2,yt)-(weighted.mean(yc,yt))^2 eta2<-varmc/vary 58 MODULO 2 59 4 Calcolo delle probabilità con R 4.1 Esperimenti casuali Consideriamo il lancio di un dado regolare. Lo spazio campionario Ω ha cardinalità card(Ω)=6 ed è costituito dai seguenti eventi elementari: Ω = {1, 2, 3, 4, 5, 6}. Attribuiamo tali eventi ad un oggetto: > dado<-1:6 > dado [1] 1 2 3 4 5 6 Il comando “sample” consente di simulare n prove di un esperimento casuale, ad esempio, n lanci di un dado regolare. Ha come argomenti: Ω, n, l’opzione “replace” che, se posta uguale a “TRUE”, consente di replicare lo stesso risultato: > sample(dado,6) [1] 5 3 1 2 6 4 > sample(dado,20) Error in sample(length(x), size, replace, prob) : can't take a sample larger than the population when replace = FALSE > sample(dado,20,replace=TRUE) [1] 5 5 5 6 2 3 2 2 5 1 6 4 4 5 4 1 3 5 5 5 Il secondo comando dà, ovviamente, errore, in quanto n supera card(Ω) e l’opzione di default “replace = FALSE” non prende in considerazione risultati già ottenuti. 4.2 Calcolo combinatorio Per calcolare le permutazioni semplici di n oggetti Pn=n!, si può utilizzare il comando “prod”. Il fattoriale dei primi 7 numeri naturali, ad esempio, si ottiene con il seguente comando: > prod(1:7) [1] 5040 E’ noto che fra il fattoriale di un numero e la funzione gamma esiste la seguente relazione: n! = Γ(n+1), per cui un comando equivalente al precedente è: > gamma(8) [1] 5040 Se si vuole calcolare il logaritmo (log) di una gamma è possibile utilizzare direttamente la funzione “lgamma”, per cui i seguenti comandi sono equivalenti: > log(gamma(8)) [1] 8.525161 > lgamma(8) 60 [1] 8.525161 Ovviamente, se consideriamo la funzione inversa (exp), ritorniamo al risultato precedente: > exp(lgamma(8)) [1] 5040 Per n>170, non è possibile lavorare con i fattoriali. Eseguiamo, allora, i calcoli in scala logaritmica, ma utilizzando la funzione “lgamma”: > prod(1:171) [1] Inf > gamma(172) [1] Inf > log(gamma(172)) [1] Inf > lgamma(172) [1] 711.7147 ⎛ n⎞ n! Per calcolare il numero delle combinazioni semplici C n ,k = ⎜⎜ ⎟⎟ = di n oggetti distinti di ⎝ k ⎠ k!(n − k )! classe k (coefficiente binomiale), si può utilizzare il comando “choose”, che richiede, nell’ordine, n e k. Ad esempio: > choose(5,3) [1] 10 4.3 Valore atteso e varianza di variabili casuali Se X ed Y sono due variabili casuali, con funzione di distribuzione di probabilità, rispettivamente, p(x) e p(y), ed a e b sono due costanti, è noto che: E(a)=a var(a)=0 E(aX)=a E(X) var(aX)=a2var(X) E(aX +bY)=aE(X)+bE(Y) var(aX+bY)=a2var(X)+b2var(Y)+2abcov(X,Y) dove: E(X)=Σxp(x) var(X)=Σ[x-E(X)]2p(x)=E(X2)-[E(X)]2 E(X2)=Σx2p(x) E(Y)=Σyp(y) var(Y)=Σ[y-E(Y)]2p(y)=E(Y2)-[E(Y)]2 E(Y2)=Σy2p(y) cov(X,Y)= ΣΣ[x-E(X)][x-E(X)]p(x,y)=E(XY)-E(X)E(Y) E(XY)= ΣΣxyp(x,y) Se X e Y sono indipendenti, p(x,y)= p(x)p(y), allora cov(X,Y)=0. 61 esempio Sia P0 il prezzo di un titolo a inizio di un anno solare e P il prezzo dello stesso titolo a fine anno. Il suo rendimento R sarà: R=(P-P0)/P0; si vuole calcolare il rendimento atteso e la varianza: E(R)=(E(P)-P0)/P0 var(R)=var(P)/P02 Supponiamo nota la distribuzione di probabilità (pr) della variabile casuale P (p), il valore atteso (EP) e la varianza (varP) di P saranno : > p<-c(21,23.5,26,32,43) > pr<-c(0.1,0.25,0.3,0.25,0.1) > EP<-sum(p*pr) > EP [1] 28.075 > varP<-sum(((p-EP)^2)*pr) > varP [1] 37.65687 Se il prezzo iniziale del titolo (P0) è pari a 20 euro, il rendimento medio (ER) e la varianza (varR) saranno: > P0<-20 > ER<-(EP-P0)/P0 > ER [1] 0.40375 > varR<-varP/P0^2 > varR [1] 0.09414219 E‘ noto che un modo per ridurre il rischio di un investimento consiste nella diversificazione del portafoglio, ossia nell‘acquisto di un insieme di attività finanziarie (titoli, azioni, fondi) con caratteristiche differenti. L‘obiettivo è quello di massimizzare il rendimento atteso, minimizzando nello stesso tempo il rischio. A tal fine viene assegnato a ciascun investimento un coefficiente di ponderazione, che corrisponde alla quota del portafoglio destinata a quella particolare attività. Supponiamo di aver scelto due attività; il rendimento Rp del portafoglio sarà: Rp=aRx+bRy, dove a+b=1. Supponiamo che per ciascuno dei due investimenti sono stati stimati i rendimenti Rx e Ry (per ogni 1000$ di capitale investito), sotto 3 diverse condizioni economiche (recessione, stabilità, espansione), cui sono associate le seguenti probabilità di verificarsi: 62 Rx / Ry -100 100 250 tot -200 0,2 50 350 0,5 0,2 0,5 0,3 0,3 tot 0,2 0,5 0,3 1 Costruiamo con R la distribuzione di probabilità congiunta e determiniamo le distribuzioni di probabilità marginali: > Rx<-c(-100,100,250) > Ry<-c(-200,50,350) > pRxRy<-matrix(rep(0,9),3,3) > pRxRy[1,1]<-0.2 > pRxRy[2,2]<-0.5 > pRxRy[3,3]<-0.3 > rownames(pRxRy)<-Rx > colnames(pRxRy)<-Ry > pRxRy -200 50 350 -100 0.2 0.0 0.0 100 0.0 0.5 0.0 250 0.0 0.0 0.3 > sum(pRxRy) [1] 1 > margin.table(pRxRy,1) -100 100 250 0.2 0.5 0.3 > margin.table(pRxRy,2) -200 50 350 0.2 0.5 0.3 Per determinare E(Rp) e var(Rp), costruiamo la seguente funzione, che calcola il valore atteso e la varianza di una combinazione lineare di variabili casuali: > mvcl<-function (a, x, y, pxy) { + px <- margin.table(pxy,1) + py <- margin.table(pxy,2) + mx <- sum(x * px) + my <- sum(y * py) + vx <- sum((x - mx)^2 * px) + vy <- sum((y - my)^2 * py) + cxy <-sum(x%*%t(y)*pxy)-mx*my + # oppure (cfr.par.boh) + # cxy <-sum(x%o%y*pxy)-mx*my + mr <- a * mx + (1 - a) * my + vr <- a^2 * vx + (1 - a)^2 * vy + 2 * a * (1 - a) * cxy + return(list(ER = mr, VR = vr)) +} 63 La funzione “mvcl” vuole in input il coefficiente di ponderazione, le due variabili casuali e la distribuzione di probabilità congiunta. Il comando “return” restituisce una lista (list) di oggetti, nel nostro caso il valore atteso e la varianza della combinazione lineare, cui è stato dato il nome “ER” e “VR”. Se supponiamo di voler formare un portafoglio destinando a ciascun investimento la stessa quota del totale a=b=1-a=0.5, E(Rp) e var(Rp) saranno: > a<-0.5 > ris<-mvcl(a,Rx,Ry,pRxRy) > ris $ER [1] 97.5 $VR [1] 24806.25 Notiamo che il rischio di portafoglio sarà più elevato del rendimento atteso, infatti è: > sqrt(ris$VR) [1] 157.5 Se a è un vettore, la funzione “mvcl” restituirà una lista che ha come elementi dei vettori: > a<-seq(0,1,0.1) >a [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 > ris<-mvcl(a,Rx,Ry,pRxRy) > ris $ER [1] 90.0 91.5 93.0 94.5 96.0 97.5 99.0 100.5 102.0 103.5 105.0 $VR [1] 37900.00 35040.25 32301.00 29682.25 27184.00 24806.25 22549.00 20412.25 [9] 18396.00 16500.25 14725.00 I seguenti grafici mostrano il rendimento atteso al variare di a, considerando diverse opzioni per “type”: > par(mfrow=c(3,2)) > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="p") > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="h") > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="b") > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="c") > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="o") > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="l") 64 E(Rp) 0.2 0.4 0.6 0.8 1.0 0.0 0.6 0.8 rendimento medio 1.0 E(Rp) 0.2 0.4 0.6 0.8 90 95 105 rendimento medio 90 95 1.0 0.0 0.2 0.4 0.6 0.8 a rendimento medio rendimento medio 1.0 90 95 E(Rp) 105 a 0.0 0.2 0.4 0.6 0.8 1.0 90 95 E(Rp) 0.4 a 105 0.0 E(Rp) 0.2 a 105 0.0 90 95 90 95 E(Rp) 105 rendimento medio 105 rendimento medio 0.0 0.2 0.4 0.6 a 0.8 1.0 a E’ interessante anche vedere come varia la varianza al variare di a: > par(mfrow=c(1,2)) > plot(a,ris$ER,ylab="E(Rp)",main="rendimento medio",type="b") > plot(a,ris$VR,ylab="var(Rp)",main="varianza del rendimento",type="b") varianza del rendimento 90 25000 15000 20000 95 E(Rp) var(Rp) 100 30000 35000 105 rendimento medio 0.0 0.4 0.8 0.0 a 0.4 0.8 a 4.4 Variabili casuali discrete 4.4.1 v.c. binomiale La variabile casuale binomiale ha, come è noto, funzione di distribuzione di probabilità: ⎛ n⎞ p( x) = P( X = x) = ⎜⎜ ⎟⎟ p x (1 − p) n − x ⎝ x⎠ x= 0, 1, 2, …, n E(X)=np var(X)=np(1-p) Supponiamo che X ~ Bin(n=7,p=0.4). Si vogliono calcolare le seguenti probabilità: 65 - p(4)=P(X=4) - F(4)=P(X≤4) - P(X>4)=1- P(X≤4)=1-F(4) Le probabilità puntuali si calcolano in R premettendo il suffisso ‘’d’’ al nome della variabile, mentre il valore della funzione di ripartizione in un punto si calcola premettendo il suffisso ‘’p’’: > dbinom(4,7,0.4) [1] 0.193536 > pbinom(4,7,0.4) [1] 0.903744 > pbinom(4,7,0.4,lower.tail=FALSE) [1] 0.096256 I comandi “dbinom” e “pbinom” vogliono in input: il valore x, n e p. L’opzione “lower.tail=FALSE”, come si è visto, è servita a calcolare probabilità complementari. Volendo calcolare i quantili q di una variabile, è necessario premettere al nome della variabile il suffisso “q”. Ad esempio, rappresentiamo graficamente la v.c. X ~ Bin(n=10, p=0.5). Ricorriamo al comando “plot”, già noto, scegliendo l’opzione type=”h”. Per calcolare le probabilità puntuali utilizziamo il comando “dbinom”: 0.00 0.05 0.10 0.15 0.20 0.25 px > x<-0:10 > px<-dbinom(x,10,0.5) > plot(x,px,type="h") 0 2 4 6 8 10 x Come ci aspetteremmo, è: > qbinom(0.5,10,0.5) [1] 5 Il comando per calcolare i quantili vuole in input dapprima il valore di α, dove α= P(X≤ q), quindi i parametri della distribuzione in esame. 4.4.2 v.c. bernoulliana La variabile casuale bernoulliana ha funzione di distribuzione di probabilità: 66 p( x) = P( X = x) = p x (1 − p)1− x x= 0, 1 E(X)=p var(X)=p(1-p) Sappiamo che X ~ Ber(p) ~Bin(n=1,p). Supponiamo che X ~ Ber(p=0.7). Si vogliono calcolare le seguenti probabilità: - p(1)=P(X=1) - F(0)=P(X≤0) Possiamo utilizzare gli stessi comandi utilizzati in precedenza, dando ad n valore 1: > dbinom(1,1,0.7) [1] 0.7 > pbinom(0,1,0.7) [1] 0.3 4.4.3 v.c. geometrica La variabile casuale geometrica o di Pascal8, ha funzione di distribuzione di probabilità: p ( x) = P ( X = x) = p(1 − p ) x x= 0, 1, 2, … E(X)=(1-p)/p var(X)=(1-p)/p2 Rappresentiamo graficamente la v.c. X ~ Geom(p=1/7): 0.08 0.04 px 0.12 > x<-0:10 > px<-dgeom(x,1/7) > plot(x, px, type="h") 0 2 4 6 8 10 x Se vogliamo che tutti i valori di X considerati vengano rappresentati, costruiamo noi gli assi, aggiungendo in “plot” l’opzione “ axes=FALSE ” e ricorrendo al comando “axis”: > plot(x, px, type="h", axes=FALSE) > axis(1,x) NULL > axis(2) NULL > box() 8 v.c. “tempo di attesa (in termini di numero di insuccessi) prima di ottenere il I successo” 67 0.12 0.08 0.04 px 0 1 2 3 4 5 6 7 8 9 10 x Ricordiamo che la v.c. geometrica gode di un’importante proprietà: la mancanza di memoria. Osservati t insuccessi, la probabilità di aspettare ancora s insuccessi prima del I successo è: P(X ≥ t+s| X ≥ t)=P(X ≥ s) 4.4.4 v.c. binomiale negativa La variabile casuale binomiale negativa9, ha funzione di distribuzione di probabilità: ⎛ x + n − 1⎞ n ⎟⎟ p (1 − p) x p ( x) = P( X = x) = ⎜⎜ ⎠ ⎝x E(X)=n(1-p)/p x= 0, 1, 2, … n=1,2,... var(X)=n(1-p)/p2 Supponiamo che X ~ BinNeg(n=3, p=0.4). Si vogliono calcolare le seguenti probabilità: - P(X=2) - P(X≤2) - P(X>2) Il comando è ‘’nbinom’’, cui si premette il suffisso opportuno: > dnbinom(2,3,0.4) [1] 0.13824 > pnbinom(2,3,0.4) [1] 0.31744 > pnbinom(2,3,0.4,lower.tail=FALSE) [1] 0.68256 Ovviamente X ~ Geom(p) ~ BinNeg(n=1, p). Infatti, ad esempio, per X=4 e p=0.4, si ha: > dgeom(4,0.4) [1] 0.05184 > dnbinom(4,1,0.4) 9 v.c. “tempo di attesa (in termini di numero di insuccessi) per ottenere l’n-mo successo” 68 [1] 0.05184 4.4.5 v.c. ipergeometrica La variabile casuale ipergeometrica ha funzione di distribuzione di probabilità: ⎛ N − K ⎞⎛ K ⎞ ⎜⎜ ⎟⎟⎜⎜ ⎟⎟ ⎝ n − x ⎠⎝ x ⎠ p ( x) = P ( X = x) = ⎛N⎞ ⎜⎜ ⎟⎟ ⎝n ⎠ E(X)=np con var(X)=np(1-p) max(0,n-(N-K)) ≤ x≤min(n,K) N −n . N −1 Supponiamo che X ~ Iperg(N=100,K=30,n=10). Si vogliono calcolare le seguenti probabilità: - P(X=3) - P(X≤ 3) I comandi sono, rispettivamente, i seguenti : > dhyper(3,30,70,10) [1] 0.2811634 > phyper(3,30,70,10) [1] 0.65402 Come si può notare, i suddetti comandi richiedono in input, dopo il valore di X, K, N-K ed n. 4.4.6 v.c. di Poisson La variabile casuale di Poisson ha funzione di distribuzione di probabilità: p ( x) = P ( X = x) = µ x e −µ x! x= 0, 1, 2, … E(X)=var(X)=µ Supponiamo che X ~ Poi(µ=7). Si vogliono calcolare le seguenti probabilità: - P(X=3) - P(X≤3) Le istruzioni sono le seguenti: > dpois(3,7) [1] 0.05212925 > ppois(3,7) [1] 0.08176542 69 E’ noto che la distribuzione di Poisson si ottiene come distribuzione limite della distribuzione binomiale, quando n→∞ e p→0 con la stessa velocità, in modo tale che µ=np si mantenga costante. La v.c. di Poisson descrive perciò eventi rari, con probabilità di successo molto basse. Rappresentiamola graficamente: 0.00 0.05 px 0.10 0.15 > x<-0:25 > px<-dpois(x,7) > plot(x,px,type="h") 0 5 10 15 20 25 x La v.c. di Poisson si presta bene anche a descrivere il numero di realizzazioni di un evento aleatorio in un determinato intervallo di tempo. Supponiamo, ad esempio, che il numero medio di telefonate ad un centralino sia di 15 per ora (µ=15). Calcoliamo: - la prob. che in 10 min. non arrivino chiamate; - la prob. che in 30 min. si abbiano al più 8 chiamate > dpois(0,15/60*10) [1] 0.082085 > ppois(30,15/60*8) [1] 1 4.5 Variabili casuali continue 4.5.1 v.c. normale o di Gauss La variabile casuale normale ha funzione di densità di probabilità: f ( x) = 1 σ 2π − e ( x − µ )2 2σ 2 -∞< x <∞ µ>0 σ>0 E(X)=µ var(X)=σ2 E’ noto che per una v.c. continua è P(X=x)=0. In tal caso, il prefisso “d” al nome della variabile serve a calcolare il valore della funzione nel punto x. Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della gaussiana sono: > dnorm(x, µ,σ) > pnorm(x, µ,σ) > qnorm(α, µ,σ) 70 I valori di default di µ e σ sono, rispettivamente, 0 e 1, quindi, se omettiamo tali parametri, R calcolerà la densità, la funzione di ripartizione e i quantili della normale standard f(z), con X −µ Z= : σ > dnorm(z) > pnorm(z) > qnorm(α) Per rappresentare graficamente una funzione, possiamo utilizzare il comando “curve”, seguito dal nome della funzione e dal range di X sul quale si vuole rappresentare la funzione. Rappresentiamo graficamente una normale standard: 0.2 0.0 0.1 dnorm(x) 0.3 0.4 > curve(dnorm(x),-4,4) -4 -2 0 2 4 x Volendo rappresentare più funzioni nello stesso grafico, bisogna riutilizzare il comando “curve”, aggiungendo l’opzione “add=TRUE”. Le opzioni xlab="", ylab="", invece, servono ad eliminare le etichette agli assi. Rappresentiamo due curve normali con diversa media e uguale varianza: 0.00 0.02 0.04 0.06 0.08 0.10 0.12 > curve(dnorm(x),-4,4) > curve(dnorm(x,5,3),-10,30,ylab="") > curve(dnorm(x,15,3),-10,30,add=TRUE) > axis(1,c(5,15),c(expression(mu==5),expression(mu==15))) > abline(v=5) > abline(v=15) -10 0 µ=5 10 µ = 15 20 30 x 71 Il comando “abline”, già incontrato, nell’ambito della regressione, per tracciare una retta generica nel piano, consente qui di tracciare due rette parallele all’asse y, in corrispondenza dei valori di µ. A tal fine, basta specificare l’opzione “v=costante”. Viceversa, se si vuole tracciare una retta parallela all’asse x, bisogna specificare l’opzione “h=costante”. Rappresentiamo adesso due curve normali con uguale media, ma diversa varianza: 0.15 σ=3 0.00 0.05 σ=2 0.10 0.20 > curve(dnorm(x,5,3),-10,20,ylim=c(0,0.2),ylab="") > curve(dnorm(x,5,2),-10,20,add=TRUE) > text(10,0.15,expression(sigma==2)) > text(10,0.10,expression(sigma==3)) -10 -5 0 5 10 15 20 x Le opzioni “ylim” e “lty” all’interno del comando “curve” hanno la stessa funzione incontrata per altri comandi, ossia definiscono, rispettivamente, il range dell’asse Y e il tipo di tratteggio: 0.10 0.15 0.20 > curve(dnorm(x,5,3),-10,20,ylim=c(0,0.2),ylab="",lty=3) > curve(dnorm(x,5,2),-10,20,add=TRUE,lty=5) > legend(10,0.10,c(expression(sigma==3),expression(sigma==2)),lty=c(3,5)) 0.00 0.05 σ=3 σ=2 -10 -5 0 5 10 15 20 x Il comando “legend” consente di inserire una legenda all’interno di un grafico. Vuole in input: le coordinate del punto in cui si vuole inserire la legenda, un vettore di caratteri alfanumerici (qui è stato usato il comando “expression” per inserire espressioni), un vettore di colori (col) o di simboli (pch) o di diversi tratteggi (lty), come in questo caso. Per maggiori dettagli sull’uso di questo comando, si rimanda all’help on-line. Vediamo adesso come è possibile evidenziare una parte di area sottesa da una curva. 72 I comandi che seguono sono tutti noti, tranne “polygon”, che consente di unire punti, formando appunto un poligono. Il comando “polygon” ha come argomenti: due vettori contenenti le coordinate dei punti, la densità e l’angolazione del tratteggio all’interno del poligono, oppure il colore. Tratteggiamo, ad esempio, le code di una curva normale standard; in particolare, tratteggiamo le aree in corrispondenza dei valori di z interni agli intervalli (-∞,-1], [1,+∞): > curve(dnorm(x),-3,3,axes=FALSE,ylab="",xlab="",ylim=c(0,.5)) > axis(1,c(-3,-1,0,1,3),c("","-z",0,"z","")) > # coda sinistra > cod<-seq(-3,-1,length=100) > x<-c(-3,cod,-1,-3) > y<-c(0,dnorm(cod),0,0) > polygon(x,y,20,45) > # coda destra > cod<-seq(1,3,length=100) > x<-c(1,cod,3,1) > y<-c(0,dnorm(cod),0,0) > polygon(x,y,20,45) > abline(h=0) > text(0,.47,expression(F(-z)==1-F(z))) > lines(c(0,0),c(0,dnorm(0))) > box() F(− z) = 1 − F(z) -z 0 z Coloriamo ora l’area sottesa da una curva normale standard, in corrispondenza dei valori di z interni all’intervallo [-1, 1]: > curve(dnorm(x),-3,3,axes=FALSE,ylab="",xlab="z",ylim=c(0,.5)) > axis(1,c(-3,-1,0,1,3),c("","-1",0,"1","")) > vals<-seq(-1,1,length=100) > x<-c(-1,vals,1,-1) > y<-c(0,dnorm(vals),0,0) > polygon(x,y,col="red") > abline(h=0) > text(0,.47,expression(P(-1<Z<1))) > box() 73 P(-1<Z<1) -1 0 1 z Supponiamo adesso che X ~ N(5,3). Calcoliamo le seguenti probabilità, a tutti note: - P(µ-σ<X<µ+σ) ~ P(-1<Z<1) - P(µ-2σ<X<µ+2σ) ~ P(-2<Z<2) - P(µ-3σ<X<µ+3σ) ~ P(-3<Z<3) > m<-5 > s<-sqrt(3) > pnorm(m+s,m,s)-pnorm(m-s,m,s) [1] 0.6826895 > pnorm(1)-pnorm(-1) [1] 0.6826895 > pnorm(m+2*s,m,s)-pnorm(m-2*s,m,s) [1] 0.9544997 > pnorm(2)-pnorm(-2) [1] 0.9544997 > pnorm(m+3*s,m,s)-pnorm(m-3*s,m,s) [1] 0.9973002 > pnorm(3)-pnorm(-3) [1] 0.9973002 Il quantile in corrispondenza di α=0.5 sarà ovviamente µ: > qnorm(.5,m,s) [1] 5 > qnorm(.5) [1] 0 4.5.2 v.c. uniforme La variabile casuale uniforme ha funzione di densità di probabilità: 1 f ( x) = b−a a+b E( X ) = 2 a≤ x ≤ b 74 2 ( b − a) var( X ) = 12 Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. uniforme sono: > dunif(x, a, b) > punif(x, a, b) > qunif(α, a, b) Rappresentiamo graficamente la v.c. corrispondenza di α=0.5: X ~ U(a=2, b=5), calcoliamo F(3.5) e il quantile in > curve(dunif(x,2,5),0,7,ylim=c(0,.8)) > punif(3.5,2,5) [1] 0.5 > qunif(0.5,2,5) [1] 3.5 4.5.3 v.c. chi-quadrato La variabile casuale Chi-quadrato ha funzione di densità di probabilità: 1 f ( x) = n 2 2 Γ(n / 2) x n / 2 −1e − x / 2 x≥ 0 E(X)=n var(X)=2n La funzione gamma ∞ Γ(a)= ∫ x α −1 e − x dx 0 gode, come è noto, della seguente proprietà: Γ(a+1)= aΓ(a) con a∈R+ Ricordiamo anche che: Γ(1/2)= π : > gamma(1/2) [1] 1.772454 > sqrt(pi) [1] 1.772454 E’ noto che se Xi i.i.d. N(µ ,σ2), allora ΣiZ i 2 ~χ 2(n), dove Z i = Xi − µ σ . Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. Chiquadrato sono: > dchisq(x, n) > pchisq(x, n) 75 > qchisq(α, n) Rappresentiamo graficamente una v.c. X ~χ 2(n); la v.c. X è asimmetrica positivamente e tenderà alla gaussiana al crescere dei gradi di libertà (n→∞): 0.15 0.20 0.25 > curve(dchisq(x,3),0,20,ylab="") > curve(dchisq(x,5),0,20,add=TRUE,lty=2) > curve(dchisq(x,7),0,20,add=TRUE,lty=3) > curve(dchisq(x,9),0,20,add=TRUE,lty=5) > legend(10,0.2,c("n=3","n=5","n=7","n=9"),lty=c(1,2,3,5)) 0.00 0.05 0.10 n=3 n=5 n=7 n=9 0 5 10 15 20 x 4.5.4 v.c. t di Student La variabile casuale t di Student ha funzione di densità di probabilità: x2 ⎞ Γ((n + 1) / 2) ⎛ ⎜⎜1 + ⎟ f ( x) = n ⎟⎠ πnΓ(n / 2) ⎝ se n>2 − ( n +1) / 2 -∞< x <∞ Se Z ~ N(0,1) è indipendente da Y ~ χ 2(n), allora Z Y n E(X)=0, var(X)=n/(n-2) ~ t(n) . Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. t di Student sono: > dt(x, n) > pt(x, n) > qt(α, n) La distribuzione t è simmetrica e platicurtica rispetto alla gaussiana; per n→ ∞, t(n)→ N: > curve(dnorm(x),-5,5,ylab="") 76 0.3 0.4 > curve(dt(x,1),lty=3,ylab="",add=TRUE) > legend(2,0.3,c("Z","t"),lty=c(1,3)) 0.0 0.1 0.2 Z t -4 -2 0 2 4 x 4.5.5 v.c. F La variabile casuale F ha funzione di densità di probabilità: f ( x) = Γ((n + m ) / 2 ) ⎛ n ⎞ ⎜ ⎟ Γ(n / 2)Γ(m / 2 ) ⎝ m ⎠ E(X)=m/(m-2) n/2 n ⎞ ⎛ x n / 2 −1 ⎜1 + x ⎟ m ⎠ ⎝ se m>2, var(X)= Se Y ~ χ 2(n) e W ~ χ 2(m), allora − (n + m ) / 2 x≥0 2m 2 (n + m − 2) n(m − 2) (m − 4) 2 se m>4 Y /n ~ F(n,m) . W /m Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. F sono: > df(x, n, m) > pf(x, n, m) > qf(α, n, m) Rappresentiamo graficamente una v.c. X~ F(3,2): 0.0 0.1 0.2 0.3 0.4 0.5 0.6 df(x, 3, 2) > curve(df(x,3,2),0,2) 0.0 0.5 1.0 1.5 2.0 x 77 4.5.6 v.c. esponenziale La variabile casuale esponenziale ha funzione di densità di probabilità: f ( x ) = λ e − λx E(X)=1/λ x>0 var(X)=1/λ2 Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. esponenziale sono: > dexp(x, λ) > pexp(x, λ) > qexp(α,λ) Poichè: - Y ~ Poi(µ) conta il n. di realizzazioni di un evento aleatorio in un intervallo di tempo; - X ~ Exp(λ) misura il tempo che intercorre tra due di tali eventi successivi (X v.c. tempo d'attesa continua per la realizzazione successiva dell’evento), allora P(Y=0)=P(X>1): > dpois(0,5) [1] 0.006737947 > pexp(1,5,lower.tail=FALSE) [1] 0.006737947 in poche parole, dire che nell’intervallo di tempo unitario non si verificano eventi, vuol dire che il primo evento si verifica dopo un’unità di tempo 4.5.7 v.c. gamma La variabile casuale gamma10 ha funzione di densità di probabilità: f ( x) = 1 a a −1 −λx λ x e Γ(a ) x≥0, a >0, λ>0 E(X)= a /λ var(X)= a /λ2 Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. gamma sono: > dgamma(x, a, λ) > pgamma(x, a, λ) > qgamma(α, a, λ) E’ noto che : X ~ G(1, λ) ~ Exp(λ) 10 v.c. tempo di attesa continua per la realizzazione n-ma di un evento aleatorio 78 3.0 1.5 0.0 dgamma(x, 1, 3) > par(mfrow=c(2,1)) > curve(dgamma(x,1,3),0,3) > curve(dexp(x,3),0,3) > dgamma(1,1,3) [1] 0.1493612 > dexp(1,3) [1] 0.1493612 0.0 0.5 1.0 1.5 2.0 2.5 3.0 2.0 2.5 3.0 3.0 1.5 0.0 dexp(x, 3) x 0.0 0.5 1.0 1.5 x X ~ G(n/2, 1/2) ~ χ 2(n) 0.00 0.10 dgamma(x, 2, 1/2) > curve(dgamma(x,2,1/2),0,10) > curve(dchisq(x,4),0,10) > dgamma(2,2,1/2) [1] 0.1839397 > dchisq(2,4) [1] 0.1839397 0 2 4 6 8 10 6 8 10 0.00 0.10 dchisq(x, 4) x 0 2 4 x Se a→ ∞, G(a, λ)→ N(a /λ, a /λ2) > par(mfrow=c(1,1)) > curve(dgamma(x,1,1),0,10,ylab="",main="densità gamma") > curve(dgamma(x,2,1),lty=2,add=TRUE) > curve(dgamma(x,3,1),lty=3,add=TRUE) > legend(7,0.8,c("a=1","a=2","a=3"),lty=c(1,2,3)) 79 0.8 1.0 densità gamma 0.0 0.2 0.4 0.6 a=1 a=2 a=3 0 2 4 6 8 10 x 4.5.8 v.c. beta La variabile casuale beta ha funzione di densità di probabilità: f ( x) = 1 b −1 x a −1 (1 − x ) Beta(a, b ) 0≤ x ≤1 a >0, b >0 La funzione beta può essere definita in termini della funzione gamma: Beta(a,b)= Γ(a )Γ(b ) 1 a −1 b −1 = ∫ x (1 − x ) dx 0 Γ(a + b ) dunque è: > beta(1,1) [1] 1 > gamma(1)*gamma(1)/gamma(2) [1] 1 Le istruzioni per determinare la densità, la funzione di ripartizione e i quantili della v.c. beta sono: > dbeta(x, a,b) > pbeta(x, a,b) > qbeta(α, a,b) Rappresentiamo graficamente la distribuzione beta al variare di a e b: > par(mfrow=c(3,2)) > curve(dbeta(x,1,1),0,1,ylim=c(0,3),ylab="",main= "a=b=1") > curve(dbeta(x,.1,.1),0,1,ylim=c(0,3),ylab="",main= "a<1,b<1") > curve(dbeta(x,.1,1),0,1,ylim=c(0,3),ylab="",main= "a<1") > curve(dbeta(x,1,.1),0,1,ylim=c(0,3),ylab="",main= "b<1") > curve(dbeta(x,2,2),0,1,ylim=c(0,3),ylab="",main="a=b=2" ) > curve(dbeta(x,4,4),0,1,ylim=c(0,3),ylab="",main="a=b=4") 80 0.0 2.5 a<1,b<1 0.0 2.5 a=b=1 x x a<1 b<1 0.0 0.0 2.5 0.0 0.2 0.4 0.6 0.8 1.0 2.5 0.0 0.2 0.4 0.6 0.8 1.0 x x a=b=2 a=b=4 0.0 2.5 0.0 0.2 0.4 0.6 0.8 1.0 0.0 2.5 0.0 0.2 0.4 0.6 0.8 1.0 0.0 0.2 0.4 0.6 0.8 1.0 0.0 0.2 0.4 0.6 0.8 1.0 x x Nei casi in cui a è diverso da b, i parametri determinano l'asimmetria della densità: > par(mfrow=c(2,1)) > curve(dbeta(x,2,4),0,1,ylim=c(0,3),ylab="",main="a=2,b=4") > curve(dbeta(x,4,2),0,1,ylim=c(0,3),ylab="",main="a=4,b=2") 0.0 2.5 a=2,b=4 0.0 0.2 0.4 0.6 0.8 1.0 0.8 1.0 x 0.0 2.5 a=4,b=2 0.0 0.2 0.4 0.6 x 4.6 Simulazione di variabili casuali R, oltre a disporre di funzioni per il calcolo di densità, funzioni di ripartizione e quantili, dispone anche di una serie di funzioni che consentono di generare realizzazioni di variabili casuali. A tal fine, il prefisso da premettere al nome della variabile casuale è “r”: rbinom(r,n,p) rgeom(r,p) rnbinom(r,n,p) rhyper(r,K,N-K,n) 81 rpois(r,µ) rnorm(r,µ,σ) runif(r,a,b) rchisq(r,n) rt(r,n) rf(r,n,m) rexp(r,λ) rgamma(r,a,λ) rbeta(r,a,b) dove l’argomento “r” è il numero di replicazioni. Proviamo a generare r=1000 replicazioni da una v.c. Z ∼ N(0,1) e ad osservarne il comportamento; costruiamo l’istogramma, quindi sovrapponiamo ad esso i grafici della densità stimata e della densità vera: > x<-rnorm(1000) > hist(x,freq=FALSE) > lines(density(x),lty=2) > curve(dnorm(x),add=TRUE) 0.2 0.0 0.1 Density 0.3 0.4 Histogram of x -3 -2 -1 0 1 2 3 x Il comando in R per stimare una densità è “density”. Non soffermandoci sull’argomento, molto banalmente diciamo che la stima della densità è una sorta di lisciamento del poligono di frequenza, quindi dell’istogramma. Al comando “density” premettiamo il comando “lines”, se vogliamo sovrapporre la densità stimata a un grafico preesistente, viceversa premettiamo il comando “plot”: > plot(density(x),lty=2) > curve(dnorm(x),add=TRUE) > curve(dnorm(x),-3,3) > lines(density(x),lty=2) 82 5 Campionamento e inferenza E’ noto che ogni indagine statistica prende in considerazione insiemi di unità (individui, oggetti, altro), che costituiscono la “popolazione” o il “collettivo statistico”. Spesso condurre un’indagine sull’intera popolazione risulta oneroso in termini di costo e/o di tempo o addirittura impossibile; la conoscenza delle caratteristiche di una popolazione può allora essere effettuata sulla base di un campione, il più possibile rappresentativo di essa. Supponiamo che la caratteristica della popolazione cui siamo interessati possa essere rappresentata da una v.c. X∼ (µ, σ2). Sia (X1,X2,…,Xn) un campione casuale estratto da X: Xi i.i.d. (µ, σ2); la v.c. “media campionaria” 1 n X n = ∑ X i ∼ (µ, σ2/n). Poiché E( X n ) = µ, X n è uno stimatore “corretto” di µ. n i =1 X −µ ∼ N(0,1). Se X ∼ N(µ, σ2), X n ∼ N(µ, σ2/n), quindi n σ2 /n Uno stimatore corretto di σ2 , quando questa non è nota, è dato dalla “varianza campionaria” ∑ (X n S n2 = i =1 − Xn) 2 i n −1 . Se Xi i.i.d. N(µ, σ2), (n-1) S n2 σ 2 ~χ 2n-1 e Xn − µ S n2 / n ∼ tn-1. 5.1 Legge dei grandi numeri Se Xi i.i.d. (µ, σ2), con σ2<∞, ∀ε>0, al crescere dell’ampiezza campionaria, la probabilità che la media campionaria sia esterna all’intervallo µ ±ε tende a zero: ( ) P Xn − µ >ε → 0, n→∞. Quest’espressione afferma che la media calcolata sul campione, all’aumentare di n, si avvicina a µ con una probabilità molto alta. Servendoci di un ciclo for, proviamo a generare 20 campioni, di ampiezza n crescente, da una N(10,22). Calcoliamo la media aritmetica (mn) su ciascun campione quindi, tramite il comando “plot”, rappresentiamo graficamente le 20 medie rispetto ad n. Il comando “abline” consente di rappresentare la vera media µ: > n<-seq(10,1000,50) >n [1] 10 60 110 160 210 260 310 360 410 460 510 560 610 660 710 760 810 860 910 [20] 960 > mn<-numeric(20) > mn [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 > for(i in 1:20){ + x<-rnorm(n[i],10,2) + mn[i]<-mean(x) +} > mn [1] 9.799474 10.387550 10.105870 10.111204 9.915069 9.903249 10.097539 [8] 10.003708 10.103273 9.950783 9.911585 9.960072 9.942577 10.046567 [15] 9.991333 9.984288 10.103710 10.030403 9.975925 9.953915 83 10 8 9 mn 11 12 > plot(n,mn,type="l",ylim=c(8,12)) > abline(h=10,lty=2) 0 200 400 600 800 n Il comando ‘’numeric‘’ è servito per inizializzare con degli zeri un vettore, in questo caso, di dimensione 20. Riutilizziamo adesso la stessa sequenza di comandi k=4 volte, servendoci di un altro ciclo for; ovviamente i vettori generati, anche se della stessa ampiezza, sono diversi, perché costituiti da sequenze di numeri pseudo-casuali: 10 11 12 8 9 mn 10 11 12 8 9 mn > op<-par(mfrow=c(2,2)) > for(k in 1:4){ + n<-seq(10,1000,50) + mn<-numeric(20) + for(i in 1:20){ + x<-rnorm(n[i],10,2) + mn[i]<-mean(x) +} + plot(n,mn,type="l",ylim=c(8,12)) + abline(h=10,lty=2) +} > par(op) 0 200 400 600 800 0 200 400 600 800 600 800 10 11 12 8 8 9 mn 10 11 12 n 9 mn n 0 200 400 n 600 800 0 200 400 n I grafici generati mostrano che la media campionaria oscilla intorno a µ e si avvicina ad essa con probabilità molto alta al crescere di n. 84 5.2 Teorema centrale del limite Asintoticamente, la somma standardizzata di n v.c. Xi i.i.d. (µ, σ2), con σ2 finita, tende a distribuirsi come una normale standard: n ∑X i =1 i − nµ ∼ N(0,1), quindi nσ 2 Xn − µ σ2 /n ∼ N(0,1), se n→∞. La velocità di convergenza dipende da n e dalla distribuzione di X. Ad esempio, se X ∼ ber(p), allora pˆ n = X n ∼ bin con E( X n ) = p e var( X n ) = p(1-p)/n. Se però n→∞, allora bin→N (Teorema di De Moivre-Laplace). La velocità di convergenza dipende da p. Proviamo a generare, servendoci di un ciclo for, 500 campioni di grandezza n=50 da una v.c. X ∼ ber(0.5). Calcoliamo la media su ciascun campione e costruiamo la distribuzione empirica della media campionaria standardizzata, quindi adattiamo una N(0,1): > p<-.5 > n<-50 > mn<-numeric(500) > for(i in 1:500){ + x<-rbinom(n,1,p) + mn[i]<-mean(x) +} > z<-(mn-p)/sqrt(p*(1-p)/n) > hist(z,freq=FALSE,ylim=c(0,.5),xlim=c(-4,4),col=2,main=paste("n=",n,"\n","p=",p)) > curve(dnorm(x),add=TRUE) L’istruzione “paste” serve a concatenare due o più stringhe in una sola; tutto ciò che non ha valore numerico va espresso fra apici, mentre "\n" serve a creare uno spazio. 0.3 0.2 0.0 0.1 Density 0.4 0.5 n= 50 p= 0.5 -4 -2 0 2 4 z Proviamo adesso a generare campioni di ampiezza crescente, utilizzando un doppio ciclo for: 85 > n<-c(10,50,100,1000) > p<-.5 > op<-par(mfrow=c(2,2)) > for(k in n){ + mn<-numeric(500) + for(i in 1:500){ + x<-rbinom(k,1,p) + mn[i]<-mean(x) +} + z<-(mn-p)/sqrt(p*(1-p)/k) + hist(z,freq=FALSE,ylim=c(0,.6), + xlim=c(-4,4),col="red",main=paste("n=",k)) + curve(dnorm(x),add=TRUE) +} 0.4 Density 0.0 0 2 4 -4 -2 0 z z n= 100 n= 1000 2 4 2 4 0.4 Density 0.0 0.2 0.0 0.2 0.4 0.6 -2 0.6 -4 Density 0.2 0.4 0.2 0.0 Density 0.6 n= 50 0.6 n= 10 -4 -2 0 z 2 4 -4 -2 0 z Come si può notare, per p=0.5 la convergenza verso la N è evidente anche per n piccolo. Se proviamo a sostituire, invece, p=0.1, ci accorgiamo che la convergenza verso la N è lenta. Verifichiamo adesso che se X ∼ N(µ, σ2), Xn − µ σ2 /n ∼ N(0,1), a prescindere dal valore di n: > n<-c(10,50,100,1000) > for(k in n){ + mn<-numeric(500) + for(i in 1:500){ + x<-rnorm(k,5,2) + mn[i]<-mean(x) +} + z<-(mn-5)/sqrt(4/k) + hist(z,freq=FALSE,ylim=c(0,.6), + xlim=c(-4,4),col="red",main=paste("n=",k)) + curve(dnorm(x),-4,4,add=TRUE) +} > par(op) 86 0.4 0.0 0 2 4 -4 -2 0 z z n= 100 n= 1000 2 4 2 4 0.4 0.2 0.0 0.0 0.2 Density 0.4 0.6 -2 0.6 -4 Density 0.2 Density 0.4 0.2 0.0 Density 0.6 n= 50 0.6 n= 10 -4 -2 0 2 4 -4 -2 z 0 z 5.3 Funzione di (log)verosimiglianza Siano (X1,X2,…,Xn) n v.c. la cui densità (probabilità) congiunta è f(x1,x2,…,xn;θ). Se (X1,X2,…,Xn) è un campione casuale estratto da X∼ f(x;θ), per cui le Xi sono i.i.d., allora è n f(x1,x2,…,xn;θ)= ∏ f (xi;θ). i =1 Tale densità (probabilità) congiunta, osservato il campione (x1,x2,…,xn), diventa funzione solo di θ e prende il nome di “funzione di verosimiglianza”, che indichiamo con L(θ, x1,x2,…,xn), o più semplicemente con L(θ). Con il metodo della massima verosimiglianza si assume come stima di θ il valore θˆ che rende massima la funzione di verosimiglianza, ossia la probabilità del campione osservato. La determinazione della stima di massima verosimiglianza si concretizza dunque nella ricerca del massimo della funzione L(θ) o, equivalentemente, della funzione log L(θ)11. Supponiamo di estrarre un campione di grandezza n=3 da X ~ ber(p). I possibili campioni sono: (0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (0, 1, 1), (1, 0, 1), (1, 1, 1). La funzione di verosimiglianza è: L(p)=pΣx(1-p)n-Σx, dunque può essere rappresentata dalle seguenti 4 curve (Σx=0, 1, 2, 3), in cui l‘ascissa del punto di massimo è la stima di massima verosimiglianza n pˆ = ∑x i =1 n i di p: > L0<-function(p) (1-p)^3 > curve(L0,0,1, xlab="p",ylab="L(p)") > L1<-function(p) p*(1-p)^2 > curve(L1,0,1,add=TRUE,col=2) > L2<-function(p) (p^2)*(1-p) 11 Ricercare il massimo di L(θ), o di log L(θ), equivale a ricercare il minimo di -L(θ), o di -log L(θ) 87 0.6 0.4 0.0 0.2 L(p) 0.8 1.0 > curve(L2,0,1,add=TRUE,col=3) > L3<-function(p) p^3 > curve(L3,0,1,add=TRUE,col=4) 0.0 0.2 0.4 0.6 0.8 1.0 p Generiamo, adesso, un campione di grandezza n=50 da una v.c. X ∼ ber(0.2) e rappresentiamo la funzione logL(p). Calcoliamo, inoltre, la stima di massima verosimiglianza di p e tracciamo due rette parallele agli assi, passanti per il punto di massimo, in modo da individuare tale stima anche graficamente: -100 -150 logL(p) -50 > n<-50 > x<-rbinom(n,1,.2) > y<-sum(x) > lnL<-function(p) +{ + y*log(p)+(n-y)*log(1-p) +} > curve(lnL,0,1,xlab="p",ylab="logL(p)") > xmax<-mean(x) > xmax [1] 0.18 > ymax<-lnL(xmax) > abline(v=xmax,lty=3) > abline(h=ymax,lty=3) 0.0 0.2 0.4 0.6 0.8 1.0 p 88 Generiamo, infine, un campione di grandezza n=50 da una v.c. X ∼ N(5,4) e rappresentiamo le ∑ ( xi − µ )2 ( x i − µ )2 n ∑ i ⎛ 1 ⎞ − n ⎟⎟ e 2σ 2 e -logL(µ,σ)= n log(σ ) + log(2π ) + i , funzioni L(µ,σ)= ⎜⎜ 2 2σ 2 ⎝ σ 2π ⎠ n considerando noto σ. Calcoliamo, quindi, la stima di massima verosimiglianza µ̂ = 6.0 e-48 0.0 e+00 L(µ) 1.2 e-47 > n<-50 > s2<-4 > x<-rnorm(n,5,sqrt(s2)) > sx<-sum(x) > sx2<-sum(x^2) > L<-function(m) +{ + k<-1/(sqrt(2*pi*s2))^n + k*exp((-1/(2*s2))*(sx2-2*m*sx+n*m^2)) +} > curve(L,4,7,xlab=expression(mu),ylab=expression(L(mu))) > xmax<-mean(x) > xmax [1] 5.041527 > ymax<-L(xmax) > ymax [1] 1.397241e-47 > abline(v=xmax,lty=3) > abline(h=ymax,lty=3) 4.0 4.5 5.0 5.5 6.0 6.5 7.0 µ > n<-50 > s<-2 > x<-rnorm(n,5,s) > sx<-sum(x) > sx2<-sum(x^2) > lnL<-function(m) +{ + k<-(n/2)*log(2*pi)+n*log(s) + k+(sx2-2*m*sx+n*m^2)/(2*(s^2)) +} 89 ∑x i =1 n i di µ: 200 100 150 logL(µ) 250 > curve(lnL,0,10,,xlab=expression(mu),ylab=expression(logL(mu))) > xmin<-mean(x) > ymin<-lnL(xmin) > ymin [1] 106.7508 > abline(v=xmin,lty=3) > abline(h=ymin,lty=3) 0 2 4 6 8 10 µ 5.4 Intervalli di confidenza 5.4.1 IC per la media E’ noto che con i metodi di stima puntuale si giunge alla determinazione di un solo valore dello stimatore del parametro; con la stima per intervallo, invece, si giunge alla determinazione di un intervallo che, con una data probabilità, dovrebbe comprendere il vero valore del parametro θ. Se si conosce la distribuzione campionaria di uno stimatore θˆ , è possibile ricavare la probabilità (1-α) che θˆ cada in un intervallo prefissato. Ad esempio, se (X1,X2,…,Xn) è un campione casuale estratto X −µ ∼ N(0,1), quindi è da X ∼ N(µ, σ2), la v.c. “media campionaria” X n ∼ N(µ, σ2/n), ovvero n σ2 /n lecito scrivere: X −µ ≤ z1-α/2) = 1-α P(zα/2 ≤ n σ2 /n Per α =0.05, è zα/2 = -1.96 e z1-α/2 =1.96, infatti: > qnorm(.025) [1] -1.959964 > # oppure > -qnorm(.975) [1] -1.959964 > qnorm(.975) [1] 1.959964 Ovviamente è zα/2 = - z1-α/2 , perché la v.c. N è simmetrica. 90 Rappresentiamo graficamente la suddetta probabilità, utilizzando comandi già noti: > curve(dnorm(x),-3,3,axes=FALSE,ylab="",xlab="",ylim=c(0,.5)) > axis(1,c(-3,-1.96,0,1.96,3),c("","-1.96",0,"1.96","")) > cods<-seq(-3,-1.96,length=100) > x<-c(-3,cods,-1.96,-3) > y<-c(0,dnorm(cods),0,0) > polygon(x,y,col=2) > codd<-seq(1.96,3,length=100) > x<-c(1.96,codd,3,1.96) > y<-c(0,dnorm(codd),0,0) > polygon(x,y, col=2) > abline(h=0) > text(0,.1,expression(1-alpha==0.95)) > text(-2.5,.1,expression(alpha/2==0.025)) > text(2.5,.1,expression(alpha/2==0.025)) > text(0,.5,expression(P(-1.96<Z<1.96)==1-alpha)) P ( − 1.96 < Z < 1.96) = 1 − α α 2 = 0.025 -1.96 1 − α = 0.95 0 α 2 = 0.025 1.96 L’espressione P(-1.96 ≤ Xn − µ σ2 /n ≤ 1.96) = 0.95 può anche scriversi nel seguente modo: P( X n -1.96 σ 2 / n ≤ µ ≤ X n +1.96 σ 2 / n ) = 0.95 L’ntervallo X n ± 1.96 σ 2 / n è un “intervallo di confidenza” per µ, perché nel 95% dei casi, ovvero per 95 campioni su 100, contiene µ. Facciamo un esempio, supponendo σ2 nota. Un urbanista è interessato alla superficie media µ delle abitazioni della propria città. Uno studio precedente indica che σ2=8 m2. In un campione di 50 appartamenti si osserva una media pari a 120 m2. Sulla base di questi dati si vuole determinare l'IC per µ al 95%. In R possiamo utilizzare i seguenti comandi: 91 > n<-50 > mx<-120 > var<-8^2 > #lc<-0.95 > #a<-0.05 > li<-mx-qnorm(.975)*sqrt(var/n) > ls<-mx+qnorm(.975)*sqrt(var/n) > cat("(",li,":",ls,")\n") ( 117.7826 : 122.2174 ) L’istruzione “cat” serve a concatenare elementi e a visualizzarli; l’espressione "\n", già vista all’interno dell’istruzione “paste” (cfr.par.5.2), consente di creare uno spazio. Supponiamo adesso σ2 non nota. Su una piastrina di silicio è stato rilevato il peso X in g di alcuni granelli di polvere. Si ipotizzi che X ~ N. Costruiamo un IC per µ: > x<-c(.39,.68,.82,1.35,1.38,1.62,1.70,1.71,1.85,2.14,2.89,3.69) > n<-length(x) > mx<-mean(x) > s2<-var(x) > #lc<-0.95 > #a<-0.05 > li<-mx-qt(.975,n-1)*sqrt(s2/n) > ls<-mx+qt(.975,n-1)*sqrt(s2/n) > cat("(",li,":",ls,")\n") ( 1.099159 : 2.270841 ) Si noti come, essendo σ2 non nota, per costruire l’IC ci siamo serviti dei quantili della t di Student; X −µ infatti, in questo caso è n ∼ tn-1. S n2 / n Lo stesso IC può essere costruito con R tramite il comando “t.test”, che vuole in input il campione e l’opzione “conf.lev”, se il livello di confidenza (1-α) è diverso da 0.95: > t.test(x) One Sample t-test data: x t = 6.3305, df = 11, p-value = 5.595e-05 alternative hypothesis: true mean is not equal to 0 95 percent confidence interval: 1.099159 2.270841 sample estimates: mean of x 1.685 > t.test(x,conf.lev=0.99) 92 One Sample t-test data: x t = 6.3305, df = 11, p-value = 5.595e-05 alternative hypothesis: true mean is not equal to 0 99 percent confidence interval: 0.8583201 2.5116799 sample estimates: mean of x 1.685 Ricordiamo che minore è l’ampiezza L dell’IC, maggiore è la precisione della stima, dunque per una scelta ottimale dell’ampiezza campionaria n, fissati α e K, è necessario che sia: L(n,α)=2 z1-a/2 σ 2 / n < K da cui n>(2 z1-a/2 σ / K)2. 5.4.2 IC per una proporzione Supponiamo che gli elettori siano stati chiamati alle urne per un referendum e che lo spoglio parziale di n=2000 schede abbia registrato una percentuale favorevole pari al 60%. Si vuole costruire l’IC al 95% della percentuale favorevole. Poiché (X1,X2,…,Xn) è un campione casuale estratto da X ∼ ber(p), e poiché n→∞, pˆ n = X n ∼ N( p,p(1-p)/n). Dunque: > p<-0.60 > n<-2000 > li<-p-qnorm(.975)*sqrt(p*(1-p)/n) > ls<-p+qnorm(.975)*sqrt(p*(1-p)/n) > cat("(",li,":",ls,")\n") ( 0.5785297 : 0.6214703 ) Con R è possibile costruire un IC molto vicino a quello trovato con il comando “prop.test”, che ha come argomenti il numero di casi favorevoli, la dimensione del campione e, se non si desidera la correzione per la continuità di Yates, l’opzione “ corr=FALSE ”: > x<-n*p > prop.test(x, n, corr=FALSE) 1-sample proportions test without continuity correction data: x out of n, null probability 0.5 X-squared = 80, df = 1, p-value = < 2.2e-16 alternative hypothesis: true p is not equal to 0.5 95 percent confidence interval: 0.5783577 0.6212589 93 sample estimates: p 0.6 > prop.test(x, n) 1-sample proportions test with continuity correction data: x out of n, null probability 0.5 X-squared = 79.6005, df = 1, p-value = < 2.2e-16 alternative hypothesis: true p is not equal to 0.5 95 percent confidence interval: 0.5781060 0.6215062 sample estimates: p 0.6 Per n piccolo, pˆ n = X n ∼ bin. In questo caso per costruire un IC per p, si può utilizzare il comando “binom.test”: > binom.test(x,n) Exact binomial test data: x and n number of successes = 1200, number of trials = 2000, p-value = < 2.2e-16 alternative hypothesis: true probability of success is not equal to 0.5 95 percent confidence interval: 0.5781459 0.6215604 sample estimates: probability of success 0.6 5.4.3 IC per la varianza Riprendendo l’esempio della piastrina di silicio, su cui era stato rilevato il peso X in g di alcuni granelli di polvere, proviamo a costruire una funzione, che chiamiamo “icvar”, che determini un IC per σ2. S2 Se (X1,X2,…,Xn) è un campione casuale estratto da X ~ N(µ, σ2), allora (n-1) n2 ~χ 2n-1, quindi è σ lecito scrivere: P(χ 2α/2 < (n-1) S n2 σ 2 < χ 21-α/2 )=1-α ovvero: P( (n − 1) S n2 χ 12−α / 2 <σ2 < 94 (n − 1) S n2 χ α2 / 2 )=1-α Un IC per σ2 è allora: > icvar<-function(x,lc=0.95) +{ + a<-1-lc + n<-length(x) + li<-(n-1)*var(x)/qchisq(1-a/2, n-1) + ls<-(n-1)*var(x)/qchisq(a/2, n-1) + c(li,ls) +} > x<-c(.39,.68,.82,1.35,1.38,1.62,1.70,1.71,1.85,2.14,2.89,3.69) > var(x) [1] 0.8501727 > icvar(x) [1] 0.4266368 2.4508692 Ovviamente, in questo caso, è χ 2α/2 ≠ -χ 21-α/2 , poiché la v.c. χ 2 non è simmetrica; fra l’altro, la v.c. χ 2 non assume valori negativi: 0.06 0.04 0.00 0.02 dchisq(x, n - 1) 0.08 > n<-length(x) > curve(dchisq(x,n-1),-1,30) > qchisq(.025,n-1) [1] 3.815748 > -qchisq(.975,n-1) [1] -21.92005 > qchisq(.975,n-1) [1] 21.92005 0 5 10 15 20 25 30 x 5.5 Verifica di ipotesi Supponiamo di avere un'idea di quale possa essere il valore incognito di un parametro θ; studiamo una strategia che, sulla base dei dati osservati, consenta di confermare o smentire la nostra ipotesi iniziale H0. Per sottoporre a verifica un’ipotesi ci serviamo di una statistica test. Il test ci dirà se rifiutare o accettare l' ipotesi nulla H0 ma, nel far questo, possiamo incorrere: - in un errore di I tipo (α), se rifiutiamo H0 ed H0 è vera; 95 - in un errore di II tipo (β), se accettiamo H0 ed H0 è falsa. 5.5.1 Verifica di ipotesi per la media Fissato α, supponiamo di voler verificare l’ipotesi H0: µ =µ0, contro l’ipotesi alternativa H1: µ <µ0. Se (X1,X2,…,Xn) è un campione casuale estratto da X ∼ N, la “statistica test” Z = X n − µ0 σ 2 /n ∼ N(0,1). Trattandosi di un test a una coda, rifiuteremo H0 se z<zα, dove z = ( x n -µ0)/ σ 2 / n è il valore di Z calcolato sul campione. Volendo verificare, invece, l’ipotesi H0: µ =µ0, contro l’alternativa H1: µ >µ0, rifiuteremo H0 se z>z1-α. Se σ2 non è nota, e viene stimata con la varianza campionaria, bisogna ricordarsi che X n − µ0 ∼ tn-1. S n2 / n Facciamo un esempio. In un campione di pazienti trattati con una terapia per l’abbassamento del colesterolo si sono osservati i seguenti valori di colesterolo in milligrammi per 100 millilitri di sangue: 130, 145, 128, 169, 132, 138, 141, 153, 129, 135, 140. Sapendo che in una popolazione di persone sane la quantità di colesterolo, che si suppone essere distribuita normalmente, in media è pari a 130, cosa fare per stabilire se la terapia adottata ha avuto effetto? Si tratta di verificare l’ipotesi H0: µ =130, contro l’alternativa H1: µ >130. Inoltre, σ2 non è nota, dunque, possiamo procedere nel seguente modo: > x<-c(130, 145, 128, 169, 132, 138, 141, 153, 129, 135, 140) >x [1] 130 145 128 169 132 138 141 153 129 135 140 > mean(x) [1] 140 > m0<-130 > var(x) [1] 149.4 > m<-mean(x) > v<-var(x) > n<-length(x) > t<-(m-m0)/sqrt(v/n) >t [1] 2.713445 >a<-0.01 > qt(1-a, n-1) [1] 2.763769 Fissato α=0.01, poiché t<t1-0.01, non rifiutiamo H0. Lo scarto (140-130) non è statisticamente significativo. Ciò vuol dire che la terapia adottata non ha avuto effetto. 96 Agli stessi risultati si perviene utilizzando la funzione “t.test”, già vista per la costruzione di un IC per µ; in questo caso, però, bisogna specificare µ0 e se l’ipotesi alternativa è “g” (greater), come nell’esempio, o “l” (less): > t.test(x,mu=m0,alternative="greater") One Sample t-test data: x t = 2.7134, df = 10, p-value = 0.01090 alternative hypothesis: true mean is greater than 130 95 percent confidence interval: 133.3204 Inf sample estimates: mean of x 140 Ricordiamo che il p-value è qui così definito: p-value = P(X>t), dove X∼ tn-1 In questo caso pvalue>α, quindi t non si trova nella zona di rifiuto. 5.5.2 Verifica di ipotesi per una proporzione Facciamo un esempio. Il direttore del personale di una compagnia di assicurazioni intende ridurre il turn-over, nel primo anno di assunzione, degli impiegati addetti all’analisi dei dati. Analisi precedenti mostrano che il 25% di coloro che vengono assunti in quest’area lascia la compagnia entro l’anno successivo all’assunzione. 150 neo assunti sono sottoposti ad un nuovo programma di training. Di questi, alla fine del primo anno, 29 non lavorano più per la compagnia. Fissato un livello di significatività pari a 0.05, si può ritenere che la proporzione di impiegati addetti all’analisi dei dati, che hanno partecipato al nuovo programma di training e poi lasciato la compagnia, sia inferiore al 25%? Si tratta di verificare l’ipotesi H0: p=p0 contro l’ipotesi alternativa H1: p<p0. Se (X1,X2,…,Xn) è un campione casuale estratto da X ∼ ber(p), per n→∞, la “statistica test” pˆ n − p 0 ∼ N(0,1). Quindi: ( p 0 (1 − p 0 ) / n > p<-29/150 >p [1] 0.1933333 > p0<-25/100 > n<-150 > z<-(p-p0)/sqrt(p0*(1-p0)/n) >z [1] -1.602775 > qnorm(0.05) # quantile [1] -1.644854 97 > pnorm(z) # p-value [1] 0.05449213 Poichè z>z0.05 e p-value>α, z non si trova nella zona di rifiuto, per cui la differenza ( pˆ n − p 0 ) non si può ritenere statisticamente significativa. Possiamo concludere, dunque, che la proporzione di impiegati addetti all’analisi dei dati, che hanno partecipato al nuovo programma di training e poi lasciato la compagnia, non è inferiore al 25%. Per la verifica di ipotesi su p si possono anche utilizzare le funzioni “prop.test”, o “binom.test” se n è piccolo, già analizzate per la costruzione di IC , specificando se l’ipotesi alternativa è “less” o “greater”. Tali funzioni però seguono una procedura diversa da quella classica, per cui non sempre si perviene agli stessi risultati: > prop.test(29,150,alternative="less") 1-sample proportions test with continuity correction data: 29 out of 150, null probability 0.5 X-squared = 55.2067, df = 1, p-value = 5.425e-14 alternative hypothesis: true p is less than 0.5 95 percent confidence interval: 0.0000000 0.2552202 sample estimates: p 0.1933333 > binom.test(29,150,alternative="less") Exact binomial test data: 29 and 150 number of successes = 29, number of trials = 150, p-value = 7.309e-15 alternative hypothesis: true probability of success is less than 0.5 95 percent confidence interval: 0.0000000 0.2541129 sample estimates: probability of success 0.1933333 5.5.3 Verifica di ipotesi per la varianza Supponiamo di voler verificare l’ipotesi H0: σ2 =σ02 contro l’alternativa H1: σ2 >σ02 oppure contro l’alternativa H1: σ2 <σ02. Costruiamo, a tale proposito, una funzione, che definiamo “testvar”, tenendo conto che se (X1,X2,…,Xn) è un campione casuale estratto da X ~ N, la “statistica test” S n2 (n-1) 2 ~χ 2n-1. σ0 La funzione “testvar” chiede, inizialmente, se (if) σ02 e i dati campionari sono “missing”, altrimenti blocca (stop) la routine e chiede di inserirli. Successivamente, definisce la statistica test “stat” e tramite istruzioni “if” nidificate chiede: 98 - se H1: σ2 >σ02, in tal caso il valore “soglia” è χ 21-α; se (n-1) - se H1: σ2 <σ02, in tal caso il valore “soglia” è χ 2α; se (n-1) s n2 σ 02 s n2 σ 02 >χ 21-α, si rifiuta H0; <χ 2α, si rifiuta H0. Una serie di istruzioni “cat”, infine, consentono di visualizzare dei messaggi. La funzione “testvar” vuole in input: i dati campionari, σ02, l’opzione “greater” o “less”, che specifica l’ipotesi alternativa, il valore di α se è diverso da 0.05: testvar<-function (x, var0, alternative = c("greater", "less"), alpha = 0.05) { if (missing(var0)) stop("specificare l'ipotesi nulla var0") if (missing(x)) stop("specificare i dati x") n <- length(x) stat <- (n - 1) * var(x)/var0 cat("\n Ipotesi nulla => H0 : var =", var0) cat("\n Varianza campionaria:", var(x), ",") cat(" statistica test:", stat) if (alternative == "greater") { soglia <- qchisq(1 - alpha, df = n - 1) cat("\n p-value:", 1 - pchisq(stat, df = n - 1), ",") cat(" livello del test:", alpha) cat("\n Quantile Chi-quadrato:", soglia, " con ", n 1, "gdl") cat("\n Ipotesi alternativa => H1 : var > ", var0) if (stat > soglia) cat("\n Decisione: si rifuta H0\n") else cat("\n Decisione: non si rifuta H0\n") } else if (alternative == "less") { soglia <- qchisq(alpha, df = n - 1) cat("\n p-value:", pchisq(stat, df = n - 1), ",") cat(" livello del test:", alpha) cat("\n Quantile Chi-quadrato:", soglia, " con ", n 1, "gdl") cat("\n Ipotesi alternativa => H1 : var < ", var0) if (stat < soglia) cat("\n Decisione: si rifuta H0\n") else cat("\n Decisione: non si rifuta H0\n") } } Nel costruire la funzione “testvar” abbiamo ipotizzato la media non nota. Facciamo un esempio. Estraiamo un campione di dimensione n=100 da una N(0,52): > x<-rnorm(100,sd=5) > var(x) [1] 24.26047 99 Fissato α=0.05, vogliamo verificare l’ipotesi H0: σ2 =25 contro l’alternativa H1: σ2 <σ02; utilizziamo la funzione “testvar”: > var0<-25 > testvar(x,var0,"less") Ipotesi nulla => H0 : var = 25 Varianza campionaria: 24.26047 , statistica test: 96.07148 p-value: 0.4353808 , livello del test: 0.05 Quantile Chi-quadrato: 77.04633 con 99 gdl Ipotesi alternativa => H1 : var < 25 Decisione: non si rifuta H0 100 Appendice (esercizi svolti) 101 ESERCIZI MODULO 1 1) Considerare il dataframe “chickwts” dell’ambiente R e costruire una tabella a doppia entrata per le due variabili “weight (Y)” e “feed (X)”, quindi individuare le distribuzioni marginali e la distribuzione condizionata di Y|X=x4 . Verificare, inoltre, se c’è associazione fra le due variabili. Calcolare, infine, i quartili per la variabile Y e rappresentare graficamente la variabile X. 2) Il file “azioni.txt” contiene i prezzi (in dollari) di chiusura di 75 azioni, scambiate su due diversi mercati americani. Per ciascuna delle due serie di dati: • Costruire la distribuzione delle frequenze e la distribuzione delle percentuali con intervalli di ampiezza costante pari a 10 dollari; • costruire l’istogramma (rappresentarli entrambi in un unico grafico); • calcolare le frequenze cumulate assolute, relative e percentuali; • calcolare gli indici di sintesi più informativi; • costruire il diagramma scatola e baffi. Sulla base delle precedenti elaborazioni si possono osservare sostanziali differenze nei prezzi di chiusura sui due mercati? 3) Il file “funds.txt” contiene informazioni su un campione di 140 fondi di investimento sul quale sono state osservate le cinque variabili: A: Tipo di azioni che compongono il fondo; B: Commissioni di uscita (Y=Si, N=No); C: Rendimento percentuale ottenuto nel primo semestre del 1999; D: Rendimento percentuale a dodici mesi; E: Spese associate al fondo (in percentuale rispetto alle attività). • Per la variabile A: costruire la distribuzione delle frequenze assolute, relative e percentuali; calcolare la moda, calcolare l’indice di eterogeneità di Gini; effettuare una rappresentazione grafica; 102 • Per la variabile E: costruire una distribuzione di frequenza per classi di ampiezza costante, rappresentare l’istogramma, calcolare l’indice di asimmetria più informativo; • Calcolare la covarianza tra le variabili C e D; • Commentare i risultati ottenuti. 4) I dati (espressi in migliaia di dollari) contenuti nel file “tax.txt” rappresentano dichiarazioni per l’imposta sulle vendite, sottoposte all’autorità fiscale competente della comunità di Gmoserville, a fine marzo 1999, dalle 50 aziende ivi operanti. • Costruire una distribuzione di frequenza per classi di ampiezza costante e scegliere la rappresentazione grafica più idonea; • calcolare le frequenze relative, le frequenze assolute cumulate, le frequenze relative cumulate; • calcolare gli indici di sintesi più informativi; • costruito il diagramma scatola e baffi, come descrivereste la forma della distribuzione? L’indice di asimmetria, calcolato in precedenza, conferma tale descrizione? 5) Importare il file di dati “aaupdat”, la cui descrizione è contenuta nel file di testo “aauptxt”. • Considerare la variabile D, classificarla e scegliere la rappresentazione grafica più idonea; • Considerare le variabili E, F, G, H. Per ciascuna di esse calcolare i quartili e costruire il boxplot, quindi commentare e confrontare la forma delle 4 distribuzioni; • Considerare le variabili E, I. Calcolare la covarianza e il coefficiente di correlazione lineare di Bravais-Pearson e commentare i risultati. Costruire la distribuzione di frequenza di una delle due variabili, scegliendo opportune classi di ampiezza costante e scegliere la rappresentazione grafica più appropriata. 6) Considerare il dataframe “cars” e verificare se sussiste una relazione lineare fra le due variabili “speed” e “dist”. In tal caso, condurre una completa analisi di regressione. 7) Considerare il dataset contenuto nel file “water”. • Stabilire se esiste una relazione fra le due variabili ed individuare la funzione che rappresenti al meglio tale relazione; • Verificare, attraverso l’uso di un indice appropriato, se la suddetta funzione si adatta bene ai dati osservati. 103 8) Considerare il dataset contenuto nel file “hospital”. Rappresentare graficamente i dati osservati e verificare, empiricamente ed analiticamente, se esiste una relazione lineare fra le due variabili. 9) Il dataset contenuto nel file “ring.txt” riporta i prezzi, in dollari, di anelli con diamante per signora e la corrispondente misura del diamante in carati. • Individuare la variabile dipendente e rappresentare graficamente le coppie di osservazioni; • stabilire il tipo di relazione che lega le due variabili ed adattare la funzione di regressione che si ritiene più idonea; • determinare un indice che dia indicazioni sulla bontà di adattamento del modello scelto ai dati osservati. 10) Il dataset contenuto nel file “phone.txt” riporta i valori delle tariffe telefoniche (in dollari, per minuto di conversazione) e il numero di minuti di conversazione (in miliardi) per le telefonate fatte dagli Stati Uniti verso 20 paesi, nel corso del 1996. • Calcolare il coefficiente di correlazione; • Ci si aspetta che quanto maggiore è la tariffa telefonica, tanto minore è la durata delle telefonate. Il coefficiente di correlazione calcolato conferma tale supposizione? 11) Un agente immobiliare intende prevedere gli affitti mensili degli appartamenti sulla base della loro dimensione. Nel file “rent.txt” si riportano i valori degli affitti (in dollari) e della dimensione (in piedi al quadrato) di 25 appartamenti in una zona residenziale. • Creare il diagramma di dispersione; • Nell’ipotesi che tra le due variabili sussista una relazione lineare, stimare con il metodo dei minimi quadrati i coefficienti di regressione a e b; • fornire un’interpretazione di a e di b con riferimento al problema considerato; • prevedere l’ammontare dell’affitto mensile per un appartamento di 1000 piedi al quadrato; • calcolare i residui e i valori predetti; • calcolare il coefficiente di determinazione e interpretarne il significato. 104 ESERCIZI MODULO 2 1) L’assistenza ai clienti di una società del gas intende stimare la durata media del tempo X che intercorre tra la ricezione di una richiesta di allacciamento e l’effettivo allacciamento. Viene estratto un campione casuale di 15 case, per cui si ottengono i seguenti risultati in numero di giorni di attesa ( i dati si riferiscono all’anno trascorso): • 114 78 96 137 78 103 117 126 86 99 114 72 104 73 86 Determinare un intervallo di confidenza di livello 95% per stimare la media del tempo di attesa dello scorso anno; • Quale ipotesi si deve fare sulla distribuzione della popolazione? 2) Un imprenditore valuta l’acquisto di una lavanderia a gettoni. L’attuale proprietario sostiene di aver conseguito, nel corso degli ultimi 5 anni, un guadagno medio giornaliero di $675 con uno scarto quadratico medio di $75. Per un campione di 30 giorni, si calcola un guadagno medio di $625. • specificare l’ipotesi nulla e quella alternativa; • si può ritenere, in base al campione, che l’affermazione dell’attuale proprietario non sia corretta? (Usare un livello di significatività di 0.01) 3) Supponiamo che in questo momento 10 persone siano collegate ad un sito per l’acquisto di articoli su Internet. Sapendo che la probabilità che ciascuno dei soggetti acquisti effettivamente un articolo è pari a 0.2, calcolare: • la probabilità che nessun soggetto acquisti un articolo; • la probabilità che almeno 2 soggetti acquistino un articolo; • la probabilità che al massimo 2 soggetti acquistino un articolo. 105 4) Sono stati rilevati i prezzi al litro di venti acque minerali (lire/10): 31, 35, 36, 34, 40, 38, 68, 46, 28, 33, 21, 34, 30, 42, 20, 34, 63, 22, 38, 28. Supposto che la distribuzione dei prezzi sia N(µ, σ2), si chiede di verificare l’ipotesi H0: σ2 = σ02 = 200 contro l’alternativa H1: σ2 < 200, al livello di significatività 0,01. 5) Sia data la seguente variabile casuale bivariata: X\Y 7 9 11 12 4 0.1 0.1 0.2 0.1 6 0.2 0.1 0.1 0.1 • verificare se le v.c. X e Y sono stocasticamente indipendenti; • determinare E(X) e var(X); • determinare E(X+Y) e var(X+Y). 6) Un manager di una società che vende combustibile per riscaldamento domestico intende stimare il consumo medio annuo (in galloni) nelle case monofamiliari di una certa area geografica. Si estrae un campione di 35 case: il loro consumo annuo è riportato nella tabella seguente: 1150.25 872.37 1459.56 941.96 1013.27 • 1352.67 1126.57 1252.01 767.37 1402.59 983.45 1184.17 373.91 1598.57 1069.32 1365.11 1046.35 1047.40 1598.66 1108.94 942.71 1110.50 1064.46 1343.29 1326.19 1577.77 1050.86 1018.23 1617.73 1074.86 330.00 851.60 996.92 1300.76 975.86 Calcolare un intervallo di confidenza del 95% per la media della popolazione del consumo di combustibile per riscaldamento in un anno. • E’ necessario fare delle assunzioni sulla distribuzione della popolazione affinché l’intervallo di confidenza trovato possa ritenersi valido? 7) Il direttore di un grande giornale cittadino intende determinare la proporzione di giornali stampati, che non sono idonei alla vendita per motivi diversi, come impaginazione sbagliata, pagine mancanti e così via. Viene allora estratto un campione di 200 giornali e si osserva che 35 di essi non sono idonei. Calcolare l'intervallo di confidenza del 90% per la proporzione di giornali non idonei nella popolazione. 8) Il file “tea.txt” riporta i pesi in grammi di 105 bustine di tè. 106 • In base alle informazioni campionarie, si può ritenere che il peso medio delle bustine di tè prodotte sia diverso da 5.5 grammi? (Supporre che il livello di significatività α sia 0.01); • Costruire un intervallo di confidenza del 99% per il peso medio dei sacchetti di tè e spiegarne il significato. 9) Il responsabile del controllo qualità della Malilyn’s cookies sta ispezionando una partita di biscotti con scaglie di cioccolato di produzione della società. Se il processo produttivo funziona correttamente il n. medio di scaglie di cioccolato per biscotto è pari a 6. Qual è la probabilità che in un particolare biscotto ispezionato: • si trovino al più 5 scaglie di cioccolato; • si trovino esattamente 5 scaglie di cioccolato; • si trovino almeno 5 scaglie di cioccolato; • si trovino 4 o 5 scaglie di cioccolato. 10) Quando un consumatore fa un ordine attraverso il Rudi’s On-line Office, un sistema informativo computerizzato controlla automaticamente se il consumatore ha ecceduto i propri limiti di credito. La probabilità che questa eventualità si verifichi è stata stimata sulla base dell’esperienza pari a 0.05. Supponendo che in un giorno siano inoltrati 20 ordini da parte di altrettanti consumatori e che il numero di ordini oltre i limiti di credito sia distribuito secondo una legge binomiale, calcolare: • Il valore atteso e lo scarto quadratico medio del numero di ordini oltre i limiti di credito; • la probabilità che in un giorno nessun consumatore inoltri un ordine che ecceda il proprio limite di credito; • la probabilità che almeno due consumatori eccedano i propri limiti di credito; • la probabilità che al più tre consumatori eccedano i propri limiti di credito. 11) Una filiale di una banca, in un quartiere commerciale di una città, ha realizzato un miglioramento nel servizio alla clientela tra le 12 e le 13, l’ora di punta della pausa pranzo. Per una settimana viene rilevato il tempo di attesa (in minuti) di ciascun cliente (definito come il tempo che intercorre tra il momento in cui inizia la fila e quello in cui è servito). Per un campione casuale di 15 clienti si ottengono i risultati riportati nel file “bank.txt”. 107 • Fissato un livello di significatività pari a 0.05, si può ritenere che il tempo medio di attesa sia inferiore a 5 minuti? • verificare l’ipotesi H0: σ2 = σ02 = 2 contro l’alternativa H1: σ2 > 2, al livello di significatività 0,01; • quali ipotesi devono essere soddisfatte per condurre i test di cui ai punti precedenti? 12) In base all’esperienza passata, si ritiene che il numero di imperfezioni al metro in un rotolo di carta assorbente segua la legge di Poisson, con un valore atteso di una imperfezione ogni 5 metri di carta (0,2 al metro). Calcolare: • la probabilità che in un metro di carta ci siano al più 2 imperfezioni; • la probabilità che in due metri di carta ci sia almeno una imperfezione; • la probabilità che in 50 metri di carta ci sia un numero di imperfezioni compreso tra 5 e 15 (estremi inclusi). 13) Un produttore di oggetti in plastica intende valutare la resistenza di blocchi rettangolari in plastica da arredamento. Per un campione di 50 blocchi si calcolano i valori di un indice di solidità riportati nel file “plastic.txt”. • Per un livello di significatività uguale a 0.05, si può ritenere che il valore medio dell’indice sia diverso da 260? • Quali ipotesi devono essere soddisfatte per condurre un test di questo genere? • Calcolare il p-value e spiegarne il significato. 108 SOLUZIONI ESERCIZI MODULO 1 1) > data(chickwts) > z<-chickwts > attach(z) > x<-feed > y<-weight > str(x) Factor w/ 6 levels "casein","horseb..",..: 2 2 2 2 2 2 2 2 2 2 ... > class(x) [1] "factor" > sort(y) [1] 108 124 136 140 141 143 148 153 158 160 168 169 171 179 181 193 199 203 206 [20] 213 216 217 222 226 227 229 230 242 243 244 248 248 250 257 257 258 260 260 [39] 263 267 271 271 283 295 297 303 309 315 316 318 318 320 322 325 327 329 332 [58] 334 339 340 341 344 352 359 368 379 380 390 392 404 423 > e<-seq(100,450,50) > y2<-cut(y,breaks=e) > y2 [1] (150,200] (150,200] (100,150] (200,250] (200,250] (150,200] (100,150] [8] (100,150] (100,150] (100,150] (300,350] (200,250] (150,200] (100,150] [15] (250,300] (200,250] (100,150] (150,200] (200,250] (250,300] (200,250] [22] (250,300] (200,250] (200,250] (200,250] (300,350] (300,350] (200,250] [29] (150,200] (250,300] (300,350] (250,300] (150,200] (150,200] (150,200] [36] (200,250] (400,450] (300,350] (350,400] (300,350] (300,350] (200,250] [43] (300,350] (250,300] (300,350] (300,350] (250,300] (300,350] (300,350] [50] (250,300] (300,350] (300,350] (350,400] (150,200] (250,300] (200,250] [57] (200,250] (300,350] (250,300] (350,400] (350,400] (350,400] (250,300] [64] (400,450] (300,350] (350,400] (350,400] (200,250] (200,250] (250,300] [71] (300,350] 7 Levels: (100,150] (150,200] (200,250] (250,300] (300,350] ... (400,450] > tabella<-table(x,y2) > tabella y2 x (100,150] (150,200] (200,250] (250,300] (300,350] casein 0 0 2 2 2 horsebean 5 3 2 0 0 linseed 2 2 4 3 1 meatmeal 0 1 2 3 4 soybean 0 4 5 2 3 sunflower 0 0 1 2 7 y2 x (350,400] (400,450] casein 5 1 horsebean 0 0 linseed 0 0 meatmeal 1 0 109 soybean sunflower 0 1 0 1 # distribuzioni marginali > xt<-margin.table(tabella,1) > yt<-margin.table(tabella,2) > xt x casein horsebean linseed meatmeal soybean sunflower 12 10 12 11 14 12 > yt y2 (100,150] (150,200] (200,250] (250,300] (300,350] (350,400] (400,450] 7 10 16 12 17 7 2 # distribuzione condizionata > tabella[4,] (100,150] (150,200] (200,250] (250,300] (300,350] (350,400] (400,450] 0 1 2 3 4 1 0 > summary(tabella) Number of cases in table: 71 Number of factors: 2 Test for independence of all factors: Chisq = 65.61, df = 30, p-value = 0.0001829 Chi-squared approximation may be incorrect > maxX2<-71*min(6-1,7-1) > 65.61/maxX2 [1] 0.1848169 > quantile(y) 0% 25% 50% 75% 100% 108.0 204.5 258.0 323.5 423.0 > plot(x) # oppure > pie(table(X)) 2) > z<-scan("azioni.txt") Read 150 items >z [1] 6.88 1.00 0.75 1.00 3.88 1.00 4.12 1.00 11.88 1.00 15.88 1.00 [13] 16.50 1.00 8.75 1.00 9.25 1.00 7.50 1.00 5.38 1.00 14.38 1.00 [25] 2.50 1.00 4.88 1.00 6.38 1.00 33.62 1.00 4.88 1.00 9.00 1.00 [37] 2.00 1.00 20.00 1.00 14.25 1.00 4.00 1.00 15.25 1.00 2.38 1.00 [49] 49.50 1.00 36.50 2.00 23.50 2.00 8.25 2.00 57.50 2.00 27.12 2.00 [61] 3.75 2.00 25.00 2.00 15.50 2.00 36.12 2.00 6.00 2.00 9.12 2.00 110 [73] 33.28 2.00 22.50 2.00 8.75 2.00 8.62 2.00 5.75 2.00 21.88 2.00 [85] 6.12 2.00 25.00 2.00 15.88 2.00 24.00 2.00 10.88 2.00 18.75 2.00 [97] 53.88 2.00 20.38 2.00 26.00 2.00 19.00 2.00 46.00 2.00 23.50 2.00 [109] 22.62 2.00 12.88 2.00 5.50 2.00 37.50 2.00 9.88 2.00 59.12 2.00 [121] 35.25 2.00 20.62 2.00 24.00 2.00 80.50 2.00 29.38 2.00 3.75 2.00 [133] 64.75 2.00 14.25 2.00 46.38 2.00 4.75 2.00 25.00 2.00 35.00 2.00 [145] 9.00 2.00 12.38 2.00 31.00 2.00 > A<-matrix(z,ncol=2,byrow=TRUE) >A [,1] [,2] [1,] 6.88 1 [2,] 0.75 1 [3,] 3.88 1 [4,] 4.12 1 [5,] 11.88 1 [6,] 15.88 1 [7,] 16.50 1 [8,] 8.75 1 [9,] 9.25 1 [10,] 7.50 1 [11,] 5.38 1 [12,] 14.38 1 [13,] 2.50 1 [14,] 4.88 1 [15,] 6.38 1 [16,] 33.62 1 [17,] 4.88 1 [18,] 9.00 1 [19,] 2.00 1 [20,] 20.00 1 [21,] 14.25 1 [22,] 4.00 1 [23,] 15.25 1 [24,] 2.38 1 [25,] 49.50 1 [26,] 36.50 2 [27,] 23.50 2 [28,] 8.25 2 [29,] 57.50 2 [30,] 27.12 2 [31,] 3.75 2 [32,] 25.00 2 [33,] 15.50 2 [34,] 36.12 2 [35,] 6.00 2 [36,] 9.12 2 [37,] 33.28 2 [38,] 22.50 2 111 [39,] 8.75 2 [40,] 8.62 2 [41,] 5.75 2 [42,] 21.88 2 [43,] 6.12 2 [44,] 25.00 2 [45,] 15.88 2 [46,] 24.00 2 [47,] 10.88 2 [48,] 18.75 2 [49,] 53.88 2 [50,] 20.38 2 [51,] 26.00 2 [52,] 19.00 2 [53,] 46.00 2 [54,] 23.50 2 [55,] 22.62 2 [56,] 12.88 2 [57,] 5.50 2 [58,] 37.50 2 [59,] 9.88 2 [60,] 59.12 2 [61,] 35.25 2 [62,] 20.62 2 [63,] 24.00 2 [64,] 80.50 2 [65,] 29.38 2 [66,] 3.75 2 [67,] 64.75 2 [68,] 14.25 2 [69,] 46.38 2 [70,] 4.75 2 [71,] 25.00 2 [72,] 35.00 2 [73,] 9.00 2 [74,] 12.38 2 [75,] 31.00 2 > x<-A[1:25,1] > y<-A[26:75,1] >x [1] 6.88 0.75 3.88 4.12 11.88 15.88 16.50 8.75 9.25 7.50 5.38 14.38 [13] 2.50 4.88 6.38 33.62 4.88 9.00 2.00 20.00 14.25 4.00 15.25 2.38 [25] 49.50 >y [1] 36.50 23.50 8.25 57.50 27.12 3.75 25.00 15.50 36.12 6.00 9.12 33.28 [13] 22.50 8.75 8.62 5.75 21.88 6.12 25.00 15.88 24.00 10.88 18.75 53.88 [25] 20.38 26.00 19.00 46.00 23.50 22.62 12.88 5.50 37.50 9.88 59.12 35.25 [37] 20.62 24.00 80.50 29.38 3.75 64.75 14.25 46.38 4.75 25.00 35.00 9.00 [49] 12.38 31.00 > sort(x) [1] 0.75 2.00 2.38 2.50 3.88 4.00 4.12 4.88 4.88 5.38 6.38 6.88 112 [13] 7.50 8.75 9.00 9.25 11.88 14.25 14.38 15.25 15.88 16.50 20.00 33.62 [25] 49.50 > sort(y) [1] 3.75 3.75 4.75 5.50 5.75 6.00 6.12 8.25 8.62 8.75 9.00 9.12 [13] 9.88 10.88 12.38 12.88 14.25 15.50 15.88 18.75 19.00 20.38 20.62 21.88 [25] 22.50 22.62 23.50 23.50 24.00 24.00 25.00 25.00 25.00 26.00 27.12 29.38 [37] 31.00 33.28 35.00 35.25 36.12 36.50 37.50 46.00 46.38 53.88 57.50 59.12 [49] 64.75 80.50 > ist1<-hist(x,plot=FALSE) > ist2<-hist(y,plot=FALSE) > n1<-ist1$counts > n1 [1] 16 7 0 1 1 > f1<-n1/length(x) > p1<-f1*100 > p1 [1] 64 28 0 4 4 > sum(p1) [1] 100 > n2<-ist2$counts > n2 [1] 13 8 15 7 2 3 1 0 1 > f2<-n2/length(y) > p2<-f2*100 > p2 [1] 26 16 30 14 4 6 2 0 2 > op<-par(mfrow=c(2,1)) > hist(x) > hist(y) > par(op) > cumsum(n1) [1] 16 23 23 24 25 > cumsum(f1) [1] 0.64 0.92 0.92 0.96 1.00 > cumsum(p1) [1] 64 92 92 96 100 > cumsum(n2) [1] 13 21 36 43 45 48 49 49 50 > cumsum(f2) [1] 0.26 0.42 0.72 0.86 0.90 0.96 0.98 0.98 1.00 > cumsum(p2) [1] 26 42 72 86 90 96 98 98 100 > median(x) [1] 7.5 > mean(x) [1] 10.9516 > sqrt(var(x)*(length(x)-1)/length(x)) [1] 10.61805 113 > median(y) [1] 22.56 > mean(y) [1] 24.4408 > sqrt(var(y)*(length(y)-1)/length(y)) [1] 17.0957 > cvx<-10.61805/10.9516 > cvx [1] 0.9695433 > cvy<-17.0957/24.4408 > cvy [1] 0.6994738 > boxplot(x) > boxplot(y) 3) > z<-read.table("funds.txt",header=TRUE) > attach(z) > table(A) A GI IL MC SC TK 43 31 17 32 17 > table(A)/length(A) A GI IL MC SC TK 0.3071429 0.2214286 0.1214286 0.2285714 0.1214286 > table(A)/length(A)*100 A GI IL MC SC TK 30.71429 22.14286 12.14286 22.85714 12.14286 > # moda: GI > gini<-function(x) { + n<-length(x) + f<-table(x)/n + k<-length(f) + if(k==1) + return(0) + 1-sum(f^2) +} > gini(A) [1] 0.774898 > plot(A) > hist(E,plot=FALSE) $breaks 114 [1] -0.00000045 0.50000045 1.00000045 1.50000045 2.00000045 2.50000045 [7] 3.00000045 3.50000045 4.00000045 4.50000045 $counts [1] 4 36 48 30 17 4 0 0 1 $intensities [1] 0.05714275 0.51428571 0.68571429 0.42857143 0.24285714 0.05714286 0.00000000 [8] 0.00000000 0.01428571 $density [1] 0.05714275 0.51428571 0.68571429 0.42857143 0.24285714 0.05714286 0.00000000 [8] 0.00000000 0.01428571 $mids [1] 0.2500000 0.7500004 1.2500004 1.7500004 2.2500004 2.7500004 3.2500004 [8] 3.7500004 4.2500004 $xname [1] "E" $equidist [1] TRUE attr(,"class") [1] "histogram" > hist(E) > beta1<-function(x) { + n<-length(x) + s3<-sqrt(var(x)*(n-1)/n)^3 + mx<-mean(x) + m3<-sum((x-mx)^3)/n + m3/s3 +} > > beta1(E) [1] 0.8937315 > covCD<-cov(C,D)*(length(C)-1)/length(C) > covCD [1] 144.1959 4) x<-scan("tax.txt") > sort(x) [1] 5.3 6.5 6.7 7.3 7.5 7.6 7.8 8.0 8.4 8.6 8.7 8.9 9.0 9.2 9.3 [16] 9.3 9.5 9.6 9.8 9.9 10.0 10.0 10.1 10.2 10.3 10.3 10.4 10.5 10.5 10.6 [31] 10.7 11.0 11.1 11.1 11.1 11.2 11.5 11.6 11.6 11.8 12.5 12.5 12.5 12.7 12.8 115 [46] 12.9 13.0 13.0 14.5 15.1 > n<-hist(x,plot=FALSE) >n $breaks [1] 4 6 8 10 12 14 16 $counts [1] 1 7 14 18 8 2 $intensities [1] 0.009999984 0.070000000 0.140000000 0.180000000 0.080000000 0.020000000 $density [1] 0.009999984 0.070000000 0.140000000 0.180000000 0.080000000 0.020000000 $mids [1] 5 7 9 11 13 15 $xname [1] "x" $equidist [1] TRUE attr(,"class") [1] "histogram" > freqass<-n$counts > freqass [1] 1 7 14 18 8 2 > hist(x) > freqrel<-freqass/50 > freqrel [1] 0.02 0.14 0.28 0.36 0.16 0.04 > cumsum(freqass) [1] 1 8 22 40 48 50 > cumsum(freqrel) [1] 0.02 0.16 0.44 0.80 0.96 1.00 > summary(x) Min. 1st Qu. Median Mean 3rd Qu. Max. 5.30 9.05 10.30 10.28 11.58 15.10 > var<-var(x)*(length(x)-1)/length(x) > sqm<-sqrt(var) > sqm [1] 2.024451 > beta1<-function(x) { 116 + n<-length(x) + s3<-sqrt(var(x)*(n-1)/n)^3 + mx<-mean(x) + m3<-sum((x-mx)^3)/n + m3/s3 +} > beta1(x) [1] -0.04984544 > beta2<-function(x) { + n<-length(x) + s4<-sqrt(var(x)*(n-1)/n)^4 + mx<-mean(x) + m4<-sum((x-mx)^4)/n + m4/s4 +} > beta2(x) [1] 2.920024 > boxplot(x) 5) > z<-read.table("aaupdat.txt",header=TRUE) > attach(z) > pie(table(D)) > quantile(E) 0% 25% 50% 75% 100% 0 428 498 594 1009 > quantile(F) 0% 25% 50% 75% 100% 0 362 410 460 733 > quantile(G) 0% 25% 50% 75% 100% 0 311 348 387 576 > quantile(H) 0% 25% 50% 75% 100% 232 352 407 475 866 > boxplot(E,F,G,H) > cov(E,I)*(length(E)-1)/length(E) [1] 35595.42 > cor(E,I) [1] 0.9948979 > hist(E,plot=FALSE) $breaks [1] 0 100 200 300 400 500 600 700 800 900 1000 1100 117 $counts [1] 68 0 7 135 385 294 181 71 14 5 1 $intensities [1] 5.857019e-04 0.000000e+00 6.029285e-05 1.162791e-03 3.316107e-03 [6] 2.532300e-03 1.559001e-03 6.115418e-04 1.205857e-04 4.306632e-05 [11] 8.613264e-06 $density [1] 5.857019e-04 0.000000e+00 6.029285e-05 1.162791e-03 3.316107e-03 [6] 2.532300e-03 1.559001e-03 6.115418e-04 1.205857e-04 4.306632e-05 [11] 8.613264e-06 $mids [1] 50 150 250 350 450 550 650 750 850 950 1050 $xname [1] "E" $equidist [1] TRUE attr(,"class") [1] "histogram" > hist(E) 6) > data(cars) > attach(cars) > help(cars) > x<-speed > y<-dist > plot(x,y) > mx<-mean(x) > my<-mean(y) > n<-length(x) > varx<-sum(x^2)/n-mx^2 > vary<-sum(y^2)/n-my^2 > cov<-sum(x*y)/n-mx*my > b<-cov/varx > a<-my-b*mx > abline(a,b) >a [1] -17.57909 >b [1] 3.932409 > sx<-sqrt(varx) 118 > sy<-sqrt(vary) > r<-cov/(sx*sy) >r [1] 0.8068949 > ystim<-a+b*x > res<-y-ystim > devres<-sum(res^2) > devy<-vary*n > R2<-1-devres/devy > R2 [1] 0.6510794 # oppure > retta<-lm(y~x) > summary(retta) Call: lm(formula = y ~ x) Residuals: Min 1Q Median 3Q Max -29.069 -9.525 -2.272 9.215 43.201 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) -17.5791 6.7584 -2.601 0.0123 * x 3.9324 0.4155 9.464 1.49e-12 *** --Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1 Residual standard error: 15.38 on 48 degrees of freedom Multiple R-Squared: 0.6511, Adjusted R-squared: 0.6438 F-statistic: 89.57 on 1 and 48 DF, p-value: 1.490e-12 7) # eliminare dal file di dati le righe di commento > z<-read.table("water.txt",header=TRUE) > attach(z) > x<-Pressure > y<-BPt > plot(x,y) > mx<-mean(x) > my<-mean(y) > n<-length(x) > varx<-sum(x^2)/n-mx^2 > vary<-sum(y^2)/n-my^2 > cov<-sum(x*y)/n-mx*my > b<-cov/varx > a<-my-b*mx 119 >a [1] 155.2965 >b [1] 1.901784 > abline(a,b) > sx<-sqrt(varx) > sy<-sqrt(vary) > r<-cov/(sx*sy) >r [1] 0.9972102 > ystim<-a+b*x > res<-y-ystim > devres<-sum(res^2) > devy<-vary*n > R2<-1-devres/devy > R2 [1] 0.9944282 # oppure: > retta<-lm(y~x) > summary(retta) Call: lm(formula = y ~ x) Residuals: Min 1Q Median 3Q Max -1.22687 -0.22178 0.07723 0.19687 0.51001 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 155.29648 0.92734 167.47 <2e-16 *** x 1.90178 0.03676 51.74 <2e-16 *** --Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1 Residual standard error: 0.444 on 15 degrees of freedom Multiple R-Squared: 0.9944, Adjusted R-squared: 0.9941 F-statistic: 2677 on 1 and 15 DF, p-value: < 2.2e-16 8) # eliminare dal file di dati le righe di commento > z<-read.table("hospital.txt",header=TRUE) > attach(z) > x<-Height > y<-Pulse > plot(x,y) > mx<-mean(x) > my<-mean(y) 120 > n<-length(x) > varx<-sum(x^2)/n-mx^2 > vary<-sum(y^2)/n-my^2 > cov<-sum(x*y)/n-mx*my > b<-cov/varx > a<-my-b*mx >a [1] 46.90693 >b [1] 0.2097740 > abline(a,b) > sx<-sqrt(varx) > sy<-sqrt(vary) > r<-cov/(sx*sy) >r [1] 0.2182248 > ystim<-a+b*x > res<-y-ystim > devres<-sum(res^2) > devy<-vary*n > R2<-1-devres/devy > R2 [1] 0.04762205 > retta<-lm(y~x) > summary(retta) Call: lm(formula = y ~ x) Residuals: Min 1Q Median 3Q Max -16.666 -4.876 -1.520 3.424 33.012 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 46.9069 22.8793 2.050 0.0458 * x 0.2098 0.1354 1.549 0.1279 --Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1 Residual standard error: 8.811 on 48 degrees of freedom Multiple R-Squared: 0.04762, Adjusted R-squared: 0.02778 F-statistic: 2.4 on 1 and 48 DF, p-value: 0.1279 9) > z<-read.table("ring.txt") > attach(z) > x<-V1 > y<-V2 121 > plot(x,y) > retta<-lm(y~x) > retta Call: lm(formula = y ~ x) Coefficients: (Intercept) x -259.6 3721.0 > summary(retta) Call: lm(formula = y ~ x) Residuals: Min 1Q Median 3Q Max -85.1586 -21.4483 -0.8688 18.9722 79.3697 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) -259.63 17.32 -14.99 <2e-16 *** x 3721.02 81.79 45.50 <2e-16 *** --Signif. codes: 0 `***' 0.001 `**' 0.01 `*' 0.05 `.' 0.1 ` ' 1 Residual standard error: 31.84 on 46 degrees of freedom Multiple R-Squared: 0.9783, Adjusted R-squared: 0.9778 F-statistic: 2070 on 1 and 46 DF, p-value: < 2.2e-16 10) > z<-read.table("phone.txt") > attach(z) > cor(V2,V3) [1] -0.6656528 > # la risposta è SI 11) >z<-read.table("rent.txt") >attach(z) >y<-V1 >x<-V2 >plot(x,y) >n<-length(x) >mx<-mean(x) >my<-mean(y) >varx<-(sum((x-mx)^2))/n 122 >cov<-sum((x-mx)*(y-my))/n >b<-cov/varx >a<-my-b*mx > mx [1] 1135.32 > my [1] 1386.4 > varx [1] 79989.9 > cov [1] 85200.75 >a [1] 177.1208 >b [1] 1.065144 #retta di regressione: > abline(a,b) > yp<-a+b*1000 > yp [1] 1242.265 > ystim<-a+b*x # oppure > predict(retta,data.frame(x=1000)) [1] 1242.265 > predict(retta) 1 2 3 4 5 6 7 8 1082.4931 1721.5795 1332.8020 1489.3781 941.8941 1758.8595 1387.1243 950.4153 9 10 11 12 13 14 15 16 922.7216 1195.3984 1348.7791 1545.8307 2291.4315 1635.3028 1428.6649 1481.9221 17 18 19 20 21 22 23 24 1503.2250 1518.1370 1402.0363 1131.4898 1626.7817 1284.8705 981.3045 1242.2647 25 1455.2935 > res<-y-ystim > r<-cor(x,y) >r [1] 0.8500608 > R2<-r^2 > R2 [1] 0.7226034 123 SOLUZIONI ESERCIZI MODULO 2 1) > x<-c(114,78,96,137,78,103,117,126,86,99,114,72,104,73,86) > n<-length(x) > mx<-mean(x) > s2<-var(x) > #lc<-0.95 > #a<-0.05 > li<-mx-qt(.975,n-1)*sqrt(s2/n) > ls<-mx+qt(.975,n-1)*sqrt(s2/n) > cat("(",li,":",ls,")\n") ( 87.76956 : 109.9638 ) # oppure > t.test(x) One Sample t-test data: x t = 19.1084, df = 14, p-value = 1.994e-11 alternative hypothesis: true mean is not equal to 0 95 percent confidence interval: 87.76956 109.96377 sample estimates: mean of x 98.86667 >X~N 2) > m0<-675 > sqm<-75 > n<-30 > m<-625 > # H0:mu=m0 > # H1:mu<m0 > z<-(m-m0)/(sqm/sqrt(n)) >z [1] -3.651484 > qnorm(.01) [1] -2.326348 > pnorm(-3.651484) [1] 0.0001303647 > rifiutiamo H0 3) > dbinom(0,10,0.2) 124 [1] 0.1073742 > pbinom(2,10,0.2,lower.tail=FALSE)+dbinom(2,10,0.2) [1] 0.6241904 > pbinom(2,10,0.2) [1] 0.6777995 4) > x<-c(31, 35, 36, 34, 40, 38, 68, 46, 28, 33, 21, 34, 30, 42, 20, 34, 63, 22, 38, 28) # caricare la funzione "testvar" (cfr.par. 5.5.3) > source("testvarianza.txt") > var(x) [1] 147.4184 > var0<-200 > testvar(x,var0,"less") Ipotesi nulla => H0 : var = 200 Varianza campionaria: 147.4184 , statistica test: 14.00475 p-value: 0.2165857 , livello del test: 0.05 Quantile Chi-quadrato: 10.11701 con 19 gdl Ipotesi alternativa => H1 : var < 200 Decisione: non si rifuta H0 5) > X<-c(4,6) > Y<-c(7,9,11,12) > pXY<-matrix(rep(0,8),2,4) > pXY [,1] [,2] [,3] [,4] [1,] 0 0 0 0 [2,] 0 0 0 0 > pXY[1,1]<-0.1 > pXY[1,2]<-0.1 > pXY[1,3]<-0.2 > pXY[1,4]<-0.1 > pXY[2,1]<-0.2 > pXY[2,2]<-0.1 > pXY[2,3]<-0.1 > pXY[2,4]<-0.1 > pXY [,1] [,2] [,3] [,4] [1,] 0.1 0.1 0.2 0.1 [2,] 0.2 0.1 0.1 0.1 > rownames(pXY)<-X > colnames(pXY)<-Y > pXY 7 9 11 12 4 0.1 0.1 0.2 0.1 6 0.2 0.1 0.1 0.1 > sum(pXY) 125 [1] 1 > #distribuzioni di probabilità marginali > pX<-margin.table(pXY,1) > pY<-margin.table(pXY,2) > pX 4 6 0.5 0.5 > pY 7 9 11 12 0.3 0.2 0.3 0.2 > pX[1]*pY[1] 4 0.15 > # X e Y non sono stocasticamente indipendenti, poichè non è p(x,y)=p(x)p(y) > EX<-sum(X*pX) > EX [1] 5 > varX<-sum((X-EX)^2*pX) > varX [1] 1 > EY<-sum(Y*pY) > varY<-sum((Y-EY)^2*pY) > Esum<-EX+EY > covXY<-sum(X%o%Y*pXY)-EX*EY > varsum<-varX+varY+2*covXY > Esum [1] 14.6 > varsum [1] 4.04 6) > x<-c(1150.25,1352.67,983.45,1365.11,942.71,1577.77,330.00,872.37,1126.57,1184.17,1046.35, 1110.50,1050.86,851.60,1459.56,1252.01,373.91,1047.40,1064.46,1018.23,996.92,941.96,767.37, 1598.57,1598.66,1343.29,1617.73,1300.76,1013.27,1402.59,1069.32,1108.94,1326.19,1074.86, 975.86) > n<-length(x) > mx<-mean(x) > s2<-var(x) > #lc<-0.95 > #a<-0.05 > li<-mx-qt(.975,n-1)*sqrt(s2/n) > ls<-mx+qt(.975,n-1)*sqrt(s2/n) > cat("(",li,":",ls,")\n") ( 1021.165 : 1224.334 ) # oppure: > t.test(x) One Sample t-test 126 data: x t = 22.4611, df = 34, p-value = < 2.2e-16 alternative hypothesis: true mean is not equal to 0 95 percent confidence interval: 1021.165 1224.334 sample estimates: mean of x 1122.750 >X~N 7) > p<-35/200 >p [1] 0.175 > n<-200 > li<-p-qnorm(.95)*sqrt(p*(1-p)/n) > ls<-p+qnorm(.95)*sqrt(p*(1-p)/n) > cat("(",li,":",ls,")\n") ( 0.1308065 : 0.2191935 ) # oppure: > x<-n*p >x [1] 35 > prop.test(x,n,corr=FALSE) 1-sample proportions test without continuity correction data: x out of n, null probability 0.5 X-squared = 84.5, df = 1, p-value = < 2.2e-16 alternative hypothesis: true p is not equal to 0.5 95 percent confidence interval: 0.1286052 0.2336443 sample estimates: p 0.175 > prop.test(x,n) 1-sample proportions test with continuity correction data: x out of n, null probability 0.5 X-squared = 83.205, df = 1, p-value = < 2.2e-16 alternative hypothesis: true p is not equal to 0.5 95 percent confidence interval: 0.1264402 0.2363814 sample estimates: 127 p 0.175 > binom.test(x,n) Exact binomial test data: x and n number of successes = 35, number of trials = 200, p-value = < 2.2e-16 alternative hypothesis: true probability of success is not equal to 0.5 95 percent confidence interval: 0.1250244 0.2348840 sample estimates: probability of success 0.175 8) > x<-scan("tea.txt") Read 105 items > mean(x) [1] 5.51 > t.test(x,mu=5.5,alternative="g") One Sample t-test data: x t = 0.9105, df = 104, p-value = 0.1823 alternative hypothesis: true mean is greater than 5.5 95 percent confidence interval: 5.491772 Inf sample estimates: mean of x 5.51 > # No, p-value>0.01 > t.test(x,conf.level=0.99) One Sample t-test data: x t = 501.6919, df = 104, p-value = < 2.2e-16 alternative hypothesis: true mean is not equal to 0 99 percent confidence interval: 5.481182 5.538818 sample estimates: mean of x 5.51 128 9) > ppois(5,6) [1] 0.4456796 > dpois(5,6) [1] 0.1606231 > 1-ppois(4,6) [1] 0.7149435 > dpois(4,6)+dpois(5,6) [1] 0.2944758 10) > p<-0.05 > n<-20 > M<-n*p > var<-n*p*(1-p) >M [1] 1 > var [1] 0.95 > # P(X=0) > dbinom(0,n,p) [1] 0.3584859 > # P(X>=2) > 1-(dbinom(0,n,p)+dbinom(1,n,p)) [1] 0.2641605 > #oppure > 1-pbinom(1,n,p) [1] 0.2641605 > # P(X<=3) > pbinom(3,n,p) [1] 0.9840985 11) > x<-scan("bank.txt") Read 15 items > mx<-mean(x) > mx [1] 4.286667 > m0<-5 > t.test(x,mu=m0,alternative="l") One Sample t-test data: x 129 t = -1.6867, df = 14, p-value = 0.05691 alternative hypothesis: true mean is less than 5 95 percent confidence interval: -Inf 5.03157 sample estimates: mean of x 4.286667 > # NO, p-value>0.05 > var0<-2 > var(x) [1] 2.682995 > n <- length(x) >n [1] 15 > stat <-(n-1)*var(x)/var0 > stat [1] 18.78097 > alpha<-0.01 > alpha [1] 0.01 > soglia <-qchisq(1-alpha, df=n-1) > soglia [1] 29.14124 > # stat<soglia, non si rifuta H0 12) l1<-0.2 > ppois(2,l1) [1] 0.9988515 > l2<-l1*2 > 1-(ppois(1,l2)-dpois(1,l2)) [1] 0.3296800 > l3<-l1*50 > ppois(15,l3)-ppois(4,l3) [1] 0.922007 13) > x<-scan("plastic.txt") Read 50 items > mean(x) [1] 267.64 > m0<-260 > t.test(x,mu=m0,alternative="g") One Sample t-test data: x 130 t = 2.2103, df = 49, p-value = 0.01589 alternative hypothesis: true mean is greater than 260 95 percent confidence interval: 261.8448 Inf sample estimates: mean of x 267.64 >X~N > p-value=0.01589<0.05, quindi rifiutiamo H0 131