Università degli Studi di Torino Ennio Davide Isaia Linguaggio R e applicazioni statistiche a.a. 2000-2001 Dipartimento di Statistica e Matematica Applicata “Diego de Castro” È senza dubbio inevitabile che questi appunti presentino errori materiali; Sarò grato a tutti coloro, e specialmente agli Studenti, che vorranno segnalarci qualunque problema, dai più banali errori tipografici alle oscurità nell’esposizione. Avvertenza Tutti i diritti di questa pubblicazione sono degli autori. Viene consentita la riproduzione integrale di questa pubblicazione a titolo gratuito. Altresı̀ è permessa, sempre a titolo gratuito, l’utilizzazione di parti di questa pubblicazione in altra opera all’inderogabile condizione che ne venga citata la provenienza e che della nuova opera nella sua interezza vengano consentite la riproduzione integrale a titolo gratuito e l’utilizzazione di parti a queste stesse condizioni. L’uso di questa pubblicazione in qualsiasi forma comporta l’accettazione integrale e senza riserve di quanto sopra. Dipartimento di Statistica e Matematica Applicata “Diego de Castro” Corso Unione Sovietica, 218/bis 10134, Torino (Italy) c 2000–2009 � Capitolo 1 Introduzione ad R R, parente di S-Plus ed erede di S, è un ambiente integrato che consente di elaborare dati, eseguire calcoli e creare rappresentazioni grafiche; dotato di un linguaggio di programmazione ad alto livello, con esso è possibile eseguire operazioni assai complesse con poche linee di comandi e, pertanto, si dimostra uno strumento estremamente potente che permette di analizzare e risolvere problemi specifici attinenti a diversi settori scientifici. Le sue caratteristiche peculiari, ai fini statistici, sono rappresentate dalla possibilità di elaborazione di grandi quantità di dati, la vasta disponibilità di operatori per il calcolo matriciale e vettoriale nonché l’enorme disponibilità di librerie (“package”) matematiche, statistiche e grafiche. R, inoltre, è un software completamente gratuito e continuamente aggiornato, disponibile per piattaforme Unix (FreeBSD, NetBSD, Linux, Irix, Solaris, OSF/1, AIX, HPUX), Windows 9x/NT nonché MacOS. La URL ufficiale per il progetto R è: http://www.r-project.org dove è possibile prelevare l’ultima versione di R, un manuale ufficiale di riferimento a cura del R Core Team (2000) nonché una vasta gamma di “packages” aggiuntivi; un’interessante lista di “Frequently Asked Questions”, The R FAQ a cura di Kurt Hornik, è reperibile all’indirizzo http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html. Una volta acquisito il programma e prescindendo dall’installazione/compilazione a seconda della piattaforma di destinazione, l’applicativo ed altri file, tra cui .Renviron saranno raccolti in un’unica directory, ad esempio <drive>\...\R Home Directory, la quale, a sua volta, conterrà altre directory, tra le quali: • \library: contenente le librerie (“package”) di base nonché quelle di interesse per l’utente, ad esempio: \library\base Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 \library\ctest ... \library\modreg nelle quali sono posti i file, in formato ACII, CONTENTS, DESCRIPTION, INDEX e TITLE; inoltre, ciascuna di esse ha una struttura comune, articolata in altre directory tra cui citiamo: – \R: contenente il file sorgente, in formato ACII, delle funzioni definite per il “package” stesso; – \data: contenente alcuni archivi di dati a cui viene spesso fatto riferimento nelle finestre di “help” di R stesso. – \help: contenente, in formato compresso (.zip, .tar, ...) i file di help in linea; – \html, \latex: ove sono posti i file di help in formato html e LATEX. • \doc: contenente, organizzati in corrispondenti sotto-directory, alcuni documenti di aiuto. A tal proposito è bene tenere a mente che essenziale ai fini di un corretto funzionamento dell’applicativo è la presenza del “package” base, contenente in \library\base\R il file di definizione dei principali comandi (base), nonché il file Rprofile di definizione dell’ambiente di lavoro. 1.1 L’ambiente di lavoro Una volta lanciato il programma compare la finestra R GUI 1 , dove potranno essere impartiti i comandi e saranno visualizzati i risultati delle elaborazioni o gli eventuali messaggi di errore; tale finestra dispone di menu (File, Edit, Misc, Windows, Help) autoesplicativi. Nel seguito lavoreremo unicamente attreverso la finestra R GUI, cioè impartiremo, dopo il classico prompt >, i comandi in sequenza oppure li sottoporremo in modalità “batch”. All’avvio R GUI mostra alcune informazioni, quali la versione di R che si sta usando ed alcuni comandi chiave per iniziare o chiudere una sessione di lavoro. Un comando, a cui ci abitueremo, è help(argomento); ad esempio help() chiede ad R di aprire una nuova finestra che contiene una breve guida in linea dal titolo 1 Sotto Unix compare la finestra R Console, il cui aspetto è piuttosto spartanto. Sotto MacOS e Linux-ppc comapre la fienstra R Console, delt tutto analoga alla finestra R GUI che caratterizza i sistemi Windows9x/NT e Linux. 2 E. D. Isaia, Linguaggio R e applicazioni statistiche “R Information”. Tale finestra offre una descrizione dettagliata del comando e, più importante, riporta in fondo una serie di esempi che, mediante “copia e incolla”, possono essere inseriti sulla Console. Un secondo comando utile per avvicinarsi ad R è demo(), il quale, a seconda della versione installata, potrebbe porgere: > demo() Use ‘demo(topic)’ where choices for argument ‘topic’ are: topics [1,] "graphics" [2,] "image" [3,] "lm.glm" [4,] "glm.vr" [5,] "nlm" [6,] "recursion" [7,] "scoping" [8,] "is.things" [9,] "dyn.load" In sostanza R suggerisce di utilizzare il comando nella forma demo(topics), dove topic è uno degli argomenti proposti; ad esempio demo(graphics). Una terza finestra disponibile è la Graphics Window ove verranno visualizzati, appunto, i grafici via via richiesti. Questa abitualmente non viene aperta all’avvio di R, ma viene attivata allorché si impartisce un comando che prevede un output grafico. L’utente può in ogni caso forzare la sua attivazione con il comando X11(), windows() o macintosh() a seconda della piattaforma Unix, Windows9x/NT o MacOS rispettivamente. È bene tenere a mente che per default l’area di lavoro corrisponde alla directory \R Home Directory; tale situazione può essere modificata in qualsiasi istante ricorendo al comando setwd(<directory>). Cosı̀, ad esempio, immaginando un’installazione su piattaforma Windows, potremmo avere: > getwd() [1] "C:\Programs\R" > setwd("C:\Progetti") NULL > getwd() [1] "C:\Progetti" > setwd(R.home()) NULL > getwd() 3 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 [1] "C:\Programs\R" Al momento di abbandonare R, ci viene richiesto se desideriamo registrare quanto svolto nella corrente sessione di lavoro: > q() Save workspace image? [y/n/c]: In caso affermativo, l’intero “workspace” verrà registrato, per default, sul file Rdata; in tal modo sarà possibile “ritornare al punto” semplicemente lancianto R tramite Rdata. 1.2 Primi passi in R Le entità con cui lavora R vengono dette oggetti; questi vengono identificati tramite un nome, a discrezione dell’utente, che deve iniziare con un carattere alfabetico e non può contenere spazi bianchi nè i caratteri @, #, $, _, mentre è ammesso l’uso del punto (.) quale separatore tra i caratteri. Se gli elementi di un oggetto presentano tutti la stessa modalità, numerica, alfanumerica, logica oppure complessa, l’oggetto stesso viene detto elementare. Tali oggetti, a loro volta, possono essere dotati di una struttura di matrice, e ciò nel senso algebrico del termine, oppure possono concorrere a creare quelli che nel seguito chiameremo oggetti complessi. Ciò premesso, dedichiamo i paragrafi che seguono alla descrizione di come definire e manipolare oggetti con struttura elementare, di matrice o complessa ed eseguire su di essi alcune semplici operazioni, ricorrendo a funzioni predefinite ovvero creadone altre ad hoc. 1.2.1 Creazione di oggetti elementari La creazione di un qualsiasi oggetto avviene ricorrendo al comando di assegnazione <- e non, come è norma abituale con altri linguaggi di programmazione, tramite il simbolo =, a cui segue, in linea di massima, entro parentesi tonde precedute dal prefisso c, acronimo di combine, l’elenco dei suoi elementi, ciasuno dei quali separato da una virgola. Qualora l’oggetto possedesse modalità alfanumerica, il suoi elementi debbono essere racchiusi entro virgolette ("). Ciò premesso, la visualizzazione degli elementi di un oggetto può avvenire digitandone il nome oppure, in fase di definizione, racchiudendone l’istruzione entro parentesi tonde. Esempio 1.2.1 Ci proponiamo di creare tre oggetti elementari e di visualizzarne il contenuto; più precisamente: 4 E. D. Isaia, Linguaggio R e applicazioni statistiche — x contenente il solo elemento numerico 17: > x<-c(17) > x [1] 17 — y i cui elementi corrispondono agli interi 10, 13, 17, 20: > (y<-c(10,13,17,20)) [1] 10 13 17 20 — alpha che conterrà tre caratteri alfanumerici > (alpha<-c("Valor medio","Mediana","Varianza")) [1] "Valor medio" "Mediana" "Varianza" ♥ A questo punto, possiamo introdurre le seguenti istruzioni di utilità assai generale: • ls(): visualizza l’elenco degli oggetti definiti in una sessione di lavoro 2 . • ls.str(): porge un breve“resoconto” circa la struttura degli oggetti definiti nella corrente sessione di lavoro. Informazioni dettagliate circa uno specifico oggetto, si ottengono con il comando str(oggetto); • mode(oggetto): restituisce, sottoforma di stringa, la modalità dell’oggetto indicato; • rm(oggetto1, ...,oggetton): consente la rimozione degli oggetti specificati. Desiderando rimuovere tutti gli oggetti definiti nel corso di una sessione di lavoro si può ricorrere all’istruzione rm(list=ls()). La rimozione del solo contenuto di un oggetto avviene tramite l’assegnazione oggetto<-NULL Esempio 1.2.2 Con riferimento ai tre oggetti introdotti all’Esempio 1.2.1, si osservi il comportamento, autoesplicativo, delle istruzioni: > ls.str() alpha : chr [1:3] "Valor medio" "Mediana" "Varianza" x : num 17 y : num [1:4] 10 13 17 20 > mode(alpha) [1] "character" > (y<-NULL) 2 In alternativa si può ricorrere al comando objects(). 5 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 NULL > ls() [1] "alpha" "x" > rm(x) > ls() [1] "alpha" "y" > rm(y,alpha) > ls() character(0) "y" ♥ Può a volte capitare di volere elencare (o rimuovere) solo alcuni degli oggetti definiti durante una sessione di lavoro; ciò avviene ricorrendo all’opzione pattern=, propria dei comandi ls(), rm() e ls.str(). A tal riguardo, si osservi il comportamento delle istruzioni: > C02<-c(0.011,0.012,0.013,0.012) > fattoreA<-c(1,2,1,2) > fattoreB<-c(1,2,1,2) > ls() [1] "C02" "fattoreA" "fattoreB" > ls.str(pattern="fat") fattoreA : num [1:4] 1 2 1 2 fattoreB : num [1:4] 1 2 1 2 > rm(list=ls(pattern="fat")) > ls() [1] "C02" L’opzione pattern=, come la maggior parte delle opzioni R, può essere abbreviata, qualora non sussistano ambiguità, ai primi tre caratteri; nel seguito tuttavia, per motivi di chiarezza espositiva, ricorreremo sempre alla forma estesa. 1.2.2 Creazione di oggetti contenenti sequenze regolari La creazione di oggetti contenenti “sequenze regolari” di elementi numerici o alfanumerici può avvenire ricorrendo ai comandi: • c(n1:n2): crea una sequenza di interi consecutivi da n1 a n2, in ordine crescente se n1 < n2, in ordine decrescente altrimenti; • seq(n1,n2,by=passo): crea una sequenza di numeri consecutivi da n1 a n2 con incrementi pari a quanto specificato in passo, in ordine crescente se n1 < n2, in 6 E. D. Isaia, Linguaggio R e applicazioni statistiche ordine decrescente altrimenti. Qualora l’opzione by=passo fosse omessa e n1 e n2 fossero interi, l’istruzione verrebbe ad essere equivalente a c(n1:n2). Un’alternativa a by= è rappresentata dall’opzione length=, con la quale si stabilisce appunto la lunghezza della sequenza o, meglio, il numero dei suoi elementi; • rep(k:n): crea un oggetto contenente i valori, numerici o alfanumerici, specificati in k ripetuti n volte; • letters[k:n] o LETTERS[k:n]: creano una sequenza di lettere, minuscole e maiuscole rispettivamente, dell’alfabeto latino comprese tra k ed n. Altri comandi specifici, quali gl(), expand.grid(), ppoints() e sequence(), verranno presentati al paragrafo 1.2.6. Esempio 1.2.3 Creazione e visualizzazione dell’oggetto x che conterrà i primi dieci interi positivi: > (x<-c(1:10)) [1] 1 2 3 4 5 6 7 8 9 10 Si noti che saremmo giunti allo stesso risultato ricorrendo all’istruzione seq(): > (x<-seq(1,10)) [1] 1 2 3 4 5 6 7 8 9 10 ♥ Esempio 1.2.4 Creazione e visualizzazione dell’oggetto x che conterrà 11 numeri progressivi da 20 a 21 con passo 0.10: > (x<-seq(20,21,by=0.10)) [1] 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 Allo stesso risultato saremmo pervenuti con il comando: > (x<-seq(20,21,length=11)) [1] 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 ♥ Esempio 1.2.5 Creazione dell’oggetto x che conterrà, nell’ordine, 3 elementi a valore nullo e 4 elementi a valore unitario. > (x<-c(rep(0,3),rep(1,4))) [1] 0 0 0 1 1 1 1 7 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 ♥ Esempio 1.2.6 Visualizzazione delle stringhe "Conforme" e "Difettoso" ripetute la prima tre volte e la seconda una sola volta: > c(rep("Conforme",3),rep("Difettoso",1)) [1] "Conforme" "Conforme" "Conforme" "Difettoso" ♥ Esempio 1.2.7 Creazione e visualizzazione dell’oggetto alfabeto che conterrà le prime sette lettere, in minuscolo, dell’alfabeto (latino): > (alfabeto<-letters[1:7]) [1] "a" "b" "c" "d" "e" "f" "g" Si osservi il comportamento delle istruzioni: > LETTERS[1:7] [1] "A" "B" "C" "D" "E" "F" "G" > paste(letters[1:3],sep="",collapse="+") [1] "a+b+c" > paste("Fattore",letters[1:3],sep="",collapse="+") [1] "Fattorea+Fattoreb+Fattorec" ♥ 1.2.3 Manipolazione di oggetti elementari In R esistono svariati comandi che consentono la manipolazione di oggetti, numerici o alfanumerici; tra essi val qui la pena citare i seguenti di utilità generale: • append(x,y): aggiunge agli elementi dell’oggeto x gli elementi di y; • c(x,y): crea un nuovo oggetto a partire da due oggetti x e y; • paste(x,y): crea un un nuovo oggetto contenente, sottoforma alfanumerica, gli elementi appaiati degli oggetti x e y; l’opzione sep="simbolo" consente di separare i diversi elementi con il simbolo desiderato, mentre l’opzione collapse="simbolo" permette di separare i singoli risultati con il simbolo prescelto; • rev(x): posiziona in senso inverso gli elementi di x; • sort(x): ordina in senso crescente gli elementi di x; altrimenti; 8 E. D. Isaia, Linguaggio R e applicazioni statistiche • unique(x): restituisce gli elementi non ripetuti contenuti in x. • x[posizione1,..,posizionen]: estrae dall’oggeto x gli elementi che occupano la posizione specificata in posizione1,..,posizionen; Altri comandi verranno presentati al paragrafo 1.2.6. Esempio 1.2.8 Ordinamento in senso crescente degli elementi di x<-c(10:1): > sort(x) [1] 1 2 3 4 5 6 7 8 9 10 5 6 7 8 9 10 o, equivalentemente: > rev(x) [1] 1 2 3 4 A proposito di rev(), si noti che: > rev(c(10,11,9)) [1] 9 11 10 e ciò coerentemente con quanto detto a proposito. ♥ Esempio 1.2.9 Creazione di un nuovo oggetto a partire da due oggetti definiti: > x<-c(1:5) > y<-rev(x) > (z<-c(x,y)) [1] 1 2 3 4 5 5 4 3 2 1 ♥ Esempio 1.2.10 Creazione, a partire da due oggetti, di un nuovo oggetto che contiene, sottoforma alfanumerica, gli elementi appaiati degli oggetti iniziali. > x<-c(1:5) > y<-c(-5:-1) > paste(x,y) [1] "1 -5" "2 -4" "3 -3" "4 -2" "5 -1" Si ossservi che, coerentemente: > paste(x) [1] "1" "2" "3" "4" "5" Si noti, ancora, il comportamento dei seguenti comandi: 9 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > paste(y,x,sep="*") [1] "-5*1" "-4*2" "-3*3" "-2*4" "-1*5" > paste(y,x,sep="*",collapse="<->") [1] "-5*1<->-4*2<->-3*3<->-2*4<->-1*5" ♥ Esempio 1.2.11 Estrazione dall’oggetto x, che contiene gli interi consecutivi da 1 a 20, degli elementi che occupano la terza e la dodicesima posizione. > x<-c(1:20) > x[3] [1] 3 > x[12] [1] 12 ♥ Esempio 1.2.12 Creazione, a partire dall’oggetto x, che contiene gli interi consecutivi da 10 a 20, dell’oggetto y che conterrà i tre elementi che occupano la prima, la terza e la sesta posizione in x. > (x<-c(10:20)) [1] 10 11 12 13 14 15 16 17 18 19 20 > (y<-x[c(1,3,6)] ) [1] 10 12 15 ♥ Esempio 1.2.13 Creazione dell’oggetto z che conterrà, nell’ordine, i primi tre elementi di x, i due elementi di y quindi i restanti elementi di x. > (x<-c(10:17)) [1] 10 11 12 13 14 15 16 17 > (y<-c(300,400)) [1] 300 400 > (z<-append(x, y, after=3)) [1] 10 11 12 300 400 13 14 15 16 17 ♥ Esempio 1.2.14 Eliminazione ed ordinamento crescente degli elementi ripetuti di un oggetto. > (x<-c(c(5:8),c(1:7))) [1] 5 6 7 8 1 2 3 4 5 6 7 > sort(unique(x)) [1] 1 2 3 4 5 6 7 8 10 E. D. Isaia, Linguaggio R e applicazioni statistiche ♥ Esempio 1.2.15 Creazione, a partire dall’oggetto x che contiene 3 elementi a valore nullo e 4 elementi a valore unitario, dell’oggetto sesso che conterrà l’etichetta Femmina se x=0 oppure Maschio se x=1. > (x<-c(rep(0,3),rep(1,4))) [1] 0 0 0 1 1 1 1 > (sex<-c(rep("Femmina",3),rep("Maschio",4))) [1] "Femmina" "Femmina" "Femmina" "Maschio" "Maschio" "Maschio" "Maschio" Un’alternativa è offerta dal ricorso al comando names(); ad esempio: > (x<-c(rep(0,3),rep(1,4))) [1] 0 0 0 1 1 1 1 > (names(x)<-c(rep("Femmina",3),rep("Maschio",4))) [1] "Femmina" "Femmina" "Femmina" "Maschio" "Maschio" "Maschio" "Maschio" Per maggiori dettagli sul comando names(), cfr. paragrafo 1.2.6. 1.2.4 ♥ Operatori aritmetici e funzioni matematiche Sugli oggetti elementari con modalità numerica è possible eseguire le più comuni operazioni aritmetiche, quali la somma (+), il prodotto (*), la divisione (/), l’elevamento a potenza (^), proprie di un qualsiasi linguaggio di programmazione. Esempio 1.2.16 Dati i due oggetti x e y ad elemeti numerici: > x<-seq(1:5) > y<-x^2 le istruzioni che seguono si commentano da sè: > x-(1/y) [1] 0.000000 1.750000 2.888889 3.937500 4.960000 > 100*(x+y)^(-1) [1] 50.000000 16.666667 8.333333 5.000000 3.333333 > y^(.5)+x [1] 2 4 6 8 10 ♥ Vale qui la pena accennare alla presenza di due particolari operatori, %% e %/%, il cui impiego, a volte utile, è illustrato dagli esempi che seguono. Esempio 1.2.17 Posto che l’oggetto x contenga gli interi consecutivi da 1 a 10, ci proponiamo di: 11 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — individuare quali di essi è divisibile per 2. A tal fine possiamo considerare il comando x%%2 che porge il resto della divisione di ciascun elemento di x per 2: > x<-c(1:10) > x%%2 [1] 1 0 1 0 1 0 1 0 1 0 — calcolare la parte intera della divisione tra ciascun elemento di x e 2. A tal fine sopperisce il comando x%/%2, infatti: > x<-c(1:10) > x%/%2 [1] 0 1 1 2 2 3 3 4 4 5 Quanto alle funzioni matematiche, tra le quali figurano exp(), log(), log10(), log2(),..., sin(), cos(), tan(), asin(), acos(), atan(), sqrt(), abs()..., è impensabile offrirne qui un’elenco seppur parziale; alcune di esse, di interesse sotto il profilo statistico, sono presentate al paragrafo che segue, mentre altre ancora saranno introdotte più oltre allorché verranno affrontati problemi specifici. Accenniamo, infine, alla presenza di particolari funzioni che cosentono di eseguire le più comuni operazioni su insiemi: • union(x,y): restituisce l’insieme costituito dall’unione degli insiemi x e y; • intersect(x,y): restituisce l’insieme costituito dall’intersezione degli insiemi x e y; • setdiff(x,y): rstituisce l’insieme costituito dalla differenza tra insiemi x e y; • setequal(x,y): restituisce il valore logico TRUE se gli insiemi contengono gli stessi elementi, il valore logico FALSE altrimenti; • is.element(el,set): restituisce il valore logico TRUE se l’elemento in el è contenuto in set, il valore logico FALSE altrimenti. Un alias del comando è %in%. Esempio 1.2.18 Definiti gli oggetti A<-letters[1:4] e B<-letters[3:7], abbiamo: > union(A,B) [1] "a" "b" "c" "d" "e" "f" "g" > intersect(A,B) [1] "c" "d" > setdiff(A,B) [1] "a" "b" > setdiff(B,A) 12 E. D. Isaia, Linguaggio R e applicazioni statistiche [1] "e" "f" "g" > is.element(A,setdiff(A,B)) [1] TRUE TRUE FALSE FALSE > "f"%in%union(A,B) [1] TRUE > is.element("q",setdiff(letters[1:24],union(A,B))) [1] TRUE Si noti che tali operatori in ogni caso rimuovono gli elementi duplicati di un insieme. 1.2.5 ♥ Su alcune funzioni statistiche Tra le innumerevoli funzioni statistiche implementate, per il momento ci limitiamo a citare le più comuni e precisamente, posto x un’oggetto elementare con modalità numerica: • cumsum(x): restituisce la somma cumulata degli elementi di x; • length(x): restituisce il numero degli elementi 3 contneuti in x; • max(x), min(oggetto): porgono, rispettivamente, il massimo ed il minimo dei valori contenuti in x; • mean(x): calcola la media aritmetica dei valori contenuti in x; • median(x): calcola la mediana dei valori contenuti in x; • prod(x): restituisce il prodotto degli elementi di x; • quantile(x,alpha): porge il quantile di ordine alpha degli elementi di x; • sum(x): restituisce la somma degli elementi di x; • summary(x): visualizza4 il minimo, il primo quartile, la media aritmetica, la mediana, il terzo quartile ed il massimo degli elementi di x; • table(x): porge la distribuzione di frequenze assolute generata dalle osservazioni individuali registrate in x; • var(x) e sd(x): calcolano, rispettivamente, la varianza e lo scarto quadratico medio dei valori contenuti in x. È bene ricordare, sin da ora, che la varianza, e di conseguenza lo scarto quadratico medio, è calcolata come: n 1 ! (xi − µx )2 n − 1 i=1 3 4 A bene vedere trattasi di una funzione “primitiva” di impiego assai generale. Tale è il suo comportamento se applicata ad un oggetto numerico elemementare. 13 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 quindi con un numero di gradi di libertà pari a length(x)-1. Tale grandezza viene abitualmente detta varianza campionaria. • weighted.mean(xi,ni): calcola la media aritmetica dei valori contenuti in xi con pesi ni. Esempio 1.2.19 Si immagini che la rilevazione il voto conseguito all’esame di Statistica, espresso in trentesimi, conseguito da un gruppo di 20 studenti abbia fornito i risultati: 18 27 23 25 30 27 25 23 27 30 27 25 30 23 20 20 20 25 25 23 Definito l’oggetto elementare voti.stat: > voti.stat<-c(18,23,30,25,27,27,30,20,20,25,27,25,27,23,30,25,23,20,25,23) facilmente possiamo ottenere: — la distribuzione dei voti in termini di frequenze assolute: > table(voti.stat) voti.stat 18 20 23 25 27 30 1 3 4 5 4 3 nonché relative: > table(voti.stat)/length(voti.stat) voti.stat 18 20 23 25 27 30 0.05 0.15 0.20 0.25 0.20 0.15 Si osservi che, dal momento che table(voti.stat) restituisce un oggetto numerico, la media dei voti potrebbe essere calcolata ricorrendo all’istruzione: > weighted.mean(sort(unique(voti.stat)),table(voti.stat)/20) [1] 24.65 — alcune misure di tendenza centrale: % > summary(voti.stat) % Min. 1st Qu. Median % 18.00 23.00 25.00 Mean 3rd Qu. 24.65 27.00 Max. 30.00 Visto che summary(voti.stat) restituisce un oggetto composto da sei elementi, possiamo ottenere la differenza interquartilica come: 14 E. D. Isaia, Linguaggio R e applicazioni statistiche > summary(voti.stat)[5]-summary(voti.stat)[2]+. — la varianza campionaria nonché la devianza: > var(voti.stat) [1] 12.02895 > var(voti.stat)*(length(voti.stat)-1) [1] 228.55 ♥ 1.2.6 Alcune funzioni di utilità generale Dedichiamo questo paragrafo alla presentazione di alcune funzioni, oltre a quelle già citate, a cui spesso può essere fatto ricorso durante una sessione di lavoro. • abbreviate(oggetto, mln=, dot=FALSE): abbrevia gli elementi dell’oggetto specificato al una lunghezza minima pari a mln=. Ponendo dot=TRUE viene visualizzato il suffisso “.”. Ad esempio: > x<-c("Ennio","Davide","Isaia") > abbreviate(x[1:2], minl=1) Ennio Davide "E" "D" > abbreviate(x[1:2], minl=1,dot=TRUE) Ennio Davide "E." "D." • all(oggetto) consente di confrontare tutti gli elementi di un oggetto rispetto ad una condizione. Ad esempio: > x<-c(-2.2,-1.8,-1.5,-1.4,-1.2,-1.0,-0.9,-0.8,-0.7 ,0.2) > all(x>0) [1] FALSE Il suo complemento è la funzione any(oggetto). > x<-c(-2.2,-1.8,-1.5,-1.4,-1.2,-1.0,-0.9,-0.8,-0.7 ,0.2) > any(x>0) [1] TRUE 15 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 • all.names(expression) e all.vars(expression) porgono, rispettivamente, gli elementi e le variabili che compaiono nell’espressione indicata e definita via expression() o quote(). • append(oggetto, valori, after=posizione): aggiunge gli elementi contenuti in valori all’oggetto specificato, eventualmente nella posizione desiderata. Ad esempio: > x<-integer(0) > (x<-append(x,1:10)) [1] 1 2 3 4 5 6 7 8 9 10 > (x<-append(x,120,after=2)) [1] 1 2 120 3 4 5 6 7 8 9 10 Si osservi che la situazione di default prevede after=length(x). Tale comando può tornare utile qualora si desideri inserire in un oggetto gli elementi via, via generati da specifiche funzioni. • attr(oggetto,attributo): attribuisce all’oggetto indicato un particolare “attributo”. Ad esempio: > x<-c(1:10) > attr(x,"dim")<-c(2, 5) > x [,1] [,2] [,3] [,4] [,5] [1,] 1 3 5 7 9 [2,] 2 4 6 8 10 > attr(x,"dim")<-NULL > x [1] 1 2 3 4 5 6 7 8 9 10 • cat(): acronimo di “concatenate & print” trasforma gli elementi indicati quale argomento in strighe alfanumeriche e li visualizza. Il suffisso "\n" consente al cursore di ritornare in modalità “prompt” (>). Ad esempio: > x<-c(1,2,3) > a<-c("degli elementi di x") > cat("La media ",a," e’:",sum(x)/length(x),"\n") La media degli elementi di x e’: 2 > 16 E. D. Isaia, Linguaggio R e applicazioni statistiche • date(): restituisce, sottoforma alfanumerica, la data di sistema. > date() [1] "Tue Aug 28 05:16:51 2001" • deparse(oggetto): trasforma la definizione dell’oggetto specificiato in una stringa. Cosı̀, ad esempio: > a<-letters[1:3] > deparse(a) [1] "c(\"a\", \"b\", \"c\")" • diff(oggetto,lag=): calcola le differenze tra i diversi elementi di un oggetto. Ad esempio: > diff(c(10,23,21,30),1) [1] 13 -2 9 • duplicated(oggetto): indica, in forma logica, quali elementi dell’oggetto specificato quale argomento sono ripetuti. Ad esempio: > x<-c(1:4) > y<-c(2:6) > duplicated(c(paste(x),paste(rev(y)))) [1] FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE • eval(funzione): calcola il valore la funzione specificata in corrispondenza a determinati valori di interesse. Quali esempi, valgano le seguenti istruzioni: > eval(3 ^ 2 ^ 3) [1] 6561 > eval(sin(.25*pi)+cos(.25*pi)) [1] 1.414214 > sin(.25*x)+cos(2*.25*x) Error: Object "x" not found > x<-pi/2 > sin(.25*x)+cos(2*.25*x) [1] 1.089790 17 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Si vedano anche i comportamenti delle funzioni expression() e quote(). • expand.grid(x,y,z,...): crea un “data frame” (cfr. paragrafo 1.4.2) contenente tutte le combinazioni degli elementi dei vettori (o fattori) x, y, z, ... specificati. Ad esempio: > expand.grid(temperatura=seq(100,120,10),pressione=seq(1,2,1)) temperatura pressione 1 100 1 2 110 1 3 120 1 4 100 2 5 110 2 6 120 2 • expression(funzione): restituisce l’espressione di una funzione senza provvedere al calcolo automatico. Si ossservi il comportamento delle istruzioni: > (fx<-expression(x^2+2*x)) expression(x^2 + 2 * x) > eval(fx) Error in eval(expr, envir, enclos) : Object "x" not found > x<-seq(-1,1) > eval(fx) [1] -1 0 3 > all.names(expression(sin(x+y))) [1] "sin" "+" "x" "y" > all.vars(expression(sin(x+y))) [1] "x" "y" Si veda anche il comportamento della funzione quote(). • factor(oggetto,levels=(n1,...,nn)): definisce in modo diretto l’oggetto specificato quale fattore a n livelli. Un’alternativa è il ricorso a as.factor(oggetto). Sono, pertanto, comandi validi: > (temperatura<-factor(c(1,1,1,2,2,2),levels=c(1:2))) [1] 1 1 1 2 2 2 Levels: 1 2 > trattamento<-c("A","B","B","A","B","A","C","C","C") 18 E. D. Isaia, Linguaggio R e applicazioni statistiche > (trattamento<-as.factor(trattamento)) [1] A B B A B A C C C Levels: A B C • format(oggetto,...): attribuisce all’oggetto specificato un formato per una migliore visualizzazione dei suoi elementi. Per default il comando prevede l’allineamento a destra, justify="right", e un numero di decimali pari a quanto definito (cfr. paragrafo 1.9) in getOption("digits"). A commento: > (x<-c(2,15,21,25)/3) [1] 0.6666667 5.0000000 7.0000000 8.3333333 > format(x,digits=3) [1] "0.667" "5.000" "7.000" "8.333" > format(x^3,digits=3,justify="right") [1] " 0.296" "125.000" "343.000" "578.704" > alpha<-c("Valor medio","Mediana","Varianza") > format(alpha,justify="left") [1] "Valor medio" "Mediana " "Varianza " > format(alpha,justify="right") [1] "Valor medio" " Mediana" " Varianza" > format(alpha,justify="none") [1] "Valor medio" "Mediana" "Varianza" • formula("espressione"): consente di definire un nuovo oggetto con struttura tipo formula il cui impiego è principalmente riservato alle procedure di regressione (lm) e di analisi della varianza (aov). La trasformazione della struttura di un’opportuna stringa in formula avviene con il comando as.formula(striga). Alcuni esempi sono: > y > > y (formulayx<-formula("y~x")) ~ x nomi.x<-paste("x",c(1:4),sep="") (f<-as.formula(paste("y ~ ", paste(nomi.x, collapse= "+")))) ~ x1 + x2 + x3 + x4 • gl(n,k): genera in modo automatico una sequenza di interi positivi da 1 a n, ciascuno dei quali viene ripetuto k volte 5 . Il risultato ha struttura factor. Ad esempio: 5 Si noti che length(gl(n,k))=n*k. 19 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > (temperatura<-gl(2,3)) [1] 1 1 1 2 2 2 Levels: 1 2 L’opzione labels =, che per default viene posta uguale a 1:n, consente di attribuire, a discrezione dell’utente, etichette ai diversi livelli del fattore di interesse; ad esempio: > (temperatura<-gl(2,3,labels=c(120,160))) [1] 120 120 120 160 160 160 Levels: 120 160 > (sesso<-gl(2,3,labels=c("Maschio","Femmina"))) [1] Maschio Maschio Maschio Femmina Femmina Femmina Levels: Maschio Femmina • levels(fattore): indica quali sono i livelli del fattore specificato. Infatti: > temperatura<-gl(2,3,labels=c(120,160)) > sesso<-gl(2,3,labels=c("Maschio","Femmina")) > levels(temperatura) [1] "120" "160" > levels(sesso) [1] "Maschio" "Femmina" • match(x,y,nomatch=NA): confronta i due oggetti x e y e restituisce l’elenco degli elementi della loro intersezione. Gli elementi diversi sono, per default, definiti mancanti (NA). Ad esempio: > x<-c(1:10) > y<-c(7:20) > match(x,y) [1] NA NA NA NA NA NA 1 2 3 mentre: > y[match(x,y,nomatch=0)] [1] 7 8 9 10 20 4 E. D. Isaia, Linguaggio R e applicazioni statistiche • names(oggetto): trattasi di un comando assai generale che, essenzialmente, consente di attribuire etichette ai diversi elementi di un oggetto. A tal proposito, si immagini che x contenga 5 elementi numerici di cui tre a valori 0 e due a valore 1 e che si desideri attribuire l’etichetta Maschio qualora x=0 e Femmina altrimenti; le istruzioni necessarie sono: > (x<-sort(c(0,1,0,1,1))) [1] 0 0 1 1 1 > (names(x)<-c(rep("Maschio",3),rep("Femmina",2))) [1] "Maschio" "Maschio" "Maschio" "Femmina" "Femmina" L’eliminazione delle etichette attribuite ad un’oggetto avviene con il comando names(oggetto)<-NULL. Si osservi che il semplice comando names(oggetto) consente di visualizzare le etichette associate all’oggetto specificato e, come vedremo nel seguito (cfr. paragrafi 1.4.1 e 1.4.2), qualora l’oggetto fosse una “lista” o un “data frame” ne elencherebbe i nomi degli elementi. • nchar(oggetto): restituisce il numero di caratteri di ciascun elemento alfanumerico contenuto nell’oggetto specificato. Cosı̀: > a<-c("sommatoria","produttoria") > nchar(a) [1] 10 11 > sum(nchar(a)) [1] 21 • noquote(oggetto): visualizza gli elementi dell’oggetto alfanumerico specificato senza racchiuderli entro le consuete virgolette. > noquote(c(letters[1:4],rev(letters[1:4]))) [1] a b c d d c b a • ppoints(n): genera una sequenza di n numeri in accordo a (1:n-.5)/n. Quale argomento è possibile indicare un oggetto numerico. > ppoints(6) [1] 0.10 0.26 0.42 0.58 0.74 0.90 21 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Tale funzione torna utile, ad esempio, per individuare i quantili di una distribuzione. • pretty(oggetto,n=): restituisce una sequenza di n numeri tali da suddividere il range dell’oggetto specificato in altrettanti intervalli di egual ampiezza. A commento: > x<-c(10,10.5,11,12,13,13.5,16.5,17,18,20) > pretty(x,n=2) [1] 10 15 20 > pretty(x) [1] 10 12 14 16 18 • quote(oggetto): restituisce l’espressione di una funzione senza provvedere al calcolo automatico. Si ossservi il comportamento delle istruzioni: > (f<-quote((2*pi)^(-.5)*exp(-.5*x^2))) (2 * pi)^(-0.5) * exp(-0.5 * x^2) > x<-c(-1,0,1) > eval(f) [1] 0.2419707 0.3989423 0.2419707 • replace(oggetto,posizione,valori): rimpiazza gli elementi dell’oggetto specificato nella posizione indicata con i valori elencati o con gli elementi di un secondo oggetto. Ad esempio: > x<-seq(1:10) > y<-c(100,120) > replace(x,2:3,y) [1] 1 100 120 4 5 6 7 8 9 10 • round(oggetto,decimali): trasforma gli elementi dell’oggetto ad elementi numerici indicato in numeri con tante cifre decimali quante specificate in decimali: > round(seq(1:10)/seq(1,2,length=10),2) [1] 1.00 1.80 2.45 3.00 3.46 3.86 4.20 4.50 4.76 5.00 • sequence(n1:nmax): crea delle sequenze di numeri interi del tipo: n1 , n1 , n2 , n1 , n2 , n3 , . . . , n1 , n2 , . . . , nmax A tal proposito: 22 E. D. Isaia, Linguaggio R e applicazioni statistiche > sequence(1:5) [1] 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 > sequence(5:1) [1] 1 2 3 4 5 1 2 3 4 1 2 3 1 2 1 • sign(oggetto): ricodifica in -1, 0 e 1 gli elementi numerici dell’oggetto specificato a seconda che essi siano, rispettivamente, negativi, nulli o positivi. > (x<-c(seq(-3,2))) [1] -3 -2 -1 0 1 2 > sign(x) [1] -1 -1 -1 0 1 1 > sign(abs(x)) [1] 1 1 1 0 1 1 • substr(oggetto,start,stop): trasforma gli elementi dell’oggetto alfanumerico indicato in strighe con un mumero di caratteri compresi tra start e stop; ad esempio: > (x<-c("Varianza","Devianza")) [1] "Varianza" "Devianza" > substr(x,1,3) [1] "Var" "Dev" > rev(substr(x, 1,3)) [1] "Dev" "Var" Per completezza, riportiamo i seguenti tre comandi di utilità: • apropos(what,mode="any"): porge un elenco di tutti gli oggetti i cui nomi contengono quanto specificato in what e ciò, per default, indipendentemente dalla loro modalità (mode="any"): > apropos(integrate) [1] "integrate" "print.integrate" Si badi che digitando apropos(".") si otterrebbe l’elenco completo di tutti gli oggetti predefiniti in R, che sono ben 1456 (length(apropos("."))); di questi quelli che poseggono modalità di tipo "function" risultano essere 1453 (length(apropos(".",mode="function"))). 23 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 • exists("oggetto",mode="any"): controlla l’esistenza dell’oggetto specificato, indipendentemente dalla sua modalità; il risultato è di tipo logico: > exists("integrate") [1] TRUE > exists("f") [1] FALSE > f<-expression(x+2*x^2) > exists("f",mode="function") [1] TRUE • find(what,mode="any"): riporta il nome della librebria in cui si trova l’oggetto indicati in what: > find(cor) [1] "package:base" > find(cor.test) [1] "package:ctest" 1.3 Vettori e Matrici Appare del tutto naturale, ora, dedicare la nostra attenzione alla creazione e la manipolazione di oggetti che hanno struttura di vettore o di matrice e ciò secondo la comune accezione dell’algebra lineare. È comunque bene tenere a mente che abitualmente nel linguaggio informatico una qualsiasi stringa di caratteri (numerici o alfanumerici) viene detta vettore. Tutti gli oggetti definiti in R sono dunque vettori, a meno che non abbiano struttura di matrice (cfr. paragrafo 1.5). I principali comandi, nella forma più semplice, che utilizzeremo nel seguito per definire e manipolare matrici algebriche sono: • array(oggetto,dim=c(nrow,ncol)): trasforma l’oggetto indicato in una matrice di ordine nrow×ncol (cfr. Osservazione 1.3.1); • cbind(oggetto): trasforma l’oggetto indicato in un vettore colonna; • matrix(oggetto,nrow=,ncol=): trasforma l’oggetto indicato in una matrice di ordine nrow×ncol; • rbind(oggetto): trasforma l’oggetto indicato in un vettore riga; 24 E. D. Isaia, Linguaggio R e applicazioni statistiche Per comodità di esposizione, a fine paragrafo, riassumiamo in modo ordinato le principali funzioni predefinite che operano su oggetti con struttura, appunto, di matrice. Esempio 1.3.1 Creazione e visualizzazione del vettore riga x e del vettore colonna y che conterranno, entrambi, i primi quattro interi positivi: > (x<-rbind(c(1:4))) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 > (y<-cbind(c(1:4))) [,1] [1,] 1 [2,] 2 [3,] 3 [4,] 4 Un’alternativa potrebbe essere la seguente: > x<-matrix(c(1:4),nrow=1,ncol=4) > y<-matrix(c(1:4),nrow=4,ncol=1) I precedenti comandi che definiscono le matrici x e y potrebbero essere scritti in forma compatta, omettendo cioè gli identificativi nrow= e ncol=, ricordando che il numero delle righe dve precedere quello delle colonne; in sostanza avremmo potuto impartire i comandi: > x<-matrix(c(1:4),1,4) > y<-matrix(c(1:4),4,1) Nel seguito tuttavia, per motivi di chiarezza espositiva, ricorreremo sempre alla forma estesa del comando. ♥ Esempio 1.3.2 Creazione della matrice X le cui righe corrispondono ai vettori x e y sudefiniti: > (X<-rbind(x,t(y))) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 1 2 3 4 Si osservi che il comando t(y) porge la trasposta del vettore (colonna) y, infatti: > t(y) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 ♥ 25 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 " # Esempio 1.3.3 Creazione dell’oggetto z, contenente gli elementi del vettore x = 1 2 3 . È sufficiente ricorrere all’istruzione drop(), infatti: > (x<-rbind(c(1:3))) [,1] [,2] [,3] [1,] 1 2 3 > z<-drop(x) > z [1] 1 2 3 ♥ Esempio 1.3.4 Creazione e visualizzazione della matrice X le cui quattro colonne contengono, in progressione, gli interi da 1 a 12: > (X<-matrix(c(1:12),nrow=3,ncol=4)) [,1] [,2] [,3] [,4] [1,] 1 4 7 10 [2,] 2 5 8 11 [3,] 3 6 9 12 Un’alternativa potrebbe essere la seguente: > X<-c(1:12) > dim(X)<-c(3,4) oppure: > Y<-array(c(1:12),dim=c(3,4)) ♥ Osservazione 1.3.1 Il comando array() è assai versatile; con esso, ad esempio si possono creare matrici, per cosı̀ dire, “a più dimensioni”. A tal proposito si immagini di volere creare due matrici, di ordine 3 × 3 ciascuna e contenenti gli interi da 1 a 9 e da 10 a 18 rispettivamente, da inserire in un’unico oggetto, Y con struttura di matrice. Ciò può avvenire tramite il comando: > (Y<-array(c(1:18),dim=c(3,3,2))) , , 1 [,1] [,2] [,3] [1,] 1 4 7 [2,] 2 5 8 [3,] 3 6 9 26 E. D. Isaia, Linguaggio R e applicazioni statistiche , , 2 [1,] [2,] [3,] [,1] [,2] [,3] 10 13 16 11 14 17 12 15 18 Esempio 1.3.5 Data la matrice: 1 2 1 A = 4 3 2 1 2 1 ( ( ci proponiamo di calcolare 32 21 aij . In R, gli elementi aij della matrice A vengono individuati con la notazione A[i,j], dove A è una matrice definita mentre i e j sono gli indici che ne identificano rispetttivamente le righe e le colonne, e quindi i=1,...,nrow(A) e j=1,...,ncol(A). Il calcolo indicato potrebbe essere risolto, perlomeno in prima battuta , come: > A<-matrix(c(1,4,1,2,3,2,1,2,1),nrow=3,ncol=3) > A[2,1]+A[2,2]+A[3,1]+A[3,2] [1] 10 A tal proposito, cfr. Esempio 1.3.14. ♥ Esempio 1.3.6 Data la matrice: A= ) 1 2 3 5 6 7 * ne estraiamo i due vettori riga e i tre vettori colonna. In R la notazione A[1,] e A[,1] indicano, rispettivamente, gli oggetti costituiti dagli elementi della prima riga e, rispettivamente, della prima colonna di A. Ciò premesso, possiamo pensare di risolvere il problema mediante le istruzioni: > > > > > > A<-matrix(c(1,5,2,6,3,7),nrow=2,ncol=3) riga1<-rbind(A[1,]) riga2<-rbind(A[2,]) col1<-cbind(A[,1]) col2<-cbind(A[,2]) col3<-cbind(A[,3]) infatti, ad esempio: 27 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > riga1 [,1] [,2] [,3] [1,] 1 2 3 > col2 [,1] [1,] 2 [2,] 6 ♥ Esempio 1.3.7 Posto che Y sia una matrice contenente, a sua volta, due matrici di ordine 3 × 3 ciascuna (cfr. Osservazione 1.3.1 ed Esempio 1.3.6), ci proponiamo di estrarre da essa: — le singole matrici: > (Y[,,1]) [,1] [,2] [,3] [1,] 1 4 7 [2,] 2 5 8 [3,] 3 6 9 > (Y[,,2]) [,1] [,2] [,3] [1,] 10 13 16 [2,] 11 14 17 [3,] 12 15 18 — il vettore corrispondente alla prima riga della prima matrice ed il vettore corrispondente alla prima colonna della seconda matrice: > (rbind(Y[1,,1])) [,1] [,2] [,3] [1,] 1 4 7 > (cbind(Y[,1,2])) [,1] [1,] 10 [2,] 11 [3,] 12 ♥ Esempio 1.3.8 Costruzione della matrice A di ordine 4 × 4 con elementi nulli tranne sulla diagonale principale ove compaiono, in successione, i primi quattro interi. In sostanza dovrà essere aij = 0 per i #= j e aij = i per i = j e i = 1, 2, 3, 4. Desiderando procedere, possiamo pensare di creare la matrice A ad elementi nulli e succesivamente rimpiazzare gli elementi della sua diagonale principale, cioè quelli per cui risulta 6 row(A) ==col(A), con gli interi 1,2,3,4. In effetti: 6 Si osservi il ricorso al simbolo ==; cfr. il paragrafo 1.6. 28 E. D. Isaia, Linguaggio R e applicazioni statistiche > A<-matrix(0,nrow=4,ncol=4) > A[row(A) == col(A)]<-c(1:4) > A [,1] [,2] [,3] [,4] [1,] 1 0 0 0 [2,] 0 2 0 0 [3,] 0 0 3 0 [4,] 0 0 0 4 Un’alternativa ci è offerta dal ricorso alla funzione diag() che porge gli elementi della diagonale principale della matrice indicata quale argomento; in tal caso > A<-matrix(0,nrow=4,ncol=4) > diag(A)<-c(1:4) > A [,1] [,2] [,3] [,4] [1,] 1 0 0 0 [2,] 0 2 0 0 [3,] 0 0 3 0 [4,] 0 0 0 4 Desiderando, quindi, costruire una matrice identità di dimensione n × n saranno sufficienti le istruzioni: > X<-matrix(0,nrow=n,ncol=n) > diag(X)<-c(1) lasciandone al Lettore la verifica sul campo. ♥ Esempio 1.3.9 Data la matrice: 1 2 3 A = 4 1 5 6 7 1 definiamo due vettori riga, diciamo x e y, contenenti rispettivamente gli elementi posti alla sinistra e alla destra della diagonale principale di A. Se osserviamo che gli elementi aij di A che giacciono a sinistra della diagonale sono quelli per cui i > j, cioè row(A)>col(A), mentre quelli che stanno alla destra della stessa saranno quelli per cui i < j, cioè row(A)<col(A), abbiamo: > A<-matrix(c(1,4,6,2,1,7,3,5,1),nrow=3,ncol=3) > x<-rbind(A[row(A) > col(A)]) > y<-rbind(A[row(A) < col(A)]) ed infatti: 29 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > x [1,] > y [1,] [,1] [,2] [,3] 4 6 7 [,1] [,2] [,3] 2 3 5 ♥ Esempio 1.3.10 Dati i vettori: ) * " # 3 x= y= 1 2 5 è noto che: x·y = ) 3 6 5 10 * x · y = 13 = xt · yt In R impartiremo le istruzioni: > x<-rbind(3,5) > y<-cbind(1,2) > x%*%y [,1] [,2] [1,] 3 6 [2,] 5 10 > y%*%x [,1] [1,] 13 Il prodotto tra vettori e/o matrici viene quindi introdotto mediante l’operatore %*%. Si noti che, coerentemente: > t(x)%*%y Error in x %*% t(y) : non-conformable arguments ♥ Esempio 1.3.11 Ci proponiamo di risolvere il sistema di equazioni: + 2x+y = 7 x+2y = 8 Riscritto il sistema in forma matriciale: ) *) * ) * x 2 1 7 −1 y = 8 → Ax = b → x = A b 1 2 in R impartiremo le istruzioni: 30 E. D. Isaia, Linguaggio R e applicazioni statistiche > > > > A<-matrix(c(2,1,1,2),nrow=2,ncol=2) b<-cbind(c(7,8)) x<-solve(A)%*%b x [,1] [1,] 2 [2,] 3 o equivalentemente: > > > > A<-matrix(c(2,1,1,2),nrow=2,ncol=2) b<-cbind(c(7,8)) x<-solve(A,b) x [,1] [1,] 2 [2,] 3 ♥ Esempio 1.3.12 Costruzione di matrice che contiene gli elementi di una semplice “tabella pitagorica” per gli interi da 1 a 4. Sono sufficienti le istruzioni: > x<-cbind(c(1:4)) > matrix(outer(x,x,"*"),4,4) [,1] [,2] [,3] [,4] [1,] 1 2 3 4 [2,] 2 4 6 8 [3,] 3 6 9 12 [4,] 4 8 12 16 Al Lettore l’interpretazione dell’output dell’istruzione matrix(outer(x,x,"^"),4,4). ♥ Esempio 1.3.13 Calcolo delle somme di riga e di colonna della matrice: 30 25 20 15 A = 5 10 15 20 3 7 10 15 Definita la matrice: > A<-matrix(c(30,5,3,25,10,7,20,15,10,15,20,15),nrow=3,ncol=4) i totali di riga e di colonna possono essere ottenuti applicando a ciascuna riga e colonna l’operatore sum(), cioè impartendo le istruzioni: 31 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > sum(A[1,]); sum(A[2,]); sum(A[3,]) > sum(A[,1]); sum(A[,2]); sum(A[,3]); sum(A[,4]) Un’alternativa consiste nel ricorso alla funzione7 apply(.,.,.) i cui argomenti sono, nell’ordine: la matrice su cui operare, l’identificativo per i vettori riga o colonna (1=righe, 2=colonne), nonché la funzione che si desidera applicare, nel caso in esame sum. Pertanto: > apply(A, 1, sum) [1] 90 50 35 > apply(A, 2, sum) [1] 38 42 45 50 Proprio sulla funzione apply() è basata la funzione margin.table(.,.), i cui argomenti sono la matrice di interesse e l’identificativo numerico per i vettori riga o colonna, che porge i totali desiderati; infatti: > margin.table(A,1) [1] 90 50 35 > margin.table(A,2) [1] 38 42 45 50 Osservazione 1.3.2 È bene ricordare che, data una matrice Ar,s , cioè di ordine r × s, ed indicando con 1α un generico vettore riga unitario di ordine α si ha: r ! i=1 aij = 1r Ar,s s ! aij = r ! s ! Ar,s 1ts i=1 aij = 1r Ar,s 1ts i=1 j=1 Cosı̀, ad esempio, nel caso della matrice A proposta: > > > > > > > A<-matrix(c(30,5,3,25,10,7,20,15,10,15,20,15),nrow=3,ncol=4) br<-rbind(c(rep(1,nrow(A)))) bs<-rbind(c(rep(1,ncol(A)))) tot.col<-br%*%A tot.riga<-A%*%t(bs) tot<-br%*%A%*%t(bs) tot.col [,1] [,2] [,3] [,4] [1,] 38 42 45 50 > tot.riga [,1] [1,] 90 [2,] 50 [3,] 35 > tot [,1] [1,] 175 7 Funzioni strettamente legate ad apply() sono tapply() (Esempio ??) e sapply() (Esempio ??). 32 E. D. Isaia, Linguaggio R e applicazioni statistiche Si noti che i risultati richiesti risultano sottoforma di vettori. Esempio 1.3.14 Data la matrice: 1 2 1 A = 4 3 2 1 2 1 calcoliamo abbiamo: (3 (2 2 1 aij . Anziché operare come illustrato all’Esempio 1.3.5, in modo diretto > sum(A[c(2:3),c(1:2)]) [1] 10 ♥ A conclusione del paragrafo, ci pare utile proporre un semplice elenco delle principali funzioni predefinite che operano su oggetti con struttura di matrice. Con riferimento ad una generica matrice Y si ha: • aperm(Y,k): consente di effetturare una permutazione di Y rispetto all’argomento k. Evidentemente con aperm(Y) si ha la trasposta di Y; • det(Y): calcola il determinante della matrice quadrata Y in accordo all’algoritmo QR (cfr. Esempio 1.6.7); • diag(Y): porge gli elementi della diagonale principale di Y; • diag(k): definisce una matrice identità di ordine (kxk); • eigen(Y): fornisce in forma di “lista” (cfr. 1.4.1) gli autovalori e gli autovettori associati alla matrice simmetrica Y; • qr(Y): procede alla decomposizione di Y secondo l’algoritmo QR, cosı̀ come suggerito da Dongarra et al. (1978); la matrice dei coefficienti della decomposizione ed altre informazioni quali il rango di Y, sono memorizzati sottoforma di “lista” (cfr. 1.4.1); • solve(Y): porge la matrice inversa di Y; • solve(Y,x): risolve l’equazione indicata; la soluzione è, dunque, x Y −1 ; • svd(Y): procede alla decomposizione di Y secondo l’algoritmo SVD, cosı̀ come suggerito da Dongarra et al. (1978); i risultati sono presentati sottoforma di “lista”. Per una semplice applicazione cfr. Esempio 1.6.7; 33 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 • t(Y): porge la trasposta di Y; • outer(x,y,funzione): costrusice una nuova matrice i cui elementi risultano essere [i,j]=funzione(x[i],y[i],...). Se la funzione che si desidera applicare è una funzione predefinita ( ad esempio +, *, /, , sum, ...) questa deve obbligatoriamente essere racchiusa entro virgolette, mentre ciò non si applica se è una funzione creata ad hoc dall’utente 8 . Per alcune semplici applicazioni, cfr. Esempio 1.3.12 e 2.1.11. 1.4 Oggetti complessi Come si disse, in R è possibile costruire oggetti a loro volte costituiti da altri oggetti elementari, non necessariamente della stessa modalità. Tali nuovi oggetti, che abbiamo definito complessi, sostanzialmente evitano il propagarsi di variabili (nomi, etichette, ...) e rendono quindi più chiara una sessione di lavoro in R. A seconda della loro natura, si distinguono in “liste” e “data frame”. 1.4.1 Liste Le “liste” vengono definite mediante l’istruzione: nomelista<-list(label1=object1,label2=object2,...,labeln=objectn) dove nomelista è il nome della “lista” che si intende creare e gli argomenti di list sono oggetti elementari già esistenti a cui si attribuisce un’etichetta (label) che servirà successivamente a riconoscerli ed eventualmente estrarli ad uno ad uno. Ciò avviene semplicemente digitando il nome della lista seguito da quello dell’oggetto che si desidera estrarre, preceduto, questo dal prefisso $, ad esempio nomelista$label1. I nomi che identificano gli elementi di una lista posono essere visualizzati in qualsiasi momento ricorrendo al comando names(nomelista). Esempio 1.4.1 Creazione, a partire degli oggetti x<-seq(1:10) e a<-letters[1:5], della lista mia.lista . Posto di attribuire all’oggetto elementare x l’etichetta dati e all’oggetto a l’etichetta stringa, il problema viene risolto ricorrendo all’istruzione: > mia.lista<-list(dati=x,stringa=a) La visualizzazione del contenuto di una lista avviene impartendo il comando mia.lista, il quale porge: 8 Si noti che il comando outer(x,y,*) può essere sosituito da x %o% y. 34 E. D. Isaia, Linguaggio R e applicazioni statistiche $dati [1] 1 2 3 4 5 6 7 $stringa [1] "a" "b" "c" "d" "e" 8 9 10 In altri termini, la lista mia.lista contiene due diversi oggetti elementari, ciascuno dei quali identificabile dalla rispettiva etichetta preceduta dal simbolo riservato $. ♥ Esempio 1.4.2 Visualizzazione degli elementi contenuti in mia.lista e successiva estrazione dell’oggetto $dati. Sono suficienti i comandi: > names(mia.lista) [1] "dati" "stringa" > mia.lista$dati [1] 1 2 3 4 5 6 7 8 9 10 È appena il caso di osservare che con nuova.x<-mia.lista$dati si crea un nuovo oggetto che conterrà, appunto, gli elementi di $dati. ♥ Esempio 1.4.3 Si immagini che l’oggetto ms.AB, con struttura di matrice, rappresenti la distribuzione congiunta dei caratteri colore degli occhi e colore dei capelli di 290 individui di sesso maschile: > ms.AB<-array(c(32,38,10,3,11,50,10,30,10,25,7,3,15,7,8,31),dim=c(4,4)) > ms.AB [,1] [,2] [,3] [,4] [1,] 32 11 10 15 [2,] 38 50 25 7 [3,] 10 10 7 8 [4,] 3 30 3 31 Desiderando attribuire alle modalità di ciascuna mutabile statistica (m.s.) le appropriate etichette, possiamo ricorrere ai comandi dimnames() e list() nel modo seguente: > dimnames(ms.AB)<-list(Capelli=c("Neri","Castani","Rossi","Biondi"), Occhi = c("Neri","Castani","Verdi","Azzurri")) ottenendo, coerentemente: > ms.AB Occhi Capelli Neri Castani Verdi Azzurri Neri 32 11 10 15 Castani 38 50 25 7 Rossi 10 10 7 8 Biondi 3 30 3 31 35 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 ♥ Osservazione 1.4.1 Molte procedure di analisi, oltre alla visualizzazione di un output standard, prevedono la creazione automatica di liste contenenti risultati intermedi che possono essere riacquisiti per successive elaborazioni. È buona norma, inoltre, documentare, in fase di programmazione, le eventuali liste create come sottoprodotto dalle funzioni via, via implementate. 1.4.2 Data frame Analogamente alle liste, i “data frame” vengono definiti mediante l’istruzione: nomedf<-data.frame(label1=object1,label2=object2,...,labeln=objectn) dove manifestamente nomedf è il nome del data frame che si intende creare metre gli argomenti di data.frame sono oggetti elementari già esistenti e di egual cardinalità a cui è possibile attribuire un’etichetta (label) che consente di riconoscerli in modo più spedito. Benché i data frame cosı̀ creati abbiano struttura list, si differenziano dalle “liste” per come vengono estratti e gestiti i singoli componenti. Definito un data frame, affinché i suoi elementi siano disponibili 9 , occorre impartire il comando attach(nomedf), in seguito al quale i singoli componenti si comportano quali comuni variabili. Il comando detach(nomedf) scarica il data frame dall’area di lavoro. Ricordiamo, infine, che i nomi che identificano gli elementi di una data frame posono essere visualizzati in qualsiasi istante ricorrendo al comando names(nomedf). Esempio 1.4.4 Creazione del data frame mydata contenente, in forma compatta, due variabili di interesse per successive elaborazioni: > > > > > > 1 2 3 4 5 6 rm(list=ls()) sex<-c("M","M","M","F","M","F","M","M","F","M","F") age<-c(21,23,24,21,23,24,25,26,24,25,21) mydata<-data.frame(sesso=sex,eta=age) rm(sex, age) mydata sesso eta M 21 M 23 M 24 F 21 M 23 F 24 9 Alcune funzioni, quali ad esempio lm() e +aov(), fanno tuttavia eccezione. 36 E. D. Isaia, Linguaggio R e applicazioni statistiche 7 M 25 8 M 26 9 F 24 10 M 25 11 F 21 > ls() [1] "mydata" > names(mydata) [1] "sesso" "eta" > str(mydata) ‘data.frame’: 11 obs. of 2 variables: $ sesso: Factor w/ 2 levels "F","M": 2 2 2 1 2 1 2 2 1 2 ... $ eta : num 21 23 24 21 23 24 25 26 24 25 ... > mode(mydata) [1] "list" Si noti che l’area di lavoro contiene il solo oggetto mydata, i cui componenti, peraltro, non sono ancora disponibili, infatti: > sesso Error: Object "sesso" not found > eta Error: Object "eta" not found Desiderando effettuare alcune elaborazioni sui dati contenuti negli oggetti del data frame, è necessario, come già si disse, ricorrere al comando attach(mydata); nel caso proposto, ad esempio: > attach(mydata) > cat("L’eta’ media e’:",round(sum(eta)/length(eta),2),"\n") L’eta’ media e’: 23.36 > detach(mydata) ♥ 1.5 Modalità e struttura di un’oggetto La modalità di un oggetto, verificabile, come si è già detto, con il comando mode(), può essere modificata, con le dovute cautele, ridefinendo l’oggetto tramite le istruzioni as.numeric oppure as.character. Qualora un’oggetto possedesse modalità numerica, il comando typeof(oggetto), o equivalentemente storage.mode(oggetto), ci informa circa la rappresentazione interna degli elementi dell’oggetto indicato, che può presentarsi come integer, real, double oppure complex, che potrebbe essere modificata con i comandi as.integer, 37 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 as.real, as.double oppure as.complex. Si noti che in tal modo oggetti con struttura di vettore o di matrice possono essere ridefiniti quali oggetti elementari. Esempio 1.5.1 Definiti gli oggetti: > > > > x<-seq(1:5) a<-letters[1:10] y<-cbind(x) Y<-matrix(log(c(1:5)),log10(c(1:5)),nrow=5,ncol=2) si osservi il comportamento delle istruzioni: verifica mode(x) mode(a) mode(y) mode(Y) → → → → esito "numeric" "character" "numeric" "numeric" verifica storage.mode(x) storage.mode(a) storage.mode(y) storage.mode(Y) → → → → esito "integer" "character" "integer" "double" ed ancora: > as.character(x) [1] "1" "2" "3" "4" "5" > as.integer(as.character(x)) [1] 1 2 3 4 5 > round(as.real(Y),3) [1] 0.000 0.693 1.099 1.386 1.609 0.000 0.693 1.099 1.386 1.609 > as.integer(Y) [1] 0 0 1 1 1 0 0 1 1 1 ♥ Quanto alla struttura di un oggetto, qusta può esssere verificata con le istruzioni intuitive is.vector(), is.matrix(), is.list(), is.data.frame(). Esempio 1.5.2 Con riferimento agli oggetti di cui all’Esempio 1.5.1, abbiamo: verifica is.vector(x) is.vector(y) is.vector(Y) → → → esito TRUE FALSE FALSE verifica is.matrix(x) is.matrix(y) is.matrix(Y) → → → esito FALSE TRUE TRUE In sostanza solo gli oggetti y e Y hanno struttura di matrice secondo l’accezione dell’algebra lineare; in tale ambito il primo risulta essere un vettore (riga), il secondo una matrice. ♥ In linea di massima, la struttura di un oggetto può eventualmente essere modificata ricorrendo ai comandi as.vector(), as.matrix(), as.data.frame(), tenendo conto che: 38 E. D. Isaia, Linguaggio R e applicazioni statistiche • as.matrix() applicato ad un oggetto elementare lo trasforma in un vettore colonna; quindi il comando equivale a rbind(); • se un’elemento di un data frame è alfanumerico, la matrice che si genera con as.matrix() avrà modalità alfanumerica; • data una matrice di ordine n × p, con as.data.frame() si definisce un data frame i cui elementi corrispondono alle p colonne della matrice specificata. 1.6 Funzioni definibili dall’utente R consente all’utente una diretta programmazione di funzioni di qualsiasi natura; in altri termini egli potrà, a seconda delle proprie esigenze, arricchire l’ambiente di lavoro con specifiche funzioni. Tra l’altro, quasi i tutti i comandi R che si utilizzano abitualmente sono funzioni definite a partire da comandi elementari. Prima di affrontare tale argomento, ci pare utile accennare alla possibilità di creare cicli iterativi ricorrendo, a seconda delle esigenze, ai costrutti autoesplicativi: • for (variabile in (range)) {istruzioni} • while (condizione) {istruzioni} • repeat (condizione) {istruzioni} Cosı̀ il costrutto retto da for consente di ripetere le istruzioni contenute appunto in {istruzioni} fintanto che la variabile specificata appartiene all’insieme numerico definito in range. Buona norma è comunque non fare ricorso a cicli iterativi quando esistono funzioni interne che possono sopperire allo scopo che ci si prefigge. Esempio 1.6.1 Creazione del vettore y che conterrà il quadrato dei primi dieci interi: > (y<-integer(10)) [1] 0 0 0 0 0 0 0 0 0 0 > for(i in 1:10) {y[i]<-i^2} > y [1] 1 4 9 16 25 36 49 64 81 100 Ovviamente saremmo giunti allo stesso risultato in modo diretto impartendo le istruzioni: > (y<-(c(1:10))^2) [1] 1 4 9 16 25 36 49 64 81 100 39 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 ♥ Esempio 1.6.2 Creazione , a partire dall’oggetto y<-c("R"), del vettore x che conterrà la replicazione "R","R","R". Ricorrendo ad un ciclo retto da for: > y<-c("R") > x<-for(i in 1:3){print(rep(y,i))} [1] "R" [1] "R" "R" [1] "R" "R" "R" > x [1] "R" "R" "R" In modo diretto, ricorrendo alla funzione rep: > y<-c("R") > (x<-rep(y,3)) [1] "R" "R" "R" ♥ Come un qualsiasi altro linguaggio di programmazione, R consente il ricorso a condizioni logiche mediante i costrutti: • if (condizione){istruzioni} • if (condizione){istruzioni} else {istruzioni} • if (condizione){istruzioni} elseif {istruzioni} tenendo a mente la tabella che segue: simbolo == => && ! significato equal to greater or equal to and not simbolo != <= || significato not equal to less or equal to or Esempio 1.6.3 Si immagini che la rilevzione di un carattere quantitativo su un collettivo statistico abbia fornito in corrispondenza ad un (solo) individuo una mancata risposta (“missing value”): > x<-c(NA,20,21,20,23,27,25,27,25,23,20,21,27) 40 E. D. Isaia, Linguaggio R e applicazioni statistiche Desiderando sostituire il valore mancante con la mediana delle osservazioni valide, possiamo ricorrere all’istruzione: > c(median(x[!is.na(x)]),x[!is.na(x)]) [1] 23 20 21 20 23 27 25 27 25 23 20 21 27 dove median(x[!is.na(x)]) calcola appunto la mediana degli elementi di x depurati dal valore mancante. ♥ Ritornando al problema inizialmente postoci, la sintassi atta alla creazione di una funzione è: nome<-function(parametri){comandi} dove il nome è a cura dell’utente, in parametri è acclusa l’eventuale lista di parametri (o meglio oggetti di natura qualsiasi) mentre in comandi sono annotate valide istruzioni R. Si noti che tutti gli oggetti definiti entro il corpo della funzione lo sono solo localmente; al fine di definirli globalmente, con le dovute cautele, si può ricorrere, in fase di definizione, all’assegnazione rafforzativa <<-. A tal proposito, tuttavia, è buona norma offrire l’output sottoforma di lista o, eventualmente, di data frame. È importante, poi, osservare che una funzione può contenere, al suo interno, altre funzioni che, ovviamente, risulteranno definite solo localmente. Nel seguito presentiamo, a puro scopo didattico, alcuni esempi di function. Esempio 1.6.4 Creazione della funzione ipotenusa(a,b) che calcola la misura dell’ipotenusa di un triangolo rettangolo i cui cateti misurano a e b. 1 > ipotenusa<-function(a,b){sqrt(a^2+b^2)} Il successivo comando ipotenusa(10,12) porge il risultato 15.6205. Si osservi il comportamento delle istruzioni: > ipotenusa(1,1) [1] 1.414214 > ipotenusa(c(1:5),1) [1] 1.414214 2.236068 3.162278 4.123106 5.099020 ♥ Esempio 1.6.5 Creazione della funzione disp.nk che provvede al calcolo delle disposizioni senza ripetizione nk ! = n (n − 1) · · · (n − k + 1). Sono sufficienti le istruzioni: 1 > disp.nk<-function(n,k){prod(n:(n-k+1))} 41 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Cosı̀, ad esempio: > for (n in 1:4) print(disp.nk(n,n)) [1] 1 [1] 2 [1] 6 [1] 24 Alla luce di quanto si è tentati di scrivere una semplice funzione per il calcolo dei coef, sopra, ficienti binomiali nk , con k ≤ n; ciò può essere evitato ricorrendo al comando choose(n,k), infatti, ad esempio: > choose(10,c(0:10)) [1] 1 10 45 120 210 252 210 120 45 10 1 ♥ Esempio 1.6.6 Creazione della funzione somma che, partendo da una matrice di input, provvede al calcolo della somma generale, nonché delle somme di riga e di colonna; i risutati verranno inseriti nell’oggetto temporaneo con struttura di lista somma.out, che potrà essere visualizzato o memorizzato a seconda delle esigenze dell’utente: 1 2 3 4 5 6 7 8 9 10 11 > somma<-function(X,print=TRUE,print.out=FALSE) { if(is.data.frame(X)) {X<-as.matrix(X)} if (!is.matrix(X)) {stop("X deve essere una matrice")} t.riga<-apply(X,1,sum) t.col<-apply(X,2,sum) t<-sum(X) somma.out<-list(tot.riga=t.riga,tot.col=t.col,tot=t) if(print==TRUE) {return(somma.out)} if(print.out==TRUE) {somma.out<<-somma.out} } A commento: — in riga [1] viene definita la funzione somma che ha quale unico input l’oggetto matrice con struttura di matrice. Le due opzioni print=TRUE e print.out=FALSE fissano la situazione di default: i risultati vengono visualizzati ma non memorizzati in un oggetto in uscita dalla funzione; — il corpo della funzione è racchiuso entro le righe [2] e [11]; — le righe [3] e [4] eseguono un controllo sull’oggetto X di input, il quale deve avere struttura di matrice o di data frame; se tale condizione non è soddisfatta la funzione visualizza un avviso di errore; 42 E. D. Isaia, Linguaggio R e applicazioni statistiche — le righe [5], [6] e [7] provvedono ai calcoli richiesti ed in riga [8] viene definito l’oggetto somma.out con struttura di lista contenente, appunto, i risultati; — in riga [9] a seconda del valore TRUE o FALSE assunto dalla variabile flag print viene visualizzata la lsita somma.out; — in riga [10] a seconda del valore TRUE o FALSE assunto dalla variabile flag print.out viene creata la lsita in uscita somma.out. Generalmente tali condizioni vengono scritte in modo compatto: if(print) e if(print.out). Cosı̀ con riferimento, ad esempio, alla matrice: ) * 1 3 A= 2 4 avremo: > A<-matrix(c(1:4),nrow=2,ncol=2) > somma(A) $tot.riga [1] 4 6 $tot.col [1] 3 7 $tot [1] 10 > somma(A,print=FALSE,print.out=TRUE) > somma.out $tot.riga [1] 4 6 $tot.col [1] 3 7 $tot [1] 10 ♥ Esempio 1.6.7 Come già si disse, il calcolo del determinante di una matrice quadrata Y può essere svolto tramite la funzione det() che, perlomeno nella situazione di default, ricorre alla funzione qr(Y). Lo stesso risultato lo si può ottenere tramite la funzione svd(Y), la quale (Dongarra et al. 1978) procede alla decomposizione di Y come: Y = U D Vt dove U e V sono matrici con colonne ortonormali di dimensione pari a ncol(Y) e ncol(Y) rispettivamente, mentre D è una matrice diagonale contenente i valori singolari di Y. I risultati di interesse della decomposizione, proposti sottoforma di lista sono $d, vettore contenente i valori singolari di Y, $u, matrice le cui colonne corrispondono agli autovettori sinistri di Y e $v, matrice le cui colonne corrispondono agli autovettori destri di Y. 43 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Il valore assoluto del determinante di Y corrisponde dunque al prodotto degli elementi della diagonale principale di D. Quanto al segno del determinante, esso sarà negativo se il numero dei valori singolari di Y è pari, positivo altrimenti; tale condizione viene verificata tramite length(diag(Y))%%2. Possiamo, quindi, scrivere la seguente funzione: 1 2 3 4 5 6 > det.new<-function(Y) { det<-prod(svd(Y)$d) if (length(diag(Y))%%2 == 1) {-det} else {det} } Cosı̀, ad esempio: > (M<-matrix(c(1,1,0,1,1,1,0,1,1),nrow=3,ncol=3)) [,1] [,2] [,3] [1,] 1 1 0 [2,] 1 1 1 [3,] 0 1 1 > det.new(M) [1] -1 > det(M) [1] -1 ♥ 1.7 Su alcune funzioni matematiche Presentiamo alcune funzioni matematiche che possono tornare utili per la risoluzione di specifici problemi e necessitano in input di oggetti di tipo expression o function. In forma schematica, abbiamo: • D(funzione,"variabile"): consente il calcolo simbolico della derivata prima di una funzione, definita quale expression(), rispetto alla variabile di interesse, che dovrà essere indicata sottoforma di stringa. Esempio 1.7.1 Data la funzione f (x, y) = exp(−(x2 + y 2 )), ci proponiamo di: — calcolare simbolicamente le derivate prime parziali: > f<-expression(exp(-(x^2+y^2))) > D(f,"x") -exp(-(x^2 + y^2)) * (2 * x) > D(f,"y") -exp(-(x^2 + y^2)) * (2 * y) 44 E. D. Isaia, Linguaggio R e applicazioni statistiche !! !! !! — valutare il determinante (fxx fyy − fxy ) della matrice hessiana in corrispondenza al punto di coordinate (x = 0, y = 0): > x<-0 > y<-0 > eval(D(D(f,"x"),"x"))*eval(D(D(f,"y"),"y")) - 2*eval(D(D(f,"x"),"y")) [1] 4 Per inciso: > D(D(f,"x"),"x") -exp(-(x^2 + y^2)) * 2 - exp(-(x^2 + y^2)) * (2 * x) * (2 * x) > D(D(f,"y"),"y") -exp(-(x^2 + y^2)) * 2 - exp(-(x^2 + y^2)) * (2 * y) * (2 * y) > D(D(f,"x"),"y") exp(-(x^2 + y^2)) * (2 * y) * (2 * x) ♥ • uniroot(function(x) espressione,interval=c(a,b),tol=1e-30): ricerca gli eventuali zeri della funzione f (x) definita quale function, nell’intervallo (a, b). Esempio 1.7.2 A commento della funzione uniroot, proponiamo i seguenti problemi: — data la funzione f (x) = x2 − 1, ricerchiamone gli zeri nell’intervallo (0, 2): > str(uniroot(function(x) x^2-1,interval=c(0,2),tol=1e-30)) List of 4 $ root : num 1 $ f.root : num 0 $ iter : int 8 $ estim.prec: num 6.51e-05 — data la funzione f (x) = (x − 1)2 (x + 1)2 , ricerchiamo gli zeri della sua derivata prima nell’intervallo10 (−.5, .5). Il problema sarebbe di semplice soluzione se immettessimo direttamente la derivata prima di f (x); qui, tuttavia, preferiamo calcolare (simboli! camente) fx e passarne l’espressione alla funzione uniroot. A tal fine sfruttiamo le istruzioni: > f<-expression((x-1)^2 * (x+1)^2) > dfdx<-as.function(list(x="x",D(f,"x"))) > uniroot(dfdx,low=-.5,up=.5)$root [1] 0 1 2 3 4 ! 10 In effetti, come si può facilmente verificare algebricamente, fx si annulla in corrispondenza a tre distinti punti in (−2, 2). 45 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 A commento è bene notare che, definita f (x) quale expression ai fini della derivazione, ! in riga [2] trasformiamo l’espressione ottenuta per fx in function, con argomento x, : cioè: > dfdx function (x = "x") 2 * (x - 1) * (x + 1)^2 + (x - 1)^2 * (2 * (x + 1)) quindi passiamo l’oggetto dfdx alla funzione uniroot. — data la funzione f (x) = exp(−x), ricerchiamo il più piccolo valore di x per cui f (x) può considerarsi “numericamente nulla”, cioè, ad esempio, se f (x) = 10 −300 . A tal fine è sufficiente l’istruzione: > str(uniroot(function(x) exp(-x)-10^(-300),interval=c(0,1000), tol=1e-30)) List of 4 $ root : num 691 $ f.root : num 2.37e-314 $ iter : int 21 $ estim.prec: num 3.41e-13 ♥ • optimize(function(x) espressione,interval=c(a,b),maximum=FALSE): ricerca un eventuale punto di minimo (o di massimo, ponendo maximum=TRUE) della funzione f (x) definita quale function, nell’intervallo (a, b). Esempio 1.7.3 Data la funzione f (x) = sin(x), ci proponiamo di calcolarne il minimo ed il massimo nell’intervallo (0, 2 π). A tal fine sopperiscono le istruzioni: > optimize(function(x) sin(x),interval=c(0,2*pi),tol=1e-30,maximum=FALSE) $minimum [1] 4.712389 $objective [1] -1 > optimize(function(x) sin(x),interval=c(0,2*pi),tol=1e-30,maximum=TRUE) $maximum [1] 1.570796 $objective [1] 1 Si noti che, data ad esempio la funzione f (x) = x3 , la ricerca di un punti di minimo (!) in (−2, 2) mediante optimize porgerebbe: 46 E. D. Isaia, Linguaggio R e applicazioni statistiche > optimize(function(x) x^3,interval=c(-2,2),tol=1e-30,maximum=FALSE) $minimum [1] -2 $objective [1] -8 risultato evidentemente privo di senso. ♥ • integrate(funzione,lower=, upper=,subdivisions=100): consente il calcolo, per quadratura numerica, dell’integrale della funzione f (x) definita quale function nell’intervallo (a, b), finito o infinito. 2 Esempio 1.7.4 Data la funzione integranda f (x) = √1 exp(− x2 ): 2π > f<-function(x) (2*pi)^(-.5)*exp(-.5*x^2) ci proponiamo di: — calcolare il suo integrale nell’intervallo (−3, 3): > str(integrate(f,lower=-3,upper=3)) List of 5 $ value : num 0.997 $ abs.error : num 9.25e-07 $ subdivisions: int 1 $ message : chr "OK" $ call : language integrate(f = f, lower = -3, upper = 3) - attr(*, "class")= chr "integrate" .3 .3 Ovviamente, per la simmetria di f (x), risulta −3 f (x) dx = 2 0 f (x) dx; numericamente, infatti: *** — calcolare il suo integrale nell’intervallo (−∞, t), con t = −3, −2.5, . . . , 0; ricorrendo ad un semplice ciclo retto da for, abbiamo: > for(b in seq(-3,0,by=.5)){ cat(integrate(f, lower = -Inf, upper = b)$value,"\n")} 0.001349899 0.006209665 0.02275013 0.0668072 0.1586553 0.3085375 0.5 ♥ 47 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 1.8 Lettura e registrazione di archivi In R vi sono sostanzialmente due modi per leggere e/o registrare archivi di dati e questi si basano sui comandi scan() - write() e read.table() - write.table() rispettivamente. A questi è giocoforza affiancare il particolare comando data() che permette di acquisire dati registrati in formato particolare che abitualmente fanno parte integrante dei “package” di base o aggiuntivi di R. Ricordiamo che comunque è possibile importare e/o esportare dati in formati riconoscibili da altri pacchetti, ad esempio Excell, Oracle, SAS, Spss, ...; a tal fine, tuttavia, occorre disporre di “funzioni” o “package” ad hoc, facilmente reperibili consultando il sito http://www.r-project.org. 1.8.1 I comandi scan() e write() Lettura di un file di dati con struttura “blank or tab delimited” può avvenire riccorrendo al comando scan() la cui sintassi è: nomelista<-scan("filename",list(label1=type,...,labeln=type)) dove filename è l’archivio dati di interesse, label sono le etichette attribuite a ciascun oggetto definito implicitamente per ciascuna colonna del file in lettura, mentre type indica la modalità dei singoli oggetti che verranno inclusi nella lista (type=0 e type="" per oggetti con modalità numerica o alfanumerica rispettivamente). Si osservi che l’oggetto nomelista ha struttura list. Esempio 1.8.1 La lettura del file di dati Mydata.dat con struttura “blank or tab delimited” 170 77 M 182 81 M 172 55 F ........ 176 67 F avverrà previa definizione della lista mieidati ed estraendo da essa i singoli oggetti di interesse. In pratica: > > > > mieidati<-scan("Mydata.dat",list(x=0,y=0,sex="")) altezza<-mieidati$x peso<-mieidati$y sesso<-mieidati$sex Una forma alternativa, meno elegante, ma forse più chiara, potrebbe essere la creazione di una lista priva di etichette e l’attribuzione delle stesse in seconda battuta; ad esempio la lettura del file Mydata.dat potrebbe avvenire in accordo alle istruzioni: 48 E. D. Isaia, Linguaggio R e applicazioni statistiche > > > > mieidati<-scan("Mydata.dat",list(0,0"")) x<-mieidati[[1]] y<-mieidati[[2]] sex<-mieidati[[3]] ♥ La scrittura, o registrazione, su file in formato “blank delimited” delle variabili di interesse avviene con il semplice comando: write(oggetto1,oggetto2,...,oggetton,file="filename") Esempio 1.8.2 La scrittura sul file Mydata.dat degli oggeti x, y e w avviene con il comando > write(x,y,w,file="Mydata.dat") ♥ 1.8.2 I comandi read.table() e write.table() Mediante il comando read.table() è possibile acquisire in memeoria, sottoforma di data frame, i dati contenuti in archivi con struttura “tab delimited”. La sintassi minima del comando è: nomedf<-read.table("filename",header = FALSE) Gli oggetti, con struttura factors, del data frame acquisito in memoria vengono indicati per default in V1,V2,V3,... Qualora la prima riga dell’archivio contenesse il nome delle variabili, una corretta lettura si avrebbe ponendo header = TRUE e gli oggetti del data frame assumerebbero tali nomi. Esempio 1.8.3 La lettura del file di dati Mydata.tab con struttura “tab delimited”: altezza 170 182 172 ... 176 peso 77 81 55 ... 67 sesso M M F ... F avviene tramite il semplice comando: 49 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > mieidati<-read.table(file="Mydata.tab",header=TRUE) > mieidati altezza peso sesso 1 170 77 M 2 182 81 M 3 172 55 F 4 176 67 F 5 170 77 M 6 182 81 M 7 170 77 M 8 171 65 F 9 170 77 M 10 165 55 F 11 180 77 M 12 172 81 M 13 160 77 M 14 192 81 M 15 170 77 M 16 172 67 F A questo punto con attach(mieidati) si rendono disponibili i tre oggetti altezza, peso e sesso per succcessive elaborazioni. ♥ In modo del tutto naturale, la scrittura su file di un generico data frame avviene con il comando write.table(dataframe,file="filename"). 1.8.3 Il comando data() Sfruttando tale comando è possibile accedere in modo diretto agli archivi di dati registrati direttamente sottoforma di lista o di data frame che, quale parte integrante dei “package” di base o aggiuntivi di R, sono abitualmente posti nelle corrispondenti directory \library\<package>\data. A tal proposito, alcuni comandi utili sono: • data(package=<package>): visualizza l’elenco ed eventualmente una breve descrizione degli archivi disponibili per il “package” specificato. Con data() si ottiene l’elenco del (o dei) “package” attualmente in uso, ad esempio base, ctest, modreg ..., mentre con data(package=.packages(all.available=TRUE)) si ha l’elenco completo degli archivi di dati relativi a tutti i “package” presenti nella directory \library di R. • help(package=<package>,<nome del file>): fornisce, se previsto, una breve descrizione dell’archivio di dati specificato; 50 E. D. Isaia, Linguaggio R e applicazioni statistiche • data(package=<package>,<nome del file>): carica in memoria l’archivio di dati specificato. Naturalmente l’utente può creare *** non so dove inserirlo *** qui o, penso meglio, in un capitolo/paragrafo ad hoc sulle librerie. 1.9 Personalizzazione dell’ambiente di lavoro L’ambiente di lavoro può essere personalizzato, a seconda delle esigenze dell’utente, semplicemente modificando i valori di default delle diverse opzioni che definiscono ad esempio il “prompt”, il numero di decimali visualizzati, la dimensione ed il layout della pagina in fase di stampa e molte cose ancora. Le modifiche, in linea di massima, possono essere attuate seguendo diverse vie, e più precisamente: — nel corso di una sessione di lavoro. In tal caso esse avranno unicamente valore temporaneo a meno che non si salvi l’ambiente stesso, creando cosı̀ il file Rdata; lanciando successivamente R tramite questo, si ritroveranno modificate; — direttamente sul file Rprofile, sı̀ che esse divengono, per cosı̀ dire, permanenti; Senza entrare in dettagli, la creazione del file Rdata ci pare la soluzione migliore, anche perché in tal modo, lasciando integro il file Rprofile, si possono creare diverse configurazioni di R poste, ad esempio, in altrettante directory di lavoro. Desiderando ottenere l’elenco completo dei nomi delle opzioni su cui è possibile intervenire, è sufficiente digitare names(.Options), infatti: > names(.Options) [1] "prompt" [4] "expressions" [7] "contrasts" [10] "check.bounds" [13] "error.messages" [16] "show.signif.stars" [19] "help.try.all.packages" [22] "download.info" [25] "device" [28] "mailer" "continue" "width" "echo" "keep.source" "ts.eps" "show.coef.Pvalues" "CRAN" "encoding" "pager" "editor" "digits" "verbose" "keep.source.pkgs" "na.action" "warn" "timeout" "papersize" "unzip" Per visualizzare i valori di default di ciascun parametro occorre digitare options() oppure str(options()); quest’ultimo porge 11 : 11 Ovviamente a seconda della piattaforma su cui è installato R. 51 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > str(options()) List of 28 $ prompt : chr "> " $ continue : chr "+ " $ editor : chr "Nedit" $ expressions : int 500 $ width : int 79 $ digits : int 7 $ contrasts : Named chr [1:2] "contr.treatment" "contr.poly"..- attr(*, "names")= chr [1:2] "unordered" "ordered" $ echo : logi TRUE $ verbose : logi FALSE $ check.bounds : logi FALSE $ keep.source : logi TRUE $ keep.source.pkgs : logi FALSE $ error.messages : logi TRUE $ ts.eps : num 1e-05 $ na.action : chr "na.omit" $ show.signif.stars : logi TRUE $ show.coef.Pvalues : logi TRUE $ warn : num 0 $ help.try.all.packages: logi FALSE $ CRAN : chr "http://cran.r-project.org" $ timeout : num 60 $ download.info : num 2 $ encoding : int [1:256] 0 1 2 3 4 5 6 7 8 9 ... $ papersize : chr "a4" $ device : chr "X11" $ pager : chr "nedit" $ unzip : chr "tar" Prima di procedere a modifiche dei parametri di default conviene creare una copia degli stessi sı̀ da poter ripristinare in qualsiasi istante la situazione di default; ciò può avvenire, ad esempio, impartendo le istruzioni: > > > > default.opt<-options() ... modifiche dei parametri ... ... elaborazioni ... options(default.opt) 52 E. D. Isaia, Linguaggio R e applicazioni statistiche Le modifiche dei parametri avvengono con il comando options(opzione=valore); ad esempio12 : > default.opt<-options() > pi [1] 3.141593 > options(digits=20) > pi [1] 3.141592653589793 > options(prompt="@->") @-> options(digits=2) @-> pi [1] 3.1 @-> options(default.opt) > pi [1] 3.141593 1.10 Le librerie e loro gestione Come si è detto, a seconda delle esigenze dell’utente,può a volte capitare di dover disporre di particolari librerie matematiche, statistiche e/o grafiche aggiuntive, reperibili al sito ufficiale http://www.r-project.org oppure costruite ad hoc. Comunque sia, per un corretto funzionamento, i “package” dovranno essere posti nella directory \library, la quale potrebbe assumere la seguente struttura: \library !→ !→ !→ ... !→ ... !→ \base \ctest \modreg ... \personale ... \ts Ciò premesso, l’elenco che segue riporta in modo schematico alcuni comandi atti alla gestione dei diversi “package” presenti \library: • (.packages()): indica quali “package” sono attualmente in uso. Abitualmente, la configurazione di Rprofile prevede il caricamento della sola libreria \base; infatti: 12 Si ricordi che nel numero di decimali da visualizzare è compreso il separatore. 53 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > (.packages()) [1] "base" • .packages(all=TRUE): fornisce la lista dei “package” disponibili in \library. Nel caso dello scrivente: > .packages(all=TRUE) [1] "KernSmooth" "MASS" [5] "bootstrap" "class" [9] "eda" "foreign" [13] "modreg" "mva" [17] "nnet" "rnotes" [21] "spatial" "splines" [25] "ts" "xtable" "base" "cluster" "integrate" "nlme" "rpart" "stepfun" "boot" "ctest" "lqs" "nls" "scatterplot3d" "survival" dove rnotes è una libreria creata ad hoc e contenente la maggior parte delle funzioni introdotte nel corso del presente lavoro. • library(): visualizza, in una finestra ad hoc, l’elenco di tutti i “package” disponibili con, a fianco, una breve descrizione degli stessi; • library(help=<package>): porge, in una finestra apposita, un breve resoconto circa il “package” specificato; • library(<package>): carica in memoria il “package” indicato. Cosı̀, ad esempio, desideando disporre delle funzioni definite in rnotes sarà sufficiente il comando: > library(rnotes) Library ‘rnotes’; Copyright (C) 2001 E.D.Isaia type ‘help(package=rnotes)’ for summary information > (.packages()) [1] "rnotes" "base" • detach(package:<package>): scarica dalla memoria il “package” specificato. Ad esempio: > detach(package:rnotes) > (.packages()) [1] "base" 54 Capitolo 2 Cenni sulle procedure grafiche Dedichiamo, ora, la nostra attenzione alla descrizione, seppur sommaria, delle principali funzioni che consentono, a partire da oggetti definiti, la creazione di grafici “standard”, precisando sin da ora che l’utente può ridefinire tali funzioni o crearne nuove secondo le proprie necessità. È bene suddividere, perlomeno idealmente, le funzioni grafiche nelle seguenti due categorie: — funzioni grafiche di “primo livello”: generano il grafico specificato corredato di assi, etichette, legende, titoli. Tali funzioni, è bene ricordalo, reinizializzano la finestra grafica; — funzioni grafiche di “secondo livello”: consentono di sovraimporre al grafico corrente alcune informazioni aggiuntive, quali, nuovi punti, linee, commenti od altro. In R, inoltre, è possibile intervenire in modo diretto sui parametri di default dell’ambiente grafico, modificandone a piacere l’aspetto. 2.1 Funzioni grafiche di “primo livello” Si tratta essenzialmente di una serie di funzioni predefinite che consentono la realizzazione di grafici “standard”. Tra esse val qui la pena citare le seguenti: 2.1.1 Funzione plot(x,y) Si tratta di una funzione assai generica e il risultato è condizionato dalla modalità del primo oggetto posto quale argomento. Infatti: Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — se x e y sono oggetti o vettori numerici, plot(x,y) porge il “classico” diagramma a dispersione di y in funzione di x. Allo stesso risultato si perviene con plot(z), posto z sia una matrice (nx2) ad elementi numerici oppure una lista; — se y rappresenta una serie storica, con plot(y) viene rappresentata la serie stessa, con in ascissa i valori dell’indice di y, cioè c(1:lenght(n)), salvo altra specificazione. — qualora x e y siano due oggetti con modalità factor il primo e numerica il secondo, plot(x,y) produce un diagramma a dispersione di y per ciascun livello di x. — se y è un vettore con modalità complessa, plot(y) produce un diagramma a dispersione con in ordinata la parte immaginaria degli elementi di y ed in ascissa quella reale. Tali sono gli argomenti obbligatori della funzione plot(). Il grafico offerto, con le avvertenze di cui sopra, provvede in modo automatico (situazione di default 1 .) alla rappresentazione dei punti di coordinate (x, y) mediante il simbolo ◦, alla suddivisione degli assi x e y in intervalli uguali tra il massimo ed il minino dei valori osservati, nonché alla visualizzazione delle etichette per gli assi x e y e di un titolo che nella forma standard è del tipo ‘Plot of ...”. Tale situazione di default può essere modificata dall’utente ricorrendo ad un ventaglio piuttosto esteso di opzioni; tra queste val la pena menzionare: — opzione che modifica la presentazione degli assi cartesiani: frame.plot=TRUE frame.plot=FALSE grafico racchiuso in una scatola (default); visualizzati i soli assi delle ascisse e delle ordinate — opzioni che alterano il campo di escursione degli assi x e/o y: xlim(c(min,max)) ylim(c(min,max)); — opzioni che modificano il tipo di rappresentazione dei punti di coordinate (x, y). Per default essi vengono rappresentati mediante un punto (◦); tale situazione può essere modificata ricorrendo a diverse opzioni; tra esse menzioninamo le seguenti: 1 Salvo diversa configurazione dei prametri grafici; a tal proposito cfr. paragrafo 2.3 56 E. D. Isaia, Linguaggio R e applicazioni statistiche type="l" type="b" type="s" type="h" type="n" coppie (x, y) congiunte da una linea; coppie (x, y) congiunte da una spezzata; coppie (x, y) congiunte da una spezzata a gradini; congiunge con un segmento x con il corrispondente y; coppie (x, y) non rappresentate; — opzioni che modificano la natura degli assi x e/o y: log="x" log="y" log="xy" dati in ascissa in forma logaritmica; dati in ordinata in forma logaritmica; entrambi gli assi in forma logaritmica; — opzioni, valide per tutte le procedure grafiche, che permettono di modificare titoli ed etichette: main="stringa" xlab="stringa" ylab="stringa" il titolo presenta l’espressione in striga; l’asse x etichettato con l’espressione in striga; l’asse y etichettato con l’espressione in striga. Evidentemente tutte le etichette scompaiono con le opzioni main="", xlab="" e ylab="". A volte può essere utile sopprimere del tutto, con il comando ann=FALSE, le annotazioni ed inserirle successivamente a piacere tramite il comando title (cfr. paragrafo 2.2). 2.1.2 Funzione matplot(x,y) Tale funzione, del tutto identica a plot per quanto concerne le diverse opzioni, se ne differenzia poiché permette di rappresentare più curve su uno stesso grafico. 2.1.3 Funzione hist(x) Tale funzione consente la creazione di un istogramma dell’oggetto numerico indicato quale argomento. Nella situazione di default il numero delle classi dell’istogramma è calcolato suddividendo il campo di escursione di x in n intervalli di ugual ampiezza, avendo cura di porre n = {1 + log 2 [length (x)]}. Infatti la funzione plot() contiene l’istruzione pretty(range(x),1+log2(length(x))). Tale situazione può essere modificata a piacere dall’utente ricorrendo all’opzione breaks=n, con n intero positivo. Ricorrendo a tale opzione, in R è possibile creare istogrammi di frequenze per dati raccolti in classi di modulo non costante; a tal proposito, posto che x contenga 100 osservazioni comprese tra 10.5 e 29.7, l’istruzione: > hist(x,breaks=c(10,15,20,30)) 57 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 porge un istogramma con classi (10 - 15], (15 - 20] e (20 - 30] ed in ordinata le corrispondenti densità, ovvero i rapporti tra le frequenze assolute di classe ed il modulo della classe stessa. Una semplice applicazione è riportata all’Esempio ??. Sempre per default, in ordinata vengono riportate, per ciascuna classe, le frequenze assolute; l’opzione freq=FALSE consente di riportare sull’asse delle ordinate le frequenze relative2 . Osserviamo, ancora, che il comando hist(...,plot=FALSE) non visualizza alcun istogramma ma crea una lista contenene i seguenti oggetti: $breaks $density $counts $mids $intensities $xname il cui significato è intuitivo. Per inciso, tale comportamento è proprio delle principali funzioni grafiche, tranne plot(). 2.1.4 Funzione boxplot(x,y,z,...) Tale funzione consente di creare un diagramma a “scatola e baffi” degli oggetti numerici indicati quale argomento. Questi potrebbero alternativamnte corrispondere ai diversi elementi di una lista o di un “data.frame”, a patto, in quest’ultimo caso, che essi abbiamo tutti la medesima cardinalità. A tal proposito, si immagini che gli oggetti mate e stat contengano, rispettivamente, i voti di Matematica e di Statistica ottenuti da 10 studenti di un corso universitario: > mate<-c(23,24,23,18,25,27,30,27,23,29) > stat<-c(24,27,21,20,27,20,30,25,18,30) Ai fini della costruzione dei diagrammi a “scatola e baffi” di cisacuna variabile si possono impartire i seguenti comandi del tutto equivalenti nel risultato: > > > > boxplot(mate,stat) boxplot(list(mate,stat)) boxplot(data.frame(mate,stat)) boxplot(data.frame(cbind(mate,stat))) Osserviamo, che in alcune situazioni può accadere di avere a disposizione due oggetti elementari, il primo dei quali contenente le osservazioni individuali di una variabile di interesse, il secondo le corrispondenti modalità di un certo fattore di stratificazione; in tali siuazioni, senza dovere modificare la struttura dei dati, si può ricorrere, in fase di definizione, all’espressione x~g, che indica che le osservazioni individuali contenute in x debbono essere stratificate in funzione delle modalità di g. Riprendendo l’esempio precedente, potremmo impartire i comandi: 2 Un’alternativa è rappresentata dall’opzione probability=TRUE. 58 E. D. Isaia, Linguaggio R e applicazioni statistiche > voti<-c(mate,stat) > materia<-c(rep(1,10),rep(2,10)) > boxplot(voti~materia) Tra le numerose sono le opzioni, ci limitamo alle seguenti di carattere assai generale: — range=n: consente di modificare la lunghezza dei “baffi”, che per default hanno una lughezza pari a 1.5 volte la differenza interquartile 3 . Ponendo range=0 essi si dimensionano in modo da includere i valori estremi; — border=colori: colora i bordi del diagramma in accordo a quanto specificato nel vettore colori; — col=colore: la scatola viene riempita con il colore indicato; — horizontal=FALSE: rappresenta la situazione di default; con horizontal=TRUE i diagrammi vengono ruotati di 90 gradi. 2.1.5 Funzioni qqplot(x,y) e qqnorm(x) Il ricorso a qqplot(x,y) consente di ottenere il diagramma a dispersione dei quantili della variabile x rispetto a quelli della variabile y, con, ovviamente, length(x) non necessariamente uguale a length(y). Se si ha cura di porre y<-qnorm(ppoints(length(x)),mean(x),sd(x)), allora i quantili di x sono raffrontati con quelli di una N (µ X , σX ). Un’alternativa consiste nel ricorso al comando qqnorm(x), il quale porge il diagramma a dispersione dei quantili della variabile x rispetto a quelli di una distribuzione normale standardizzata. Le opzioni di tali funzioni sono del tutto analoghe a quelle presentate a proposito di plot(x,y). Per una semplice applicazione, cfr. Esempio 4.2.3. 2.1.6 Funzione barplot(x) e piechart(x) Tali funzioni permettono la creazione di semplici diagrammi a barre e a torta rispettivamente. Il loro output grafico può essere arricchito, ad esempio,attribuendo delle etichette a ciascun elemento dell’oggetto specficato quale argomento. 2.1.7 Funzione polygon(x,y) Tramite tale funzione è possibile visualizzare poligoni i cui vertici sono contenuti negli oggetti x e y. A titolo di esempio: 3 In altri termini,lasciano alla loro sinistra e destra circa il 5% delle osservazioni. 59 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > > > > x<-c(9.154932,11.374214,9.313423,11.044401,8.634460,11.176227) y<-c(12.66062,31.05207,17.42724,15.11586,22.99784,18.09190) plot(x,y, type="n", xlab="", ylab="") polygon(x,y,col="red") 2.1.8 Funzione curve(espressione) Il ricorso a tale funzione consente di rappresentare graficamente sul piano cartesiano di riferimento (x, y) una qualsiasi funzione indicata in espressione, scritta quale funzione in x. La sintassi completa, peraltro di facile interpretazione è: curve(espressione,from,to,n = 101,add=FALSE) Ponendo add=TRUE è possibile sovraimporre una seconda curva al grafico corrente. Un esempio di comando valido è, pertanto, curve(x^2*(1-x^2)), che potrebbe essere migliorato definendo un intervallo in ascissa entro cui visualizzare la funzione stessa, ad esempio porre curve(x^2*(1-x^2),-1,1). In alternativa avremmo potuto definire la funzione f e successivamente rappresentarla graficamente con i comandi: > f<-function(x) (x^2*(1-x^2)) > curve(f,-1,1) 2.1.9 Funzione grid(nx,ny) Tale funzione consente di aggiungere ad un grafico una “griglia” composta da nx×ny celle delimitate da altrettante linee tratteggiate. La situazione di default, ottenibile con grid(), prevede un numero di celle pari al numero di “tick marks” presenti su entrambi gli assi. 2.1.10 La funzione rect(xmin,xmax,ymin,ymax) Ricorrendo a tale funzione possiamo costruire e visualizzare rettangoli con vertici i punti di coordinate (xmin , ymin ) e (xmax , ymax ) definite dall’utente. Quale esempio, suggeriamo all’utente di osservare il comportamento delle istruzioni: > plot(c(0, 22), c(0, 22), type = "n") > k<-4*(0:5) > rect(0+k, 0+k, 2+k, 2+k) Per inciso, è la funzione primitiva per la costruzione di istrogrammi. 60 E. D. Isaia, Linguaggio R e applicazioni statistiche 2.1.11 Funzione persp(x,y,z) Tramite tale funzione possiamo rappresentare graficamente nello spazio cartesiano (x, y, z) una qualsiasi funzione z = f (x, y) che verrà passata quale argomento. Argomenti obbligatori di persp sono: — i vettori x e y contenentI i punti (x, y) in corrispondenza ai quali calcolare i valori di z = f (x, y); — la matrice quadrata z, di dimensione length(x)×length(y), contenente appunto i valori di z = f (x, y). Desiderando, ad esempio, rappresentare graficamente la funzione: x2 y 2 z=/ (x2 + y 2 ) per x ∈ (−10, 10) e y ∈ (−10, 10), saranno sufficienti le istruzioni: 1 2 3 4 5 > > > > > x<-seq(-10, 10, length=50) y<-x f<-function(x,y){fz<-x^2*y^2/sqrt(x^2+y^2)} z<-outer(x,y,f) persp(x,y,z,theta=35,phi=35,col="lightgreen") A commento: — in riga [1] e [2] si definiscono gli intervalli per x e y entro cui visualizzare la funzione z; — la riga [3] definisce in modo chiaro la funzione f (x, y) di interesse; — in riga [4], per ogni coppia (x, y), calcoliamo i valori della funzione f che risulteranno inseriti, tramite il comando outer(x,y,f), nella matrice z di ordine dim(z)=length(x)×length(x), ovvero 50 × 50; — in riga [5] il comando persp(...) visualizza il grafico richiesto. Se osserviamo che la sintassi completa del comando è: persp(x=seq(0,1,len=nrow(z)),y=seq(0,1,len=ncol(z)),z, xlim=range(x),ylim=range(y),zlim=range(z,na.rm=TRUE), xlab=NULL,ylab=NULL,zlab=NULL,main=NULL,sub=NULL, theta=0,phi=15,r=sqrt(3),d=1,scale=TRUE,expand=1, col=NULL,border=NULL,ltheta=-135,lphi=0,shade=NA, box=TRUE,axes=TRUE,nticks=5,ticktype="simple",...) 61 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 la sintassi minima sarà dunque persp(z). Per ulteriori applicazioni, cfr. Esempi ?? e **. 2.1.12 Funzione pairs(x) Ricorrendo a tale funzione è possibile, partendo da una matrice x contenente poniamo s ≥ 2 colonne che rappresentano altrettante variabili di interesse, creare i diagrammi a dispersione tra tutte le (s2 − s) combinazioni delle variabili oggetto di studio. La sintassi per accedere a tale funzione è, nella sua veste più dimessa, pairs(x). Tra le diverse opzioni, vale la pena menzionare: — panel=function(x,y,...): consente di sovraimprimere ai diagrammi a dispersione una particolare funzione grafica definita dall’utente, ad esempio la seguente, che sovraimpone a ciascun diagramma a dispersione la corrispondente retta di regressione: panel.fit<-function(x,y,col=par("col"),pch=par("pch"),cex=1) { points(x,y,pch=pch,col=col,cex=cex) lines(x,lm(y~x)$coef[1]+lm(y~x)$coef[2]*x,col="red") } che può essere attivata con il comando pairs(x,panel=panel.fit). Lasciamo al Lettore il commento della funzione proposta alla luce di quanto esposto ai paragrafi 2.2 e 2.3 e 6.2.1. Una funzione predefinita in R è panel.smooth, la quale aggiunge, a ciascun grafico, una particolare curva di regressione cosı̀ come proposto da Cleveland (1981); — diag.panel=function(x,y,...): permette di inserire sulla diagonale principale della “matrice dei diagrammi a dispersione”, in luogo dei nomi delle s variabili coinvolte (situazione di default), particolari funzioni grafiche a seconda delle esigenze dell’utente. A tal proposito, pensando di rappresentare le s distribuzioni marginali mediante semplici istogrammi di frequenze, potremmo definire la seguente funzione4 : >panel.hist<-function(x, ...) { 4 Per ragioni di comodo, le altezze degli istogrammi corrispondono alle frequenze assolute divise per il massimo di esse. 62 E. D. Isaia, Linguaggio R e applicazioni statistiche usr<-par("usr") par(usr=c(usr[1:2],0,1.5) ) istogramma<-hist(x,plot=FALSE) tagli<-istogramma$breaks ntagli<-length(tagli) y<-istogramma$counts/max(istogramma$counts) rect(tagli[-ntagli],0,tagli[-1],y,col="lightblue") par(usr=c(0,1,0,1)) } che può essere attivata con il comando pairs(x,diag.panel=panel.hist). Lasciamo al Lettore il commento della funzione proposta, e ciò alla luce di quanto esposto ai paragrafi 2.2 e 2.3. Per una semplice applicazione, cfr. Esempio 3.2.6. — lower.panel=function(x,y,...) e upper.panel=function(x,y,...): consentono di inserire nelle celle, rispettivamente, a sinistra e a destra della diagonale principale della matrice dei diagrammi a disersione, particolari funzionidefinite dall’utente. Per un’applicazione, cfr. Esempio 3.2.6. 2.1.13 Altre funzioni grafiche Oltre a quelle citate, in R sono implementate diverse altre funzioni grafiche utili qualora si affronti lo studio di particolari problemi. Senza entrare in dettaglio, ci limitano a fornirne un mero elenco, invitando il Lettore a consultare l’aiuto in linea o il manuale di riferimento R Core Team (2000): contour(x,y,z) image(x,y,z) 2.2 coplot(...) stripplot(x) dotplot(x) sunflowerplot(x,y) Funzioni grafiche di “secondo livello” A volte i grafici ottenuti in modo automatico mediante le funzioni di “primo livello” non corrispondono a quanto desiderato, nel senso che possono mancare dettagli, informazioni aggiuntive, ... Le funzioni di “secondo livello” possono esserci di aiuto, dal momento che esse vengono semplicemente sovraimposte all’output grafico corrente. Di esse ci limitamo a citare le seguenti: • abline(a,b): aggiunge un segmento di retta di equazione y = a + bx al grafico corrente; 63 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 • abline(h=y), abline(v=x): permettono di aggiungere un segmento di retta orrizontale e verticale rispettivamente a partire dalle coordinate y e/o x specificate; • arrows(x0,y0,x1,y1,code=k,length=n,angle=m): disegna una freccia tra i punti di coordinate (x0 , y0 ) e (x1 , y1 ). Quanto al parametro code: se code=1 la freccia è disegnata nel punto (x0 , y0 ), se code=2 nel punto (x1 , y1 ) mentre se si specifica code=3 si hanno due frecce, la prima in (x 0 , y0 ) e la seconda in (x1 , y1 ). Il parametro length indica la lunghezza (in pollici) dei segmenti della freccia, mentre angle ne determina la divaricazione. • lines(x,y): permette di tracciare una “linea”, secondo i valori contenuti in x e y, al grafico corrente; • points(x,y): consente di aggiungere punti, in accordo alle coordinate specificate, al grafico corrente; • segments(x0,y0,x1,y1): traccia un segmento di retta congiungente i punti di coordinate (x0 , y0 ) e (x1 , y1 ); • text(x,y,stringa): permette di inserire, a partire dalle coordinate (x, y) specificate, il testo contenuto in stringa. Consigliamo all’utente di osservare l’output generato dalle istruzioni: > plot(1:20,type="n") > for (i in (1:20)){text(i,i, letters[i])} • title(main="...",xlab="...",ylab="...",): consente di inserire etichette per il titolo del grafico, per l’asse della ascisse e per quello delle ordinate. Si noti che occorre porre, al momento della creazione del grafico stesso, ann=FALSE. 2.3 Parametri grafici Non sempre i grafici prodotti in modo automatico ed eventualmente arricchiti mediante le funzioni di “secondo livello” soddisfano le esigenze, ad esempio tipografiche, dell’utente. Egli, tuttavia, può agire direttamente sui parametri di default delle funzioni grafiche di R, che, identificate da un nome proprio, definiscono ad esempio il tipo di caratteri, lo stile delle linee e/o dei punti, la giustificazione del testo, il layout della finestra grafica e molte cose ancora. L’elenco completo dei nomi dei 68 parametri grafici si ottinene digitando .Pars: 64 E. D. Isaia, Linguaggio R e applicazioni statistiche > .Pars [1] "adj" [6] "cex" [11] "cin" [16] "col.sub" [21] "din" [26] "font" [31] "gamma" [36] "mai" [41] "mfrow" [46] "omd" [51] "ps" [56] "tcl" [61] "xaxs" [66] "yaxs" "ann" "cex.axis" "col" "cra" "err" "font.axis" "lab" "mar" "mgp" "omi" "pty" "tmag" "xaxt" "yaxt" "ask" "cex.lab" "col.axis" "crt" "fg" "font.lab" "las" "mex" "mkh" "pch" "smo" "type" "xlog" "ylog" "bg" "cex.main" "col.lab" "csi" "fig" "font.main" "lty" "mfcol" "new" "pin" "srt" "usr" "xpd" "bty" "cex.sub" "col.main" "cxy" "fin" "font.sub" "lwd" "mfg" "oma" "plt" "tck" "xaxp" "yaxp" mentre con par() si ottiene corrispondente lista dei valori di default. Desiderando ottenere informazioni circa un parametro di interesse, possiamo impartire il comando par("parametro"); ad esempio con: > par("type") [1] "p" veniamo a sapere che per default la rappresentazione dei punti avviene in accordo all’opzione type="p". Un’eventuale modifica dei parametri grafici può avvenire con il comando par(parametro=nuovi valori); ad esempio: > par(type="l") > par("type") [1] "l" Prima di procedere a modifiche dei parametri di default, che come si è detto sono contenuti in par(), conviene creare una copia degli stessi, sı̀ da ripristinarne, a fine sessione, l’originale; ciò può avvenire, ad esempio, impartendo le istruzioni: > > > > default.par<-par ... modifiche dei parametri ... ... rappresentazioni grafiche ad hoc ... par(default.par) Data la complessità dell’argomento, ci limitiamo ad elencare il comportamento dei seguenti parametri: 65 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 • bg="colore": modifica il colore dello sfondo (“background”). Per default si ha bg="white". I colori possibili, identificati da un nome e/o da un numero progressivo, sono ben 657; il loro elenco si può ottenere con colors() oppure, più elegantemente, con colours(); • cex=n: riduce o aumenta l’output grafico nella poporzione n specificata. Per default cex=1; • col="colore": modifica il colore dell’output grafico (linee, punti, ...); per default si ha bg="white"; • fin=c(x,y): determina la dimensione, in pollici, dell’output grafico. La situazione di default prevede fin=c(5,5); • font.lab=1, font.main=2: tipo dei caratteri per la rappresentazione delle etichette per gli assi cartesiani e del titolo. Generalmente 1=testo normale, 2=grassetto, 3=corsivo e 4=corsivo grassetto; • cex.lab=1, cex.main=1.2: ingrandimento dei caratteri per la rappresentazione delle etichette per gli assi cartesiani e del titolo; • lab=c(nx,ny): consente di modificare il numero delle etichette, “tickmarks”, da apporre su entrambi gli assi di un grafico; • lty="tipo": modifica il tipo di tratteggio nella rappresentazione di linee (“line type”); la situazione di default prevede lty="solid". I tipi di tratteggio previsti, identificabili da un nome e/o da un numero progressivo da 0 a 6, sono, nell’ordine, "blank", "solid", "dashed", "dotted" "dotdash", "longdash" e "twodash"; • mfrow=c(r, s) consente di suddividere la finestra grafica in una matrice r x s, i cui elementi saranno gli output generati dalle funzioni hist(), plot(), ... La situazione di default viene ristabilita mediante mfrow=c(1, 1). Il comportamento di mfcol=c(r, s) è del tutto analogo; • pch=n: modifica il tipo di simbolo impiegato per la rappresentazione delle coppie di punti (x, y) della funzione plot(); n è un intero compreso tra 0 e 20. Per default si ha pch=1; • tmag=n: modifica la dimensione dei caratteri dei titoli, annotazioni, etichette,... Per default si ha tmag=1. • usr=c(x1, x2, y1, y2): indica le coordinate “estreme” della regione grafica; per default si ha usr=c(0,1,0,1). 66 Capitolo 3 Argomenti di statistica descrittiva Nel seguito vedremo come affrontare in R alcuni semplici argomenti di Statistica descrittiva quali la costruzione di istogrammi, diagrammi a barre, diagrammi a dispersione, diagrammi a “scatola e baffi”, la creazione di tabelle di frequenze per variabili e/o mutabili statistiche sia univariate che bivariate, il calcolo alcuni indici di posizione e/o di variabilità, l’individuazione dei coefficienti di un modello di interpolazione a minimi quadrati, il calcolo del coefficiente di correlazione lineare, l’individuazione dei parametri di una retta di regressione, ... Per comodità presenteremo i diversi problemi sottoforma di paragrafo *** comandi e funzioni ad hoc*** , poi, faremo riferimento, di volta in volta, alle variabili contenute negli archivi: — stat1.txt: misurazioni della statura (cm) e del peso (Kg) di 100 coscritti; — stat2.txt: numero di televisori e numero di autovetture posseduti da 50 famiglie; — stat3.txt: reddito netto mensile, espresso in euro, percepito da 110 individui, di cui 50 lavoratori autonomi e 60 lavoratori dipendenti; — stat4.txt: titolo di studio (licenza elementare, licenza media superiore, diploma universitario e laurea), posizione professionale (operaio, impiegato e quadro) e sesso di 50 dipendenti di una grande azienda; — stat5.txt: numero (in migliaia di unità) degli occupati, suddivisi per sesso, in Italia negli anni 1982 − 1990, fonte ISTAT; — stat6.txt: voti, espressi in trentesimi, degli esami di Matematica Generale e di Statistica di un gruppo di 40 studenti iscritti ad un corso di Diploma in Economia. che verranno acquisite in memoria via read.table(file="<nome del file>"). Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 3.1 Mutabili e variabili statistiche univariate Nel seguito vedremo come affrontare in R alcuni semplici argomenti di Statistica descrittiva quali la costruzione di istogrammi, diagrammi a barre, diagrammi a dispersione, diagrammi a “scatola e baffi”, la creazione di tabelle di frequenze per variabili e/o mutabili statistiche sia univariate che bivariate, il calcolo alcuni indici di posizione e/o di variabilità, 3.1.1 Costruzione di semplici tabelle di frequenze La costruzione di semplici distribuzioni di frequenze, in termini assoluti e/o relativi, per una mutabile o variabile statistica, le cui osservazioni individuali sono contenute nell’oggetto x, avviene semplicemente utilizzando il comando table(x). Tale modo di procedere può dare luogo a tabelle di difficile lettura e tale è il caso qualora la mutabile o la variabile statistica in esame presenti un elevato numero di modalità. In tali situazioni, com’è noto, si suole procedere ad una classificazione delle modalità, ovvero raccogliere le osservazioni individuali in “classi”. In R ciò è possibile ricorrendo al comando cut, la cui sintassi è: cut(x,breaks=ncl,right=TRUE) dove ncl indica appunto il numero delle classi desiderate 1 o, in alternativa, i limiti superiori di classe, mentre con right=TRUE, ciascuna classe viene ad essere “chiusa a destra”. Esempio 3.1.1 Acquisite in memoria le due variabili contenute in stat1.txt mediante i comandi: > stat1<-read.table(file="stat1.txt") > names(stat1) [1] "altezza" "peso" > attach(stat1) ci proponiamo di visualizzarne la distribuzione di frequenze assolute. Con riferimento alla sola variabile altezza, abbiamo: > table(altezza) altezza 164.7 166.3 167.2 167.4 167.8 167.9 168.5 169.1 169.2 169.3 169.4 170.6 170.8 1 1 1 1 1 1 1 1 1 1 1 1 1 171 171.3 171.4 172 172.6 173.6 173.8 174.2 174.5 174.6 174.9 175 175.4 1 In tal caso spetta ad R individuare l’ampiezza, costante, delle singole classi nonché i limiti inferiore e superiore delle stesse. 68 E. D. Isaia, Linguaggio R e applicazioni statistiche 1 175.6 3 179.2 1 181.5 1 185.2 1 1 1 1 1 175.9 176 176.2 176.5 1 1 2 2 179.3 179.5 179.9 180 2 2 2 1 181.9 182 182.4 182.5 1 2 1 1 185.3 185.5 186.4 186.7 1 1 1 1 1 2 1 1 176.7 177 177.2 178.1 1 1 2 3 180.1 180.3 180.4 180.8 1 1 1 2 182.8 183.1 183.6 184.2 1 2 2 2 186.9 187.1 187.3 187.4 1 1 2 1 1 178.2 1 180.9 1 184.8 1 188.4 1 1 2 4 178.5 178.6 178.9 1 1 1 181.1 181.3 181.4 1 1 1 184.9 185 185.1 1 2 1 190.9 191 192.5 1 1 1 manifestamente di difficile lettura. Una migliore leggibilità la si ottiene raccogliendo i dati individuali in classi, ad esempio, di egual ampiezza; scelto di raccogliere i dati individuali in 7 classi e lasciando a R individuare l’ampiezza ed i limiti di ciascuna di esse, avremo: > table(cut(altezza,breaks=7)) (165,169] (169,173] (173,177] (177,181] (181,185] (185,189] (189,193] 7 11 22 22 19 16 3 Una via alternativa consiste nell’indicare il limite inferiore della prima classe, l’ampiezza di classe ed il loro numero. Nel caso dell’altezza possiamo porre immaginare di raccogliere i dati individuali in 7 classi di modulo 5 cm a partire da 165 cm. In tal caso: > table(cut(altezza,breaks=160+5*(0:7))) (160,165] (165,170] (170,175] (175,180] (180,185] (185,190] (190,195] 1 10 16 32 26 12 3 In sostanza, per le variabili in esame, definiti per chiarezza espositiva gli oggetti: > (classi.alt<-160+5*(0:7)) [1] 160 165 170 175 180 185 190 195 > (classi.peso<-70+5*(0:5)) [1] 70 75 80 85 90 95 abbiamo: > table(cut(altezza,breaks=classi.alt)) (160,165] (165,170] (170,175] (175,180] (180,185] (185,190] (190,195] 1 10 16 32 26 12 3 > table(cut(peso,breaks=classi.peso)) (70,75] (75,80] (80,85] (85,90] (90,95] 12 31 41 15 1 69 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Qualora si operi su variabili statistiche, potrebbe essere interessante ripartire i valori individuali in tre classi a seconda che essi cadano entro il primo quartile, tra il primo ed il terzo, oltre il terzo; a tal fine, abbiamo approntato la seguente funzione ad hoc: > classi.speciali<-function(x) { as.real(c(min(x),quantile(x,prob=.25), quantile(x,prob=.75),max(x))) } la quale ci consente di ottenere, per le variabili in esame, le seguenti distribuzioni di frequenze: > table(cut(altezza,breaks=classi.speciali(altezza))) (165,175] (175,183] (183,192] 24 50 25 > table(cut(peso,breaks=classi.speciali(peso))) (70.6,76.8] (76.8,84.1] (84.1,91.5] 25 49 25 Ciò facendo possono evidentemente ottenersi distribuzioni di frequenze con classi di modulo non necessariamente costante. ♥ A volte capita che alle osservazioni di un carattere di interesse sia asssociata una variabile di stratificazione; ad esempio: — la statura in funzione del sesso; — il reddito annuo lordo in funzione del numero dei componenti il nucleo familiare; — il rapporto tra prezzo ed utile di titoli azionari su diverse borse; — ... Se tale è il caso, possiamo immaginare di suddividere le osservazioni individuali del carattere in tanti gruppi quanti indicato dalle modalità assunte dalla variabile di stratificazione f; a ciò sopperisce, appunto, il comando split, la cui sintassi è: split(x,f) dove f è generalmente un oggetto a valori numerici interi consecutivi di lunghezza pari a length(x), ovvero esso protrebbe possedere modalità factor. In ogni caso con split viene creata una lista i cui elementi sono gli elementi contenuti in x in corrispondenza a ciascuna modalità della stessa. 70 E. D. Isaia, Linguaggio R e applicazioni statistiche Esempio 3.1.2 L’archivio stat3.dat contiene, sottoforma di data frame, i valori del reddito netto mensile, espresso in euro, percepito da 110 individui, di cui 50 lavoratori autonomi e 60 lavoratori dipendenti. L’archivio in questione è strutturato in modo che la prima colonna riporti le misurazioni dei redditi e la seconda una variabile di tipo “flag” che assume valore 1 se il reddito proviene da lavoro autonomo e valore 2 se esso proviene da lavoro dipendente. Aquisiti i dati individuali mediante le istruzioni: > redditi<-read.table(file="stat3.txt") > names(redditi) [1] "reddito" "posizione" > attach(redditi) e desiderando, nel seguito, analizzare separatamente la distribuzione dei redditi dei lavoratori autonomi e quella dei lavoratori dipendenti, sfruttando la funzione split, che porgerebbe: > split(reddito,posizione) $"1" [1] 1949 1967 1797 1812 1855 [14] 1801 1810 2020 2105 1767 [27] 1929 1909 1868 2079 1793 [40] 1906 2103 1616 1939 1703 1698 2011 1897 1593 1855 1986 1977 1782 1703 1977 1672 1979 1989 1882 2012 1630 1865 1911 1875 1761 2099 2054 2080 1868 1672 1963 1689 1820 1631 1761 $"2" [1] [14] [27] [40] [53] 1430 1548 1551 1624 1371 1479 1468 1202 1392 1419 1357 1532 1285 1239 1178 1559 1435 1177 1492 1625 1535 1886 1078 1420 1306 1604 1530 1182 1688 1532 1249 1396 1652 1475 1084 1720 1524 1495 1386 1602 1098 1418 1770 1750 1524 1600 1548 1654 1629 1563 1301 1367 1858 1228 1785 1443 1400 1191 1428 1566 possiamo creare i due nuovi oggetti: > reddito.aut<-split(reddito,posizione)$"1" > reddito.dip<-split(reddito,posizione)$"2" su cui sarà possibile operare, ad esempio: > table(cut(reddito.aut,breaks=1550+150*(0:4))) (1550,1700] (1700,1850] (1850,2000] (2000,2150] 8 12 21 9 ♥ 71 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 3.1.2 Rappresentazioni grafiche Parallelamente alla presentazione di tabelle di frequenze, il comportamento del carattere statistico sotto esame può essere riassunto mediante opportuni grafici, ricordando che in linea di massima: — per le mutabili statistiche si fa ricorso a semplici diagrammi a barre ovvero a diagrammi circolari o a torta; — per le variabili statistiche si ricorre ad istogrammi o a diagrammi a bastoncini, a seconda che la variabile sia di tipo continuo o discreto. Inlotre, nel caso si operi su variabili statistiche, può essere interessante evidenziare l’andamento della funzione delle frequenze cumulate oppure ricorrere a semplici “boxplot”, o diagrammi a “scatola e baffi”; com’è noto, tali rappresentazioni grafiche offrono informazioni intuitive circa i quantili, la variabilità e l’eventuale simmetria della distribuzione del carattere in esame. Esempio 3.1.3 Con riferimento alla variabile statistica altezza di cui all’Esempio 3.1.1, mantenendo il raggruppamento in classi: > (classi.alt<-160+5*(0:7)) [1] 160 165 170 175 180 185 190 195 l’istogramma di frequenze relative e la funzione delle frequenze relative cumulate, riportati in figura (3.1), sono ottenuti mediante le istruzioni: 1 2 3 4 5 6 7 8 9 10 > fcum.classi.alt<-c(0,cumsum(table(cut(altezza,breaks=classi.alt))) /length(altezza)) > par(mfrow=c(1, 2)) > hist(altezza,breaks=classi.alt,probability=TRUE,col="light yellow", main="",xlab="Classi di altezza",ylab="Frequenze relative") > plot(classi.alt,fcum.classi.alt,col="blue",xlab="Classi di altezza", ylab="Frequenze relative cumulate",main="",frame.plot=FALSE) > lines(classi.alt,fcum.classi.alt,col="red") > grid() > par(mfrow=c(1, 1)) A commento, si noti che: — al fine della rappresentazione grafica della funzione delle frequenze relative cumulate della variabile statistica in esame, occorre dapprima procedere al calcolo 2 delle frequenze relative cumulate, calcolate, linee [1]-[2], ricorrendo alle funzioni cumsum(variabile) e length(variabile); 2 Perlomeno per motivi di chiarezza espositiva. 72 0.8 0.6 0.4 0.0 0.2 Frequenze relative cumulate 0.04 0.02 0.00 Frequenze relative 0.06 1.0 E. D. Isaia, Linguaggio R e applicazioni statistiche 160 170 180 190 160 Classi di altezza 170 180 190 Classi di altezza Figura 3.1: Istogramma e funzione di frequenze cumulate — Esempio 3.1.2 — desiderando rappresentare sul piano cartesiano anche i punti di coordinate del tipo (u, w), dove u rappresentano gli estremi superiori di classe e w i valori delle frequenze relative cumulate, converrà dapprima rappresentare tali punti e successivamente, tramite il comando lines(), tracciare la spezzata che li congiunge. Si osservino le istruzioni in linea [6], [7] e [8]. A risultati simili a quelli sopra descritti saremmo potuti giungere mediante l’istruzione: > plot(classi.alt,fcum.classi.alt,type="b") lasciandone al Lettore la verifica sul campo. ♥ Esempio 3.1.4 Con riferimento alle variabile statistica reddito.aut definita all’Esempio 3.1.2, i comandi che seguono producono gli istogrammi proposti in figura (3.2): > par(mfrow=c(1,2)) > hist(reddito.aut,probability=TRUE,col="light yellow", main="",xlab="Calssi di reddito",ylab="Frequenze relative") > hist(reddito.aut,breaks=c(1500,1700,1800,2000,2150),col="light yellow", main="",xlab="Calssi di reddito",ylab="Frequenze relative") > par(mfrow=c(1,1)) di immediata interpretazione. ♥ 73 0.0020 0.0000 0.0010 Frequenze relative 0.0020 0.0010 0.0000 Frequenze relative Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 1500 1700 1900 2100 1500 Calssi di reddito 1700 1900 2100 Calssi di reddito Figura 3.2: Istogrammi con classi a modulo costante e non costante— Esempio 3.1.3 Esempio 3.1.5 Sempre con riferimento alle variabili reddito.aut e reddito.dip introdotte all’Esempio 3.1.2, il grafico a “scatola e baffi” riprodotto in figura (3.3) ed ottenuto mediante le istruzioni: > boxplot(reddito.aut,reddito.dip,reddito,col="light yellow", names=c("Autonomo","Dipendente","Autonomo+Dipendente")) evidenzia come ci si trovi in presenza di due diverse distribuzioni dei redditi. In particolare, si noti come la distribuzione dei redditi da lavoro autonomo sia tutta spostata verso l’alto rispetto a quella dei redditi da lavoro dipendente. Inoltre, mentre entrambe le distribuzioni tendano ad essere simmetriche (si noti la posizione delle rispettive mediane all’interno della “scatola”), i redditi da lavoro dipendente mostrano una maggiore variabilità. Volutamente il grafico di figura (3.3) riporta anche il “boxplot” relativo alla variabile reddito. I “diagrammi a scatola e baffi” delle sole due variabili reddito.aut e reddito.dip possono essere ottenuti in modo diretto tramite il comando: > boxplot(reddito.aut,reddito.dip,names=c("Autonomo","Dipendente")) o, alternativamente: 74 1200 1400 1600 1800 2000 E. D. Isaia, Linguaggio R e applicazioni statistiche Autonomo Dipendente Autonomo+Dipendente Figura 3.3: Diagramma a “scatola e baffi” — Esempio 3.1.5 > boxplot(split(reddito,posizione),names=c("Autonomo","Dipendente")) cioè senza dovere introdurre le variabili reddito.aut e reddito.dip ♥ Esempio 3.1.6 Per cose ormai note, introdotto per comodità l’oggetto: > x<-nchar(apropos(".",mode="function")) il successivo comando table(x) porge la distribuzione, in termini di frequenze assolute, del numero di caratteri delle funzioni definite in R: > table(x) x 1 2 3 24 34 59 18 19 20 29 14 18 4 5 6 7 8 9 85 115 122 129 104 114 21 22 23 24 26 13 3 2 1 1 10 91 11 90 12 82 13 70 14 51 15 42 16 32 17 25 La distribuzione di tale variable discreta può essere riassunta graficamente mediante un diagramma a bastoncini e, per completezza, la corrispondente funzione delle frequenze relative cumulate; a tal fine sono sufficienti le istruzioni: 75 0 0.8 0.6 0.4 0.0 0.2 80 60 40 20 Frequenze assolute 100 Frequenze relative cumulate 120 1.0 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 1 4 7 10 14 18 22 26 0 Numero di caratteri 5 10 15 20 25 Classi di altezza Figura 3.4: Diagramma a bastoncini e funzione cumulativa — Esempio 3.2.1 > fcum.x<-cumsum(table(x))/length(x) > par(mfrow=c(1,2)) > plot(table(x),type="h",main="",xlab="Numero di caratteri", ylab="Frequenze assolute",col="blue") > plot(sort(unique(x)),fcum.x,main="",xlab="Classi di altezza", ylab="Frequenze relative cumulate",type="s",col="blue") > par(mfrow=c(1,1)) che producono i grafici desiderati riportati in figura (3.4). ♥ A conclusione del paragrafo, osserviamo che qualora si operi con variabili statistiche continue, l’istogramma costituisce un’approssimazione della “curva di densità”, diciamo f (x), che caratterizza la variabile in esame; immaginando che le classi abbiano ampiezza costante h, tale approssimazione avviene attribuendo a tutti i punti x ∈ IR appartenenti alla i-esima classe, il medesimo valore n i /n h. Sotto tale profilo, appare evidente come la determinazione del numero delle classi sia quanto mai delicata; un numero di classi esiguo comporta in genere una perdita di informazione mentre un numero elevato di classi può produrre grafici incoerenti, ad esempio alcune classi potranno avere frequenze nulle o quasi. Un diverso approccio al problema ci è offerto da quelle tecniche che in Statistica vanno sotto il nome di teoria della stima non parametrica di una densità; su tal argomento 76 E. D. Isaia, Linguaggio R e applicazioni statistiche si possosno consultare i testi introduttivi di Bowman, Azzalini (1997) e Wand, Jones (1995). Senza entrare in dettagli, vale qui la pena accennare, perlomeno dal punto di vista operativo, al cosidetto metodo della finestra mobile o della stima a kernel, secondo il h quale in corrispondenza ad un prefissato x ∈ IR si costruisce una classe ]x − h 2 ; x + 2 [, di ampiezza appunto h e, indicando con n x il numero delle osservazioni individuali che cadono nella classe stessa, l’approssimazione di f (x) verrà data dal rapporto n x /n h; naturalmente iterando tale processo su tutto IR si perverrà all’approssimazione fˆ(x) di f (x). Generalizzando, si potrebbe dimostrare che fˆ(x) soddisfa la relazione: 1 x − xi fˆ(x) = K( ) nh h dove K, detta funzione kernel, è la funzione indicatrice in ] − 1/2; 1/2[ e pertanto K(u) = 1 per −1/2 ≤ u < 1/2. In pratica, si preferisce ricorrere a funzioni kernel che offrano una migliore “lisciatura” per fˆ(x); tra queste citiamo il kernel gaussiano, per cui K(u) = (2 π) −1 exp −u2 /2. Ovviamente, resta aperto, come nel caso dell’approssimazione mediante un istogramma, il problema della scelta di h. A tal proposito la letteratura specialistica abbonda di proposte di metodi analitici ed empirici; per dettagli si rimanda ancora ai testi di Bowman, Azzalini (1997) e Wand, Jones (1995) ed alla bibliografia ivi citata. In R è possibile eseguire una siffatta analisi ricorrendo alla funzione density, la cui sintassi minima, supponendo che le osservazioni individuali del carattere continuo in esame siano raccolte nell’oggetto x, è: density(x) che, ricorrendo per default ad una funzione kernel gaussiana, e visualizza alcune informazioni circa la variabile di input, il valore proposto per h, nonché alcune misure riassuntive sui 512 valori x e i corrispondenti valori di ordinata y = fˆ(x). Questi, in particolare, possono essere estratti dalla lista creata dalla funzione stessa con i consueti comandi density(x)$x e density(x)$y ed utilizzati per altri fini, ad esempio la visualizzazione della funzione fˆ(x) mediante l’istruzione: > plot(density(x)$x,density(x)$y) Esempio 3.1.7 Riprendendo i dati relativi ai redditi e contenuti in stat3.txt: > redditi<-read.table(file="stat3.txt") > attach(redditi) 77 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 1800 2200 0.0012 1000 1400 1800 Classi di reddito (c) 12 classi - modulo = 100 (d) 15 classi - modulo = 80 1800 2200 Classi di reddito 0.0006 Frequenze relative 1400 2200 0.0012 Classi di reddito 0.0000 1000 0.0006 Frequenze relative 0.0006 0.0000 1400 0.0012 1000 0.0000 0.0012 (b) 8 classi - modulo = 150 0.0006 Frequenze relative 0.0000 Frequenze relative (a) 6 classi - modulo = 200 1000 1400 1800 2200 Classi di reddito Figura 3.5: Istogrammi della distribuzione dei redditi — Esempio 3.2.2 la figura (3.5) riporta alcuni istogrammi per la variabile reddito costruiti ipotizzando quattro diversi raccoglimenti in classi dei dati individuali; in particolare l’istogramma (c) suggerisce un comportamento bimodale della distribuzione in esame, il che fa supporre di essere in presenza di due diverse distribuzioni quanto a parametri di scala e, probabilmente, di variabilità. Alle stesse conclusioni saremmo giunti effettuando una “stima a kernel” mediante la funzione density; infatti il comportamento bimodale della distribuzione dei redditi viene evidenziato dai grafici riportati in figura (3.6), ottenuti mediante le istruzioni: 1 2 3 4 5 6 7 8 > par(mfrow=c(1,2)) > plot(density(reddito),main="Kernel normale - h = 92.55",xlab="Reddito", ylab="",col="red",cex.main=1,font.main=1,frame.plot=FALSE) > hist(reddito,breaks=12,probability=TRUE,main="", xlab="Classi di reddito",ylab="",col="light yellow",cex.main=1, font.main=1,xlim=c(min(density(reddito)$x),max(density(reddito)$x))) > lines(density(reddito)$x,density(reddito)$y,type="l",col="red") > par(mfrow=c(1,1)) 78 E. D. Isaia, Linguaggio R e applicazioni statistiche 0.0000 0.0000 0.0004 0.0004 0.0008 0.0008 0.0012 0.0012 Kernel normale - h = 92.55 1000 1500 2000 1000 Reddito 1500 2000 Classi di reddito Figura 3.6: Stima a kernel della distribuzione dei redditi — Esempio 3.2.2 a commento delle quali, ci limitiamo ad osservare che, a parte alcune consuete opzioni di formato (main="...", xlab="...", ..., frame.plot=...): ˆ — in riga [2] e [3] si richiede il grafico di f(x) nella forma plot(density(reddito)), in alternativa a: plot(density(reddito)$x,density(reddito)$y,type="l",...) — le righe [4], [5] e [6] consentono di visualizzare l’istogramma, articolato su 12 classi a modulo costante, della variabile in esame, nell’intervallo: xlim=c(min(density(reddito)$x),max(density(reddito)$x)) ˆ — in riga [7], infine, all’istogramma viene sovraimposto il grafico di f(x). Si noti che, in “modo automatico”, R propone quale valore per h: > density(reddito)$bw [1] 92.54717 Valori maggiori o minori di h produrrebbero, come emerge dai grafici riportati in figura (3.7), curve o troppo “liscie” o troppo “aderenti” alle osservazioni individuali. ♥ 79 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 0.0010 0.0005 0.0000 0.0000 0.0005 0.0010 0.0015 Kernel normale - h = 30 0.0015 Kernel normale - h = 200 500 1000 1500 2000 2500 1000 Reddito 1400 1800 2200 Reddito Figura 3.7: Stime a kernel della distribuzione dei redditi — Esempio 3.2.2 3.1.3 Su alcune misure di sintesi Sulle principali funzioni statistiche, per cosı̀ dire “primitive”, si è già detto in (1.2.5), pertanto nel seguito affronteremo alcuni problemi specifici che porteranno alla creazione di funzioni ad hoc o all’impiego di particolari funzioni predefinite. La funzione stat.base In molti casi, potrebbe essere di qualche utilità, perlomeno nella prima fase di descrizione di un carattere statistico quantitativo, disporre di una semplice funzione che, a seconda del vettore di dati in ingresso, calcoli e visualizzi le principali misure di posizione e di variabilità. Tale funzione, a cui daremo il nome stat.base, potrebbe assumere la forma: 1 2 3 4 5 6 7 stat.base <-function(x,digits=4) { n.oss<-length(x) ris<-c(1:10) ris[1]<-round(mean(x),digits) ris[2]<-round(median(x),digits) ris[3]<-round(quantile(x,0.25),digits) 80 E. D. Isaia, Linguaggio R e applicazioni statistiche ris[4]<-round(quantile(x,0.75), digits) ris[5]<-round(quantile(x,0.75)-quantile(x,0.25),digits) ris[6]<-round(max(x)-min(x), digits) ris[7]<-round(var(x)*(sum(x)-1)/(sum(x)),digits) ris[8]<-round((var(x)*(sum(x)-1)/(sum(x)))^.5,digits) ris[9]<-round(sum(x),digits) ris[10]<-round(var(x)*(sum(x)-1),digits) ris<-matrix(ris,ncol=1) dimnames(ris)<-list(c("Media","Mediana:","I quartile:", "III quartile:","Diff. Interquartile:","Range:","Varianza:", "S.q.m.:","Somma:","Devianza"),"") cat("Vettore dei dati individuali: ", deparse(substitute(x)), "\nOsservazioni: ", n.oss, "\n--------------------","\nStatistiche:","\n") return(ris) 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 } A commento, si osservi: — il ricorso alla definizione del vettore ris i, cui elementi sono ris[i] con evidentemente i = 1, 2, . . . , 10; — l’impiego della funzione dimnames(ris) quale lista contenente le stringhe di identificazione di ciascun risultato proposto; — l’uso della funzione deparse(substitute(x)) che fa apparire a fianco dell’etichetta "Vettore dei dati individuali:" il vero nome della variabile oggetto di studio; — l’impiego di round(oggetto,digits) dove, per default, si ha digits=4; situazione che potrebbe essere modificata ricorrendo a stat(oggetto,digits=n), con n intero positivo. Esempio 3.1.8 Con riferimento alla sola variabile altezza contenuta in stat1.txt, il ricorso alla funzione stat.base produrrebbe: > stat1<-read.table(file="stat1.txt") > attach(stat1) > stat.base(altezza) Vettore dei dati individuali: altezza Osservazioni: 100 -------------------Statistiche: 81 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Media 178.5150 Mediana: 178.7500 I quartile: 174.9750 III quartile: 182.8750 Diff. Interquartile: 7.9000 Range: 27.8000 Varianza: 36.8736 S.q.m.: 6.0724 Somma: 17851.5000 Devianza 658248.4568 > detach(stat1) ♥ Le differenze assolute medie In R non è implementata alcuna funzione che permetta il calcolo delle differenze assolute medie con (o senza) ripetizione, sicché l’utente è obbligato a ricorrere ad una funzione creata ad hoc. Ricordando che, operando sui dati individuali x α , α = 1, 2, . . . n, le differenze assolute medie sono definite come: ∆R = !n α=1 !n β=1 2 |xα − xβ | ∆= n !n α=1 !n β=1 |xα − xβ | n (n − 1) a seconda che esse siano, rispettivamente, con o senza ripetizione, a fini operativi sarà sufficiente calcolare la quantità posta a numeratore, la quale può essere posta nella forma: (3.1) 1 D 1t dove D indica la matrice quadrata delle differenze in modulo |x α − xβ |, cioè: |x1 − x1 | ... D = |xα − x1 | ... |xn − x1 | . . . |x1 − xβ | ... ... . . . |xα − xβ | ... ... . . . |xn − xβ | . . . |x1 − xn | ... ··· . . . |xα − xn | ... ··· . . . |xn − xn | mentre 1 è un vettore riga ad elementi unitari. Ciò premesso, osservando che la (3.1) equivale al calcolo della somma degli elementi di D ed ipotizzando che le n osservazioni individuali del carattere quantitaivo in esame siano raccolte nell’oggetto x, si possono impartire direttamente i comandi: 82 E. D. Isaia, Linguaggio R e applicazioni statistiche 1 2 3 4 x<-rbind(x) s.dif<-sum(abs(matrix(outer(x,x,"-"),ncol(x),ncol(x)))) s.dif/length(x)^2 s.dif/(length(x)*(length(x)-1)) a commento dei quali osserviamo: — in riga [1] si ridefinisce x quale vettore riga; — in riga [2] si procede al calcolo della (3.1), il cui risultato viene inserito nell’oggetto s.dif. Si noti che la matrice D viene individuata mediante la semplice istruzione: abs(matrix(outer(x,x,"-"),ncol(x),ncol(x))) — le righe [3] e [4] porgono, rispettivamente, le differenze assolute medie con ripetizione e senza ripetizione. Esempio 3.1.9 Posto che x contenga gli interi consecutivi da 1 a 4, abbiamo: > x<-rbind(1:4) > s.dif<-sum(abs(matrix(outer(x,x,"-"),ncol(x),ncol(x)))) > s.dif/length(x)^2 [1] 1.25 > s.dif/(length(x)*(length(x)-1)) [1] 1.666667 In particolare: > abs(matrix(outer(x,x,"-"),ncol(x),ncol(x))) [,1] [,2] [,3] [,4] [1,] 0 1 2 3 [2,] 1 0 1 2 [3,] 2 1 0 1 [4,] 3 2 1 0 > sum(abs(matrix(outer(x,x,"-"),ncol(x),ncol(x)))) [1] 20 come il Lettore può facilmente verificare. ♥ Qualora l’utente non disponesse dei dati individuali x α , ma unicamente della distribuzione di frequenze {xi , ni }i=1,2,...,k del carattere quantitativo in esame, allora la 83 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 quantità posta a numeratore delle differenze assolute medie con o senza ripetizione risulterebbe: k ! k ! i=1 j=1 |xi − xj | ni nj e in tal caso si tratterà di calcolare: (3.2) n D nt dove D indica la matrice quadrata, di dimensione k × k, delle differenze in modulo |xi − xj |, mentre n è un vettore riga i cui k elementi corrispondono alle frequenze assolute ni . Quindi, ipotizzando che gli oggetti xi e ni contengano, rispettivamente, le k modalità quantitative del carattere in esame e le corrispondenti frequenze assolute, si possono impartire direttamente i comandi: > > > > > xi<-rbind(xi) ni<-rbind(ni) s.dif<-ni%*%abs(matrix(outer(xi,xi,"-"),ncol(xi),ncol(xi)))%*%t(ni) s.dif/sum(ni)^2 s.dif/(sum(ni)*(sum(ni)-1)) Ciò premesso, la funzione difemedie che segue si occupa del calcolo delle differenze assolute medie con e senza ripetizione e ciò indipendentemente dal fatto che quale input si immetta il solo vettore x delle osservazioni individuali oppure i due vettori, x e ni contenenti, rispettivamente, le k modalità rilevate del carattere e le corrispondenti frequenze assolute: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 difmedie<-function(x,ni,decimali=4,print.out=TRUE) { if (!is.matrix(x)){x<-rbind(x)} if (missing(ni)){ni<-rep(1,length(x))} if (!missing(ni) && !is.matrix(ni)){ni<-rbind(ni)} s.dif<-ni%*%abs(matrix(outer(x,x,"-"),ncol(x),ncol(x)))%*%t(ni) delta.cr<-s.dif/sum(ni)^2 delta.sr<-s.dif/(sum(ni)*(sum(ni)-1)) if (print.out) { cat(" Dif. medie CR -> ",round(delta.cr,decimali),"\n") cat(" Dif. medie SR -> ",round(delta.sr,decimali),"\n") } invisible(list(D.cr=as.real(delta.cr),D.sr=as.real(delta.sr))) } 84 E. D. Isaia, Linguaggio R e applicazioni statistiche A commento della funzione proposta: — in riga [3] si controlla che l’oggetto in entrata sia un vettore; in caso contrario si provvede alla sua trasformazione locale; — in riga [4], si crea, qualora non sia stato definito in modo esplicito, il vettore unitario ni, mentre in riga [5], verificata l’esistenza dell’oggetto in entrata ni contenente le frequenze assolute, lo si trasforma, se è il caso, in un vettore; — in riga [6] si procede al calcolo della (3.2), mentre le righe [7] e [8] si occupano del calcolo delle differenze assolute medie con ripetizione (delta.cr) e senza ripetizione (delta.sr); — in riga [9] il controllo if (print.out) consente di visualizzare i risultati, a patto che print.out=TRUE (situazione di default); — le righe [11] e [12] visualizzano i risulati desiderati; — in riga [14] viene creata una lista contenente i risultati che può servire a visualizzare, e se è il caso utilizzare per successive elaborazioni, uno dei due oggetti delta.cr o delta.cr. Esempio 3.1.10 A puro scopo didattico, si immagini che da un’indagine effettuata su 60 automobilisti italiani, al fine di indagare circa il numero di infrazioni al Codice della Strada commesse nel corso dell’anno corrente, risultino i seguenti valori individuali: 0 1 0 1 0 0 0 3 0 0 1 3 4 0 0 4 4 1 0 0 0 7 0 0 0 1 2 1 0 0 0 2 0 0 0 0 0 3 1 1 0 0 1 0 0 0 0 4 2 0 0 0 0 0 0 0 1 0 0 0 Definito l’oggetto x contenente le 60 osservazioni e sfruttando la funzione difemedie, abbiamo: > x<-c(0,1,0,0,4,4,0,7,0,1,0,0,0,1,1,0,2,0,0,0,1,0,3,1,0,4,0,0,1,0, 2,0,3,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,2,0,0,0,1,0,0,4,0,0,1,0) > difmedie(x) Dif. medie CR -> 1.2367 Dif. medie SR -> 1.2576 Dal momento che la distribuzione di frequenze del carattere in esame è: > table(x) x 0 1 2 3 39 10 3 3 4 4 7 1 85 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 saremmo giunti agli stessi risultati definendo gli oggetti xi e ni contenenti le k = 6 modalità del carattere e le corrispondenti frequenze assolute, infatti: > (xi<-sort(unique(x))) [1] 0 1 2 3 4 7 > (ni<-as.real(table(x))) [1] 39 10 3 3 4 1 > difmedie(xi,ni) Dif. medie CR -> 1.2367 Dif. medie SR -> 1.2576 Si noti che, desiderando visualizzare unicamente la differenza assoluta media con ripetizione, potremmo, a questo punto, impartire indifferentemente i comandi: > difmedie(x,print.out=FALSE)$D.cr [1] 1.236667 > difmedie(xi,ni,print.out=FALSE)$D.cr [1] 1.236667 ottenendo, coerentemente, gli stessi risultati. ♥ Sulla stratificazione Come già si osservò, a volte capita che le n osservazioni individuali di un carattere possano essere ripartite in più gruppi (o “strati”) a seconda dalle modalità assunte da una variabile di stratificazione. Nel seguito vedremo come sia possibile, qualora di operi con un carattere quantitativo, ottenere le più comuni misure di posizione e di variabilità per ciascun strato. A tal fine, per scioltezza espositiva, supporremo che le n osservazioni individuali del carattere in esame siano raccolte nell’oggetto x e che flag contenga le k ≤ n modalità, non necessariamente numeriche, della variabile di stratificazione. Un primo modo di procedere consiste ovviamente nel creare, ricorrendo al comando split, tante nuove variabili quante indicato dalla variabile di stratificazione e su ciascuna di esse applicare la funzione statistica di interesse. Agli stessi risutlati, ma in modo più “elegante”, si può giungere sfruttando le funzioni tapply o sapply, le cui sintassi, perlomeno nella veste più dimessa, si presentano: tapply(x,flag,funzione) sapply(split(x,flag),funzione) dove funzione è, in linea di massima, una qualsiasi funzione predefinita o eventualmente definita dall’utente. Un terzo modo di risolvere il problema consiste nel ricorso alla funzione aggregate, la cui sintassi minima è: 86 E. D. Isaia, Linguaggio R e applicazioni statistiche aggregate(x,list(flag),funzione) la quale, sfruttando la funzione tapply, porge i risultati desiderati in forma tabellare. L’esempio che segue illustra i tre diversi approcci testé descritti. Esempio 3.1.11 A puro scopo didattico, si immagini che su un un collettivo costituito 14 studenti universitari, di cui 8 di sesso maschile, si sia rilevato il voto conseguito ad un particolare esame di profitto; definiti gli oggetti elementari: voto<-c(23,27,27,30,25,20,27,27,18,27,27,30,30,23) sesso<-c("M","M","M","M","M","M","M","M","F","F","F","F","F","F") aggregate(stat,list(sex),mean) ci proponiamo di calcolare il voro medio in funzione del sesso: — introducendo due nuove varibili: > (femmine<-split(voto,sesso)$"F") [1] 18 27 27 30 30 23 > (maschi<-split(voto,sesso)$"M") [1] 23 27 27 30 25 20 27 27 > mean(femmine) [1] 25.83333 > mean(maschi) [1] 25.75 — ricorrendo alla funzione tapply: > tapply(voto,sesso,mean) F M 25.83333 25.75000 per cui il voto medio dei maschi è: > as.real(tapply(voto,sesso,mean)[2]) [1] 25.75 — sfruttando la funzione sapply: > sapply(split(voto,sesso),mean) F M 25.83333 25.75000 per cui il voto medio delle femmine risulta: > as.real(sapply(split(voto,sesso),mean)[1]) [1] 25.83333 87 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — ricorrendo alla funzione aggregate: > aggregate(voto,list(sesso),mean) Group.1 x 1 F 25.83333 2 M 25.75000 per cui il voto medio dei maschi è: > as.real(aggregate(voto,list(sesso),mean)[2,2]) [1] 25.75 ♥ Sui valori mancanti Se un oggetto contiene valori mancanti, classificati come NA (acronimo di “Not Available”) l’applicazione delle funzioni statistiche comporta alcuni problemi poiché essi, per default, vengono conteggiati in length(oggetto). In effetti le funzioni in questione tengono conto della possiblità di escludere i valori mancanti; ad esempio la funzione mean è definita: mean<-function(x,na.rm=FALSE) { if(na.rm) {x<-x[!is.na(x)]} else if(any(is.na(x))) {return(NA)} sum(x)/length(x) } sicché è sufficiente modificare la situazione di default na.rm=FALSE in na.rm=TRUE. Ad esempio: > x<-c(NA,12,NA,14,15,17,21) > mean(x) [1] NA > mean(x,na.rm=TRUE) [1] 15.8 Nel seguito proponiamo due semplici alternative che a nostro avviso permettono un maggior controllo dei valori mancanti. Le funzioni off.na(x) e rep.na(x) consentono di modificare un oggetto che presenta elementi mancanti (NA). La prima funzione si limita ad eliminarli, mentre la seconda sostituisce tali valori con il valor medio o, a discrezione dell’utente, con la mediana di x. *** Per comodità i nuovi valori in uscita sono messi negli oggetti w.off e w.rep rispettivamente. I listati delle due funzioni sono: 88 E. D. Isaia, Linguaggio R e applicazioni statistiche 1 off.na<-function(x){x<-x[!is.na(x)]} Cosı̀ ad esempio: > x<-c(NA,12,NA,14,15,17,21) > mean(off.na(x)) [1] 15.8 1 2 3 4 5 6 7 rep.na<-function(x, media=TRUE) { if (!media){valore<-median(x[!is.na(x)])} else {valore<-mean(x[!is.na(x)])} for (i in (1:length(x))){if (is.na(x[i])==TRUE) {x[i]<-valore}} x<-x } > rep.na(x) The new w.rep object has been created > w.rep [1] 15.8 12.0 15.8 14.0 15.0 17.0 21.0 > rep.na(x,media=FALSE) The new w.rep object has been created > w.rep [1] 15 12 15 14 15 17 21 3.1.4 3.2 Sulla concentrazione Mutabili e variabili statistiche bivariate 3.2.1 Tabelle di frequenze doppie 3.2.2 L’indice di dipendenza chi-quadro 3.2.3 L’indice di dipendenza in media 3.2.4 Sulla correlazione lineare Esempio 3.2.1 Con riferimento alle variabili qualitative contenute in stat4.dat, ci proponiamo di costruire la distribuzione congiunta del titolo di studio (studio) e della posizione professionale (posizio) dei 50 individui intervistati. Acquisiti i dati mediante le consuete istruzioni: > esempio4<-read.table(file="stat4.txt") > names(esempio4) 89 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 [1] "studio" "posizio" "sex" > attach(esempio4) la distribuzione congiunta di frequenze assolute desiderata la si ottiene mediante l’istruzione: > table(studio,posizio) posizio studio 0 1 2 0 10 1 1 1 6 14 1 2 0 10 3 3 0 1 3 Desiderando migliorare la leggibilità della tabella proposta, possiamo ricorrere ai comandi array() e dimnames(); infatti, impartite le istruzioni: >tutti<-array(table(studio,posizio),c(length(unique(studio)), length(unique(posizio)))) > dimnames(tutti)<-list(studio = c("L.Elem.", "M.Sup.", "Dipl.", "Laurea"),posizio = c("Operaio", "Impiegato", "Quadro")) Posizione professionale Titolo di studio Operaio L.Elem. M.Sup. Laurea Impiegato Dipl. Figura 3.8: Diagrammi a torta — Esempio 3.1.1 otteniamo la seguente tabella: 90 Quadro E. D. Isaia, Linguaggio R e applicazioni statistiche > tutti posizio studio Operaio Impiegato Quadro L.Elem. 10 1 1 M.Sup. 6 14 1 Dipl. 0 10 3 Laurea 0 1 3 di cui in figura (3.8) riportiamo i diagrammi delle rispettive distribuzioni marginali. ♥ Esempio 3.2.2 Con riferimento alla situazione di cui all’Esempio 3.2.1, ci proponiamo di individuare le distribuzioni congiunte i frequenze assolute del titolo di studio (studio) e della posizione professionale (posizio) condizionatamente al sesso. A tal fine (cfr. Esempio 3.1.4) possiamo ricorrere al comando split(variabile,flag); le istruzioni: > > > > studio.f<-split(matrice[,1],matrice[,3])$"0" studio.m<-split(matrice[,1],matrice[,3])$"1" posizio.f<-split(matrice[,2],matrice[,3])$"0" posizio.m<-split(matrice[,2],matrice[,3])$"1" ci consentono, infatti, di generare le seguenti due tabelle > table(studio.m,posizio.m) posizio.m studio.m 0 1 2 0 7 1 1 1 2 7 0 2 0 5 1 3 0 0 2 > table(studio.f,posizio.f) posizio.f studio.f 0 1 2 0 3 0 0 1 4 7 1 2 0 5 2 3 0 1 1 Anche in questo caso (cfr. Esempio 3.2.1) possiamo migliorare la leggibilità delle tabella ricorrendo ai comandi array() e dimnames(); tuttavia ci pare utile disporre di una sola lista, che chiameremo ms.sex, contenente le tabelle in esame sottoforma di matrice. A tal fine: — creiamo l’oggetto ms.sex i cui elementi sono le frequenze assolute delle distribuzioni congiunte table(studio.m,posizio.m) e table(studio.m,posizio.m); cioè: > ms.sex<-c(c(table(studio.m,posizio.m)),c(table(studio.f,posizio.f))) 91 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — trasformiamo l’oggetto ms.sex in array(), con dimensioni pari al numero delle modalità di ciascuna m.s. considerata, mediante l’istruzione: > ms.sex<-array(ms.sex,dim=c(length(unique(studio)), length(unique(posizio)),length(unique(sex))) — miglioriamo la leggibilità della matrice attribuendo le appropriate etichette alla sue modalità con il comando: > dimnames(ms.sex)<-list(studio = c("L.Elem.","M.Sup.","Dipl.", "Laurea"),posizio = c("Operaio","Impiegato","Quadro"), sesso =c("Maschi","Femmine")) In definitiva in ms.sex avremo: > ms.sex , , sesso = Maschi posizio studio Operaio Impiegato Quadro L.Elem. 7 1 1 M.Sup. 2 7 0 Dipl. 0 5 1 Laurea 0 0 2 , , sesso = Femmine posizio studio Operaio Impiegato Quadro L.Elem. 3 0 0 M.Sup. 4 7 1 Dipl. 0 5 2 Laurea 0 1 1 Osservazione 3.2.1 Desiderando estrarre, per ulteriori elaborazioni, le distribuzioni congiunte condizionate alla mutabile sesso, possiamo ricorrere ai consueti comandi, ricordando che ms.sex è un array a tre dimensioni; ad esempio: > ms.sex.maschi<-ms.sex[,,sesso="Maschi"] > ms.sex.femmine<-ms.sex[,,sesso="Femmine"] ♥ Esempio 3.2.3 Con riferimento alla situazione descritta agli Esempi 3.2.1 e 3.2.2, ci proponiamo ora il calcolo, per ciascuna delle due distribuzioni congiunte presenti in ms.sex, dell’indice di dipendenza globale χ2 del Pearson nonché dell’indice normalizzato V del Cramér, definiti, con ovvio significato dei simboli: ) *0.5 ) *0.5 r ! r ! (nij − n̂2ij ) χ2 χ2 2 χ = V = = inf [n (r − 1); n (s − 1)] n2ij M ax(χ2 ) i=1 i=1 92 E. D. Isaia, Linguaggio R e applicazioni statistiche A tal fine, possiamo creare una funzione ad hoc, di nome ad esempio chi.sqr, che potrà assumere la forma: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 chi.sqr<-function(x,decimali=4,print.out=TRUE) { if (!is.matrix(x)){ stop("X ust be a matrix")} rig.tot<-apply(x, 1, sum) col.tot<-apply(x, 2, sum) tot<-sum(col.tot) Teor<- outer(rig.tot, col.tot, "*")/sum(x) Teor.out<-round(Teor,decimali) C<-round(x-Teor,decimali) Chi<-round(sum((x-Teor)^2/Teor),decimali) VCr<-round(Chi/(min(c(tot*(nrow(x)-1),tot*(ncol(x)-1)))),decimali) if (print.out) { cat("X =", Chi, "\n") cat("V =", VCr, "\n") } invisible(list(chi.sq=Chi,V=VCr,teorici=Teor.out,cont=C)) } A commento: — input della funzione è un oggetto con struttura di matrice; in caso contrario (riga [3] e [4]) viene visualizzato un messaggio di errore. Si noti il valore di default attribuito alla variabile logica print.out; — i comandi in riga [5], [6] e [7] si calcolano le somme di riga, di colonna nonché la somma totale; — il comando outer(rig.tot, col.tot, "*")/sum(x) calcola la matrice delle frequenze teoriche (Teor); — le righe [9] e [10] calcolano la matrice delle frequenze teoriche (Teor.out) e la matrice delle contingenze (C.out) che verranno inserite nella lista dei risultati in uscita; — le righe [11] e [12] si occupano del calcolo dei due indici richiesti; — in riga [13] il controllo if (print.out) consente di procedere alla visualizzazione (in riga [15] e [16]) dei risultati, a patto che print.out=TRUE; in riga [18] si crea, non visualizzandola, una lista che contiene i due indici richiesti, la matrice delle matrice delle frequenze teoriche e la matrice delle contingenze. Osservazione 3.2.2 Si noti che nella funzione chi.sqr proposta non si è fatto ricorso ad alcun ciclo di calcolo iterativo. Tornando al problema postoci, abbiamo: 93 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > > > X V > X V x.m<-taglio[,,sesso="Maschi"] x.f<-taglio[,,sesso="Femmine"] chi.sqr(x.m) = 25.2623 = 0.4858 chi.sqr(x.f) = 12.8407 = 0.2675 Desiderando visualizzare il contenuto della lista in uscita dalla funzione chi.sqr, è sufficiente digitare print(chi.sqr() o print(chi.sqr(...,print.out=FALSE))). Qualora si desideri estrarre alcuni risultati per successive elaborazioni si è obbligati ad assegnare l’output di chi.sqr ad una nuova variabile (di tipo list) e successivamente da questa estrarre gli oggetti di interesse; ad esempio: > contingenze.m<-chi.sqr(x.m,print.out=FALSE)$cont > contingenze.m posizione studio Operaio Impiegato Quadro L.Elem. 3.8846 -3.5 -0.3846 M.Sup. -1.1154 2.5 -1.3846 Dipl. -2.0769 2.0 0.0769 Laurea -0.6923 -1.0 1.6923 ♥ Esempio 3.2.4 L’archivio stat5.dat contiene il numero, espresso in migliaia di unità, degli occupati totali e suddivisi per sesso in Italia negli anni 1982 − 1990; come di consueto acquisiamo tali dati mediante le istruzioni: > esempio5<-read.table(file="stat5.txt") > names(esempio5) [1] "tempo" "maschi" "femmine" "mf" > attach(esempio5) Volendo in qualche modo evidenziare l’eventuale diversità della dinamica del fenomeno in esame, conviene ragionare, più che in valori assoluti, in termini di numeri indice a base fissa. A tal fine trasformiamo le serie maschi femmine e mf nelle corrsipondenti serie di numeri indice percentuali, ponendo quale base la situazione dell’anno iniziale, mediante i comandi: > ind.m<-(maschi/maschi[1])*100 > ind.f<-(femmine/femmine[1])*100 > ind.mf<-(mf/mf[1])*100 In figura (3.9) è evidenziato l’andamento delle tre serie sia in termini di valori assoluti sia in termini di numeri indici, in base al quale si nota una “esplosione” dell’occupazione femminile. Per inciso, che il numero degli occupati di sesso femminile è aumentato, nei nove anni considerati, del 12.7%, mentre quello dei maschi rimasto all’incirca costante; infatti: 94 E. D. Isaia, Linguaggio R e applicazioni statistiche (b) - Numeri indice (base 1982) 112 25000 (a) - Valori assoluti Femmine Maschi Entrambi 100 5000 102 104 10000 106 15000 108 20000 110 Femmine Maschi Entrambi 1982 1984 1986 1988 1990 1982 1984 anni 1986 1988 1990 anni Figura 3.9: Occupazione italiana nel periodo 1982-1990 — Esempio 3.2.4 > ind.f[length(ind.f)]-100 [1] 12.70693 > ind.m[length(ind.m)]-100 [1] -0.1288568 Procedendo, ci pare corretto adottare, per ciascuna serie di numeri indice, un modello interpolante del tipo ŷi = a0 + a1 ti , con i = 1, 2, . . . , n, dove, ricorrendo al metodo dei minimi quadrati: a1 = Cov(T, Y ) σT2 a0 = µY − a1 µT Possiamo, dunque, ricorrere3 ai comandi cov(x,y) e var(x): > n<-length(tempo) > a1<-cov(ind.m,tempo)*((n-1)/n)/var(tempo)*((n-1)/n) > a0<-mean(ind.m)-a1*mean(tempo) > a0 [1] 208.1988 > a1 [1] -0.05458331 3 Si rammenta che, come nel caso del calcolo della varianza (cfr Osservazione??), la covarianza tra due o più v.s. viene calcolata ponendo a denominatore n − 1 in luogo di n. 95 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 sı̀ che il modello interpolante a minimi quadrati risulta Maschi ŷi = 208.1988 − 0.0546 ti. Operando in modo analogo per le altre serie di numeri indici otteniamo: F emmine ŷi = −2771.763 + 1.4488 ti F emmine+Maschi ŷi = −740.4797 + 0.4240 ti I valori teorici in base ai modelli sono stati raccolti nel vettori modello.m, modello.f e modello.mf ottenuti mediante le semplici istruzioni: > > > > > > > > > a1<-cov(ind.m,tempo)*((n-1)/n)/var(tempo)*((n-1)/n) a0<-mean(ind.m)-a1*mean(tempo) modello.m<-a0+a1*tempo a1<-cov(ind.f,tempo)*((n-1)/n)/var(tempo)*((n-1)/n) a0<-mean(ind.f)-a1*mean(tempo) modello.f<-a0+a1*tempo a1<-cov(ind.mf,tempo)*((n-1)/n)/var(tempo)*((n-1)/n) a0<-mean(ind.mf)-a1*mean(tempo) modello.mf<-a0+a1*tempo Per completezza, in figura (3.10) è riportato l’andamento delle tre rette interpolanti. Osservazione 3.2.3 I passi necessari ai fini della costruzione del grafico proposto in figura (3.10) sono stati: — introduzione della variabile yrange che definisce il campo di variazione (a, b) dei valori in ordinata: > > > > a<-min(min(ind.f),min(ind.m),min(ind.mf)) b<-max(max(ind.f),max(ind.m),max(ind.mf)) yrange<-c(a,b) rm(a,b) — costruzione del grafico di base “vuoto” (opzione type="n") con suddivisione (opzione ylim=) dell’asse delle ordinate in accordo ai valori posti in yrange, munito di titolo (opzione main=) e etichette per l’asse delle ascisse (opzione xlab=) e quello delle ordinate (opzione ylab=): > plot(tempo,modello.m,,type="n",ylim=yrange, xlab="anni",ylab="",main="(b) - Numeri indice (base 1982)") — rappresentazione delle coppie di punti (Ŷ , t) con i comandi: > points(tempo,modello.m,col="red") > points(tempo,modello.f,col="black") > points(tempo,modello.mf,col="blue") 96 E. D. Isaia, Linguaggio R e applicazioni statistiche (b) - Numeri indice (base 1982) 100 102 104 106 108 110 112 Femmine Maschi Femmine+Maschi 1982 1984 1986 1988 1990 anni Figura 3.10: Occupazione italiana nel periodo 1982-1990 — Esempio 3.2.4 — rappresentazione delle tre rette interpolanti ricorrendo alla funzione lines(x,y); per migliorarne la leggibilità impieghiamo altrettanti tipi di tratteggio (opzione lty=). I comandi impartiti sono: > lines(tempo,modello.m,col="red",lty=3) > lines(tempo,modello.f,,col="black",lty=1) > lines(tempo,modello.mf,,col="blue",lty=5) — introduzione della variabile testo, contenente il testo della legenda, e visualizzazione della legenda stessa a partire dai punti di coordinate indicati in coord.leg: > coord.leg<-c(min(tempo),max(ind.f)) > testo<-c("Femmine","Maschi","Femmine+Maschi") > legend(coord.leg,legend=testo,col=seq(testo),lty = c(1,3,5)) È superfluo osservare che la maggior parte dei comandi presentati potrebbere essere inserita in una funzione ad hoc, sı̀ da automatizzare le procedure. ♥ 97 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Esempio 3.2.5 Con riferimento alle due variabili contenute in stat6.dat, che acquisiamo mediante i consueti comandi: > esempio6<-read.table(file="stat6.txt") > names(esempio6) [1] "mate" "stat" > attach(esempio6) può essere interessante evidenziare ed analizzare l’eventuale legame di dipendenza tra le v.s. Y =voto conseguito in Statistica e X =voto di ottenuto in Matematica. A tal fine, iniziamo con la presentazione della distribuzione congiunta delle v.s. in esame, che, come di consueto, otteniamo ricorrendo al comando table(); pertanto: > table(mate,stat) stat mate 18 19 20 21 22 23 25 26 27 29 30 18 2 0 1 0 0 0 0 0 0 0 0 19 0 0 1 1 0 1 0 0 0 0 0 20 0 1 3 0 0 1 0 0 0 0 0 21 0 0 0 1 1 1 0 0 0 0 0 23 0 0 1 1 0 1 2 0 0 0 0 25 0 0 1 0 0 0 2 0 1 0 0 26 0 0 0 0 0 0 1 0 4 0 0 27 0 0 0 0 0 0 0 1 3 0 1 28 0 0 0 0 0 0 0 0 1 1 1 30 0 0 0 0 0 0 0 0 0 1 3 È sufficiente una rapida lettura della tabella per accorgersi di una dipendenza (in senso statistico) tra le variabili oggetto di studio. A tal proposito4 : > chi.sqr(table(mate,stat)) X = 129.637 V = 0.3601 Anzi, la circostanza che buona parte delle frequenze osservate giaccia sulla diagonale principale può indurci a ritenere il legame di dipendenza positivo e di tipo, approssimativamente, lineare. Per sincerarsene, possiamo costruire un semplice diagramma a dispersione tra le variabili originarie mate e stat oppure ricorrere ad un diagramma a dispersione dei voti medi di Statistica condizionati a ciascun voto riportato in Matematica. Prima di presentare i risultati, occupiamoci del calcolo delle medie della v.s. condizionata Y |X, in simboli µY |X=xi . A tale scopo, ricorriamo alla ormai nota funzione split() e successivamente al nuovo comando5 sapply(). In particolare: 4 Si tratta dell funzione presentata all’Esempio 3.2.3. Il cui comportamento è simile a quello dei comandi apply() e tapply(). Argomenti sonol’oggetto su cui operare e la funzione che si desidera applicare. 5 98 E. D. Isaia, Linguaggio R e applicazioni statistiche — definiamo l’oggetto stat.m che conterrà, sottoforma di lista, i voti di Statistica in corrispondenza a ciascuna modalità (o livello) del voto di Matematica; #& #% ## !" #$ ,()*+,10-+,-+,3*/*+4*+2/ #" '$ — calcoliamo le medie di ciascun oggetto contenuto in stat.m, cioè le medie condizionate µY |X=xi , con il comando sapply(stat.m,mean); i risultati, utili per successive elaborazioni, verranno inseriti nel nuovo oggetto medie.cond. !" #$ ## #% #& #" '$ ()*+,-+,./*01/*+2/ Figura 3.11: Medie condizionate e spezzata di regressione — Esempio 3.2.5 Ciò premesso, le istruzioni6 : > stat.m<-split(stat, mate) > media.cond<-round(sapply(stat.m, mean),4) In definitiva le medie condizionate µY |X=xi , espresse a solo due decimali, risultano: > round(media.cond,2) 18 19 20 21 23 25 26 27 28 30 18.67 21.33 20.40 22.00 22.80 24.25 26.60 27.40 28.67 29.75 A questo punto possiamo procedere alla costruzione di un diagramma a dispersione dove rappresenteremo le coppie (xi , µY |X=xi ); le istruzioni: 6 Sarebbe sufficiente la sola istruzione: medie.cond<-sapply(split(stat, mate), mean). 99 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > plot(unique(sort(mate)),media.cond,type="p",cex=2.5,pch=20,col="red", frame.plot=FALSE,ann=FALSE,cex.main=1,font.main=1,ylim=c(18,30)) > lines(unique(sort(mate)),media.cond,col="blue") > title(main="",xlab="Voti di Matematica",ylab=" Voti medi di Statistica") porgono il grafico riportato in figura (3.11). A questo punto, evidenziata l’esistenza, perlomeno graficamente, di un legame lineare tra le variabili considerate possiamo “quantizzarla”. Innanzitutto possiamo procedere al calcolo del coeficiente di correlazione lineare del Pearson (ρ) che “a occhio” dovrà risultare prossimo all’unità7 ; infatti abbiamo: #& #% ## !" #$ ,()*+,10-+,-+,3*/*+4*+2/ #" '$ > (rho<-cor(stat,mate)) [1] 0.9052952 !" #$ ## #% #& #" '$ ()*+,-+,./*01/*+2/ Figura 3.12: Retta di regressione — Esempio 3.2.5 7 Nel caso di adozione di un modello lineare esso viene a coincidere, com’è noto, con il coefficiente di determinazione. 100 E. D. Isaia, Linguaggio R e applicazioni statistiche Inoltre possiamo individuare i parametri della retta di regressione yi = a0 + a1 xi . Ricordando che: a1 = σY Cov(X, Y ) =ρ 2 σX σX a0 = µY − a1 µX le istruzioni: > a1<-rho*sqrt(var(stat))/sqrt(var(mate)) > a0<-mean(stat)-a1*mean(mate) > modello<-a0+a1*mate porgono: > a1 [1] 0.9078971 > a0 [1] 2.605864 sı̀ che la retta di regressione viene ad assumere la forma yi = 2.6059 + 0.9079 xi , il cui andamento è riportato in figura (3.12), ottenuto mediante le istruzioni: > plot(unique(sort(mate)),media.cond,type="p",cex=2.5,pch=20,col="red", frame.plot=FALSE,ann=FALSE,cex.main=1,font.main=1,ylim=c(18,30)) lines(mate,modello,col="blue") ♥ Esempio 3.2.6 Si immagini di avere rilevato, su gruppo di n = 10 autovetture europee medio-piccole ad alimentazione a benzina, la cilindrata (x1 ), la potenza espressa in CV-Din (x2 ), la velocità massima dichiarata (x3 ) ed il consumo di carburante (x4 ), ottenendo i risultati che seguono: x1 x2 x3 x4 1100 45 135 5 1200 54 145 5.5 1000 45 140 4.8 1300 50 140 6.2 1400 60 150 6.7 1000 45 140 5 1100 50 140 4.8 1200 54 145 5.2 1400 70 165 6.7 1250 60 155 6.2 Definito8 il data frame auto, contenente tutte le informazioni: > > > > x1<-cbind(c(11, 12, 10, 13, 14, 10, 11, 12, 14, 12)*100) x2<-cbind(c(45, 54, 45, 50, 60, 45, 50, 54, 70, 60)) x3<-cbind(c(135, 145, 140, 140, 150, 140, 140, 145, 165, 155)) x4<-cbind(c(5, 5.5, 4.8, 6.2, 6.7, 5, 4.8, 5.2, 6.7, 6.2)) 8 Meno elegantemente avremmo potuto definire la matrice X<-cbind(x1,x2,x3,x4) ed operare su di essa attribuendo nomi appropriati ai suoi vettori colonna. 101 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > (auto<-data.frame(Cilindrata=x1,CV.Din=x2,Vel.max=x3,Consumo=x4)) Cilindrata CV.Din Vel.max Consumo 1 1100 45 135 5.0 2 1200 54 145 5.5 3 1000 45 140 4.8 4 1300 50 140 6.2 5 1400 60 150 6.7 6 1000 45 140 5.0 7 1100 50 140 4.8 8 1200 54 145 5.2 9 1400 70 165 6.7 10 1200 60 155 6.2 calcoliamo la matrice dei coefficienti di correlazione lineare tramite il semplice comando 9 : > round(cor(auto),4) Cilindrata Cilindrata 1.0000 CV.Din 0.8305 Vel.max 0.6889 Consumo 0.9194 CV.Din Vel.max Consumo 0.8305 0.6889 0.9194 1.0000 0.9637 0.8282 0.9637 1.0000 0.7661 0.8282 0.7661 1.0000 Per avere un’idea “globale” delle relazioni tra le variabili conteute in auto, possiamo pensare di creare i diagrammi a dispersione tra tutte le 42 − 4 = 12 combinazioni delle variabili oggetto di studio. Ciò può essere attuato ricorrendo alla funzione pairs(). Tuttavia desiderando migliorare la situazione di default, scegliamo di: — rappresentare sulla diagonale principale gli istogrammi delle variabili x1,x2,x3 e x4; a tal fine ricorriamo alla funzione panel.hist presentata in 2.1.12; — visualizzare, nelle celle a destra della diagonale principale, i diversi coefficienti di correlazione lineare; a tal fine consideriamo la nuova funzione: panel.cor <- function(x, y, digits=2,pch=20) { par(usr = c(0, 1, 0, 1)) r <- cor(x, y) txt <- paste(format(r, digits=digits),sep="") text(0.5, 0.5, txt, cex = 2) } A questo punto il comando: > pairs(auto,pch = 20,diag.panel=panel.hist,upper.panel=panel.cor) 9 Si osservi che stiamo operando sull’intero data frame e non sui suoi singoli componenti, per il momento non disponibili (cfr. paragrafo 1.4.2). 102 E. D. Isaia, Linguaggio R e applicazioni statistiche 5.0 5.5 6.0 6.5 Cilindrata 0.69 0.92 0.96 0.83 1000 0.83 1200 1400 45 50 55 60 65 70 6.5 135 0.77 145 Vel. max. 155 165 45 55 65 CV-Din 5.0 5.5 6.0 Consumo 1000 1200 1400 135 145 155 165 Figura 3.13: Matrice dei diagrammi a dispersione — Esempio 3.2.6 porge il grafico riportato in figura (3.13). Lasciamo al Lettore la verifica sul campo del comando: > pairs(auto,pch = 20,diag.panel=panel.hist,lower.panel=panel.cor) ♥ Esempio 3.2.7 A volte capita, nel caso di analisi di una variabile statistica doppia, di disporre non già dei singoli dati individuali, bensı̀ degli stessi raccolti in distribuzione congiunta di frequenze. In tali situazioni è sempre possibile procedere ad analisi statistiche dei dati in R, purché questi vengano acquisiti in modo corretto. Distinguiamo i casi: — abbiamo a disposizione una tabella a doppia entrata per due caratteri qualitativi, ad esempio: 103 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 m.s. B → m.s. A ↓ a1 a2 a3 b1 b2 200 400 100 150 100 250 I dati potranno essere correttamente acquisiti in R tramite le istruzioni: > ms.AB<-array(c(200,400,100,150,100,250),dim=c(3,2)) > dimnames(ms.AB)<-list(A = c("a1", "a2", "a3"),B = c("b1", "b2")) infatti: > ms.AB B A b1 b2 a1 200 150 a2 400 100 a3 100 250 — abbiamo a disposizione una tabella a doppia entrata per due caratteri quantitativi, ad esempio: v.s. Y → v.s. X ↓ 0 1 0 1 10 30 20 10 I dati potranno essere correttamente acuisiti in R tramite le istruzioni: > vs.XY<-array(c(10,30,20,10),dim=c(2,2)) > vs.XY > vs.XY Y X 0 1 0 10 20 1 30 10 e, per ulteriori elaborazioni: > XY<-array(c(0,0,1,1,0,1,0,1,10,20,30,10),dim=c(4,3)) > XY [,1] [,2] [,3] [1,] 0 0 10 [2,] 0 1 20 [3,] 1 0 30 [4,] 1 1 10 104 E. D. Isaia, Linguaggio R e applicazioni statistiche ♥ Esempio 3.2.8 Se un oggetto contiene valori mancanti (NA) l’applicazione delle funzioni statistiche standard elencate, ad esempio, in (3.1.3) comporta alcuni problemi poiché essi, per default, vengono conteggiati in length(oggetto). In effetti le funzioni in questione tengono conto della possiblità di escludere i valori mancanti; ad esempio la funzione mean è definita: 1 2 3 4 5 6 mean<-function (x,na.rm = FALSE) { if(na.rm) {x <- x[!is.na(x)]} else if(any(is.na(x))) {return(NA)} sum(x)/length(x) } sicché è sufficiente modificare la situazione di default na.rm = FALSE in na.rm = TRUE. Ad esempio: > x<-c(NA,12,NA,14,15,17,21) > x [1] NA 12 NA 14 15 17 21 > mean(x) [1] NA > mean(x,na.rm=TRUE) [1] 15.8 Nel seguito proponiamo due semplici alternative che a nostro avviso consentono un maggior controllo dei valori mancanti. Le funzioni off.na(x) e rep.na(x) consentono di modificare un oggetto che presenta elementi mancanti (NA). La prima funzione si limita ad eliminarli, mentre la seconda sostituisce tali valori con il valor medio o, a discrezione dell’utente, con la mediana di x. Per comodità i nuovi valori in uscita sono messi negli oggetti w.off e w.rep rispettivamente. I listati delle due funzioni sono: 1 2 3 4 5 off.na<-function(x) { w.off<<-x[!is.na(x)] cat("The new w.off object has been created","\n") } Cosı̀ ad esempio: > x<-c(NA,12,NA,14,15,17,21) > x [1] NA 12 NA 14 15 17 21 > off.na(x) The new w.off object has been created 105 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > w.off [1] 12 14 15 17 21 > mean(w.off) [1] 15.8 1 2 3 4 5 6 7 8 9 10 11 rep.na<-function(x, media=TRUE) { if (!media){valore<-median(x[!is.na(x)])} else {valore<-mean(x[!is.na(x)])} for (i in (1:length(x))) { if (is.na(x[i])==TRUE) {x[i]<-valore} } w.rep<<-x cat("The new w.rep object has been created","\n") } > rep.na(x) The new w.rep object has been created > w.rep [1] 15.8 12.0 15.8 14.0 15.0 17.0 21.0 > rep.na(x,media=FALSE) The new w.rep object has been created > w.rep [1] 15 12 15 14 15 17 21 ♥ 106 Capitolo 4 Elementi di calcolo delle probabilità In ambiente R sono implementate le principali distribuzioni di probabilità univariate. Esse sono identificate da un nome proprio che deve obbligatoriamente essere preceduto da un suffisso che indica quale aspetto di esse si desidera, ed infine dalla lista dei parametri che contraddistinguono ciascuna v.c.. Quanto ai suffissi, comuni a tutte le v.c.: — d porge i valori della densità in corrispondenza ai valori specificati in x; — p porge i valori della funzione di ripartizione in corrispondenza ai valori indicati in x; — q porge i valori dei quantili in corrispondenza ai valori elencati in prob; — r estrae casualmente noss elementi dalla densità specificata; Quanto alle distribuzioni di probabilità implementate, citiamo: ! binomiale f (x) = 2 n x 3 px (1 − p)n−x dbinom(x,n, p) qbinom(prob, n, p) pbinom(x, n, p) rbinom(noss, n, p) ! binomiale negativa f (x) = 2 x+r−1 x dnbinom(x, r, p) qnbinom(prob, r, p) 3 pr (1 − p)x pnbinom(x, r, p) rnbinom(noss, r, p) Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 ! geometrica f (x) = p(1 − p)x dgeom(x, p) qgeom(prob, p) pgeom(x, p) rgeom(noss, p) ! ipergeometrica f (x) = 2 32 N1 N2 x n−x 2 3 N1 + N2 n dhyper(x, N1, N2) qhyper(prob, N1, N2) 3 phyper(x, N1, N2) rhyper(noss, N1, N2) ! di Poisson f (x) = λx e−λ x! dpois(x, lambda) qpois(prob, lambda) ppois(x, lambda) rpois(noss, lambda) ! Chi-Quadro f (x) = 1 2 n/2 dchisq(x, df) qchisq(prob, df) Γ (n/2) xn/2−1 e−x/2 pchisq(x, df) rchisq(noss, df) ! esponenziale f (x) = λe−λx dexp(x, rate) qexp(prob, rate) pexp(x, rate) rexp(noss, rate) ! F di Snedecor f (x) = Γ (n1 /2 + n2 /2) n1 n1 n1 /2−1 n1 x −(n1 +n2 )/2 ( )2x (1 + ) Γ (n1 /2) Γ (n2 /2) n2 n2 df(x, n1, n2) qf(prob, n1, n2) pf(x, n1, n2) rf(noss, n1, n2) 108 E. D. Isaia, Linguaggio R e applicazioni statistiche ! gamma f (x) = 1 xa−1 e−x/b b Γ (a) a dgamma(x, shape, scale) qgamma(prob, shape, scale) pgamma(x, shape, scale) rgamma(noss, shape, scale) ! normale 1 2 f (x) = √ e−(x−µ)/2σ σ 2π dnorm(x, mean, sd) qnorm(prob, mean, sd) pnorm(x, mean, sd) rnorm(noss, mean, sd) ! t di Student f (x) = dt(x, df) qt(prob, df) 5 6−(n+1)/2 Γ (n + 1/2) 4 √ 1 + x2 2 Γ (n/2) nπ pt(x, df) rlt(noss, df) ! uniforme f (x) = 1 max − min dunif(x, min, max) qunif(prob, min, max) punif(x, min, max) runif(noss, min, max) Osservazione 4.0.4 La v.c. Chi-Quadro precedentemente introdotta non è altro che un particolare caso della distribuzione Chi-Quadro non centrale. Questa rappresenta la distribuzione della somma dei quadrati di n v.c. indipendenti e normalmente distribuite ciascuna con varianza unitaria e valor medio µ i , i = 1, 2, . . . , n. La densità di una v.c. Chi-Quadro non centrale con ν gradi di libertà e parametro di non ( centralità λ = ni=1 µ2 , per x ≥ 0, è: fnc (x) = e(−λ/2) +∞ ! (λ/2)r f (x; ν + 2 r) r! r=0 dove f (x) indica la densità di una v.c. Chi-Quadro con ν + 2 r gradi di libertà. Per una v.c. Chi-Quadro con parametro di non centralità λ =ncp, si ha: 109 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 dchisq(x, df, ncp=0) qchisq(prob, df, ncp=0) pchisq(x, df, ncp=0) rchisq(noss, df, ncp=0) A tal proposito, osserviamo ancora la possibilità di calcolare particolari valori di interesse della funzione di ripartizione delle distribuzioni F di Snedecor e t di Student con parametro di non centralità ncp tramite i comandi pf(t, df =,ncp=) e pt(t, df =, ncp=) 4.1 Semplici esercizi sul calcolo delle probabilità Nel seguito i limitiamo a fornire alcuni semplici esempi applicativi che coinvolgono in modo diretto le v.c. introdotte al paragrafo precedente. Esempio 4.1.1 Visualizzare la funzione di distribuzione di probabilità e la funzione di ripartizione di una v.c. binomiale di parametri n = 9, p = 0.5; le istruzioni possono essere: > > > > x<-c(0:9) par(mfrow=c(1, 2)) plot(x,pbinom(x,9,.5),col="red",type="s",ann=FALSE) title(main="(a) - Funzione di ripartizione", xlab="Determinazioni x",ylab="P(Xx)") > plot(x,dbinom(x,9,.5),col="blue",type="h",ann=FALSE) > title(main="(b) - Distribuzione di probabilita’", xlab="Determinazioni x",ylab="P(X=x)") > par(mfrow=c(1, 1)) il cui output è riprodotto in figura (4.1). ♥ Esempio 4.1.2 Ci proponiamo di visualizzare la funzione di ripartizione di una v.c. con distribuzione binomiale di parametri n = 9 e p = 0.10, 0.25, 0.50, 0.75, 0.90; le istruzioni possono essere: > > > > > > > > > x<-c(0:9) plot(x,pbinom(x,9,.5),xlim=c(-1,10),type="n",ann=FALSE) title(main="",xlab="Numero di prove",ylab="P[X x]") for(p in c(0.10,0.25,0.50,0.75,0.90)) {lines(x,pbinom(x,9,p),col=p*10,type="s")} text(0.65,0.80,"p=0.10",cex=.75) text(1.70,0.65,"p=0.25",cex=.75) text(3.25,0.30,"p=0.50",cex=.75) text(5.25,0.20,"p=0.75",cex=.75) text(6.20,0.10,"p=0.90",cex=.75) il cui output è riprodotto in figura (4.2). 110 E. D. Isaia, Linguaggio R e applicazioni statistiche (b) - Distribuzione di probabilita' 0.15 0.05 0.10 P(X=x) 0.6 0.4 0.0 0.00 0.2 P(X!x) 0.8 0.20 1.0 0.25 (a) - Funzione di ripartizione 0 2 4 6 8 0 Determinazioni x 2 4 6 8 Determinazioni x Figura 4.1: Distribuzione binomiale, n=9 e p=0.5 — Esempio 4.1.1 Esempio 4.1.3 Calcolare la probabilità all’evento {5 ≤ X ≤ 7}, posto che X sia una v.c. binomiale con parametri n = 10, p = 0.75; le istruzioni possono essere: > pbinom(7,10,.75)-pbinom(5,10,.75) [1] 0.3962803 Tutto ciò è piuttosto ripetitivo; la seguente funzione, in base ai parametri essenziali, porge la soluzione desiderata: 1 > evento<-function(x1,x2,n,p){print(pbinom(x2,n,p)-pbinom(x1,n,p))} A questo punto l’istruzione evento(5,7,10,.75) restutuisce il risultato desiderato. ♥ Esempio 4.1.4 Calcolare i percentili di ordine 5, 15, ..., 85, 95 di una distribuzione ChiQuadro con 10 gradi di libertà. A tal fine è sufficiente impartire l’istruzione: > qchisq(ppoints(10), 10) [1] 3.940299 5.570059 6.737201 7.783243 8.812352 [6] 9.892216 11.097142 12.548861 14.533936 18.307038 111 p=0.10 0.6 p=0.25 0.4 P[X ! x] 0.8 1.0 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 0.2 p=0.50 p=0.75 0.0 p=0.90 0 2 4 6 8 10 Numero di prove ♥ Figura 4.2: Funzioni di ripartizione di v.c. Bin(n = 9, p) — Esempio 4.1.2 ♥ 2 Esempio 4.1.5 Posto X una v.c. N (µX = 120, σX = 25), calcolare la probabilità attinente agli eventi {X ≥ (µX − σX )} e {(µX − σX ) ≤ X ≤ (µX + σX )}. Sono sufficienti le istruzioni: > mu<-120 : s<-5 > 1-pnorm(115,mu,s) [1] 0.8413447 > pnorm(125,mu,s)-pnorm(115,mu,s) [1] 0.6826895 ♥ Esempio 4.1.6 Posto X una v.c. N (0, 1), calcolare la probabilità attinente all’evento {X ≥ x}, con x = 0, 3, (0.05). Si tratta di calcolare le probabilità della coda destra di una N (0, 1) in corrispondenza a determinati quantili; il problema viene risolto mediante le istruzioni: 112 E. D. Isaia, Linguaggio R e applicazioni statistiche > x<-seq(0,3,by=0.05) > n.prob.coda.dx<-1-pnorm(x,0,1) > round(n.prob.coda.dx,4) [1] 0.5000 0.4801 0.4602 0.4404 [10] 0.3264 0.3085 0.2912 0.2743 [19] 0.1841 0.1711 0.1587 0.1469 [28] 0.0885 0.0808 0.0735 0.0668 [37] 0.0359 0.0322 0.0287 0.0256 [46] 0.0122 0.0107 0.0094 0.0082 [55] 0.0035 0.0030 0.0026 0.0022 0.4207 0.2578 0.1357 0.0606 0.0228 0.0071 0.0019 0.4013 0.2420 0.1251 0.0548 0.0202 0.0062 0.0016 0.3821 0.2266 0.1151 0.0495 0.0179 0.0054 0.0013 0.3632 0.2119 0.1056 0.0446 0.0158 0.0047 0.3446 0.1977 0.0968 0.0401 0.0139 0.0040 Si osservi che coerentemente: > (n.quantili<-(qnorm(1-n.prob.coda.dx,0,1))) [1] 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 [14] 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 [27] 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 [40] 1.95 2.00 2.05 2.10 2.15 2.20 2.25 2.30 2.35 [53] 2.60 2.65 2.70 2.75 2.80 2.85 2.90 2.95 3.00 0.45 1.10 1.75 2.40 0.50 1.15 1.80 2.45 0.55 1.20 1.85 2.50 0.60 1.25 1.90 2.55 ♥ Esempio 4.1.7 Per una v.c. N (0, 1) si ha P [X > 1.959964 = x∗ ] = 0.025. Ci proponiamo di calcolare il corrispondente quantile x∗ per una v.c. con distribuzione t di Student con gdl = 5, 200, (5) gradi di libertà. Rsiolviamo il problema ricorrendo alle istruzioni: > > > > prob<-0.025 gdl<-seq(5,200,by=5) quantile.t<-qt(1-prob,gdl) round(quantile.t,4) [1] 2.5706 2.2281 2.1314 2.0860 [10] 2.0086 2.0040 2.0003 1.9971 [19] 1.9853 1.9840 1.9828 1.9818 [28] 1.9771 1.9765 1.9759 1.9754 [37] 1.9729 1.9725 1.9722 1.9719 2.0595 1.9944 1.9808 1.9749 2.0423 1.9921 1.9799 1.9744 2.0301 1.9901 1.9791 1.9740 2.0211 1.9883 1.9784 1.9736 2.0141 1.9867 1.9777 1.9732 ♥ Esempio 4.1.8 Data una v.c. Gamma(10, 5), il quantile di ordine, poniamo, 0.67 viene ottenuto in modo diretto tramite il comando qgamma(0.67,10,5). Un’alternativa è rappresentata dal ricorso (cfr. paragrafo ??) alla funzione uniroot(); infatti: > uniroot(function(x) pgamma(x ,10, 5) - 0.67, c(0, 100))$root [1] 55.48862 > qgamma(0.67 ,10, 5) [1] 55.48862 ♥ 113 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 4.2 Generazione di numeri pseudo-casuali La generazione di realizzazioni di variabili casuali 1 ha diverse motivazioni, ad esempio in ambito statistico può essere utilizzata al fine della verifica di modelli teorici o dell’applicazione di metodi di simulazione quali Monte Carlo ed analoghi. Le v.c. possono essere generate a partire da numeri casuali o, meglio, dovremmo dire numeri pseudo-casuali dal momento che la loro generazione avviene in accordo a specifici algoritmi numerici. La generazione di un numero casuale può essere intesa come la generazione di un’osservazione da una v.c. con distribuzione uniforme in (0, 1). Dal momento che la funzione di ripartizione F (·) di qualsiasi v.c. X assume valori in (0, 1), se generiamo un numero, sia esso w, tra 0 e 1, esisterà smpre un valore x tale che x = F −1 (w), ovvero tale che w = F (x). In generale è assai complesso individuare l’inversa di F (·). A titolo di esempio, si immagini di voler generare una v.c. distribuzione Bernoulliana di parametro p, ovvero: X= + 0 1−p 1 p con funzione di ripartizione: F (x) = 0 x<0 1 0≤x<1 1 x≥1 Iniziamo generando un numero w da una v.c. uniforme in (0, 1); se w < 1−p possiamo definire F −1 (w) = 0, mentre se w ≥ 1 − p definiamo F −1 (w) = 1. In altri termini, per generare una v.c. di Bernoulli di parametro p è sufficiente generare un numero compreso tra 0 e 1 e se risulta più piccolo di 1 − p diciamo che X = 0 altrimenti 1. Dal momento che la condizione w < 1− p è equivalente, in probabilità, alla condizione w > p, diremo che X = 0 se w > p. Esempio 4.2.1 Generazione di 5 realizzazioni di una v.c. con distribuzione Bernoulliana di parametro p = 0.25. Estraiamo dapprima cinque numeri da un’uniforme in (0, 1) e verifichiamo se sono minori di p: > (w<-runif(5)) [1] 0.29534834 0.21283447 0.26371730 0.93382201 0.07352568 > (esito<-(w<.25) [1] FALSE TRUE FALSE FALSE TRUE Trasformiamo, ora, gli elementi del vettore logico esito in un vettore numerico binario: 1 Alternativamente: generazione di numeri casuali 114 E. D. Isaia, Linguaggio R e applicazioni statistiche > (binario<-1*esito) [1] 0 1 0 0 1 ♥ Come già si disse in (4), in R sono implementate funzioni basate su algoritmi ottimizzati per la generazione di numeri pseudo-cauali. A commento valgano gli esempi che seguono. 2 Esempio 4.2.2 Generazione di n = 10 numeri casuali tratti da una N (µX = 200, σX = 225): > rnorm(10,200,(225)^.5) [1] 210.0311 198.6509 216.4558 203.8878 199.0929 190.8120 199.3914 [8] 188.4484 201.6433 203.5893 ♥ Esempio 4.2.3 Desiderando verificare, perlomeno graficamente, se n osservazioni campionarie possono considerarsi tratte da una distribuzione normale si può ricorrere ad un diagramma a dispersione avendo cura di porre in ascissa i quantili di una N (µ, σ) ed in ordinata i quantili campionari (o empirici) calcolati sulla base della n-pla osservata. Tenendo a mente quanto detto a tal proposito al paragrafo 2.1.5, ciò può essere ottenuto ricorrendo al comando qqplot(x,y), dove x contiene le osservazioni campionarie e y è definito come qnorm(ppoints(length(x)),mean(x),sd(x)), oppure tramite il comando qqnorm(x). A titolo di esempio la figura (4.3) riporta i diagrammi a dispersione dei quantili di sei campioni tratti da una N (120, 20) di numerosità n = 25, (25), 150, in accordo alle seguenti istruzioni: > par(mfrow=c(2,3)) > for(n in c(25,50,75,100,125,150)) { .Random.seed<-c(1,2037680562,1033614556) qqnorm(rnorm(n),main=paste("n=",n),xlab="Quantili teorici N(0,1)", ylab=" Quantili campionari",pch=20,col=1+n) } > par(mfrow=c(1,1)) Si noti la presenza del comando .Random.seed<-c(1,2037680562,1033614556) che consente di rigenerare una stessa sequenza di numeri casuali; a tal proposito valga l’Osservazione 4.2.1. ♥ Esempio 4.2.4 La generazione di n = 1000 numeri casuali da una v.c. con distribuzione Chi-quadro con gdl = 12 gradi di libertà può avvenire tramite il semplice comando: > valori.chi<-rchisq(1000,12) 115 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 n= 50 n= 75 1 0 Quantili campionari -1 0 -1 Quantili campionari 1 0 0 1 2 -2 -1 0 1 2 -2 Quantili teorici N(0,1) n= 125 1 2 2 1 Quantili campionari 1 0 -2 -2 -2 -1 Quantili campionari 2 1 0 Quantili campionari -1 0 n= 150 2 n= 100 -1 Quantili teorici N(0,1) 0 -1 Quantili teorici N(0,1) -1 -2 -2 -2 -1 Quantili campionari 1 2 2 n= 25 -2 -1 0 1 Quantili teorici N(0,1) 2 -2 -1 0 1 Quantili teorici N(0,1) 2 -2 -1 0 1 2 Quantili teorici N(0,1) Figura 4.3: Campionamento da una v.c. N(0, 1): QQ-plot — Esempio 4.2.3 In figura (4.4) è riportato l’istogramma della variabile valori.chi generata nonché il diagramma a dispersione tra i quantili empirici e quelli teorici di una distribuzione N (0, 1); i grafici proposti sono stati generati dalle istruzioni: > hist(valori.chi,main="",xlab="x",ylab="Frequenze assolute", col="lightgreen") > qqnorm(valori.chi,main="",xlab="Quantili teorici N(0,1)", ylab=" Quantili campionari",pch=20,col="magenta") Lasciamo al Lettore l’interpretazione, in termini grafici, dei risultati ottenuti. ♥ Osservazione 4.2.1 A volte può tornare utile rigenerare una stessa sequenza di numeri casuali. A tal fine occerre conoscere e reimmettere il seme che ha generato la prima sequenza e che è immaganizzato nella variabile .Random.seed. Un modo per risolvere il problema è il ricorso alle seguenti istruzioni: > rbinom(5,4,.36) [1] 1 1 0 1 1 116 25 20 15 0 5 10 Quantili campionari 300 200 100 Frequenze assolute 30 E. D. Isaia, Linguaggio R e applicazioni statistiche 0 5 10 20 30 -3 x -2 -1 0 1 2 3 Quantili teorici N(0,1) Figura 4.4: Istogramma e QQ-plot — Esempio 4.2.3 > seme<-.Random.seed > seme [1] 1 14739194 782820522 > .Random.seed<-seme > rbinom(5,4,.36) [1] 1 1 0 1 1 Per approfondimenti, si vedano gli articoli di Marsaglia (1997) e Wichmann, Hill (1982) e la bibliografia ivi citata. 4.3 Il campionamento In R è definita una particolare funzione che consente l’estrazione di un campione casuale, di dimensione specificata, da un dato oggetto; tale estrazione può avvenire con o senza rimessa a seconda delle esigenze dell’utente. La sintassi estesa del comando necessario per accedere a tale funzione è: sample(oggetto,n,replace=FALSE) dove: 117 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — l’oggetto specificato può avere modalità numerica o alfanumerica indifferentemente; — n indica la dimensione del campione che si desidera estrarre. Si ricordi che per default si ha n=length(oggetto); — replace=FALSE indica che l’estrazione avviene senza rimessa; tale è la situazione di default. Esempio 4.3.1 Estrazione senza rimessa di un campione casuale di dimensione n = 5 dalle 26 lettere dell’alfabeto anglosassone. Il probbema è risolto con: > sample(letters,5) [1] "a" "m" "t" "g" "u" ♥ Esempio 4.3.2 Estrazione senza rimessa di 4 campioni casuali di dimensione ni = 1, . . . , 4, con i = 1, . . . , 4, dalle 26 lettere dell’alfabeto anglosassone. Ricorrendo ad un ciclo retto da for, abbiamo: > for(n [1] "m" [1] "b" [1] "e" [1] "d" in 1:4){print(sample(letters,n))} "c" "o" "c" "y" "g" "m" ♥ Esempio 4.3.3 Campionamento con rimessa da un oggetto con modalità alfanumerica: a<-LETTERS[1:7] for(i in 1:4){print(sample(a,4,replace=TRUE))} il cui risultato potrebbe essere: [1] [1] [1] [1] "C" "C" "G" "E" "F" "E" "G" "E" "D" "C" "A" "G" "G" "D" "F" "G" Osservazione 4.3.1 Ricorrendo all’istruzione: for(i in 1:4); print(sample(a,replace=TRUE)) si ottengono quattro permutazioni degli elementi di a; ad esempio le seguenti: 118 E. D. Isaia, Linguaggio R e applicazioni statistiche [1] [1] [1] [1] "D" "F" "D" "E" "B" "D" "A" "G" "E" "E" "B" "C" "A" "G" "G" "D" "G" "C" "G" "C" "C" "A" "F" "D" "F" "B" "D" "F" ♥ Esempio 4.3.4 Estrazione senza rimessa di 4 campioni di 5 elementi ciascuno, da una v.c. N (10, 2). > for(i in 1:4){print(sample(rnorm(1000,10,2),5))} [1] 7.500336 11.596424 11.279172 10.808307 9.332722 [1] 11.683638 11.538254 9.494141 8.657761 8.943494 [1] 8.721086 11.026309 6.303418 8.370027 11.259078 [1] 8.636034 9.080102 12.447917 11.931348 7.070856 Esempio 4.3.5 Simulazione del lancio di una moneta ripetuto 10000 volte. Eseguiamo un’estrazione con rimessa, che ripetiamo 10000 volte, da un oggetto che contiene i valori 0 e 1. A tal fine è sufficiente l’istruzione: > sample(c(0,1),10000,replace=TRUE) > ## non mandare in esecuzione!! Meglio potremmo fare riassumendo i risultati in una tabella di frequenza, ad esempio mediante le istruzioni: > lancio<-table(sample(c(0,1), 10000, replace = TRUE)) > dimnames(lancio)<-list(Lancio=c("Testa","Croce")) > lancio Lancio Testa Croce 4973 5027 Manifestamente resta aperto il problema della bontà della simulazione, ma su tale argomento torneremo nel seguito. ♥ 119 Capitolo 5 Elementi di statistica inferenziale Nel seguito ci occuperemo del problema della costruzione di intervalli di confidenza e della verifica di ipotesi statsitiche, perlomeno in situazioni, per cosı̀ dire, classiche. In particolare vedremo come sia possibile e parimenti facile costruire funzioni ad hoc e, al contempo, come si possano sfruttare funzioni già implementate e piuttosto sofisticate, presenti nella libreria ctest. Ricordiamo1 che la stima puntuale dei parametri θ = (θ 1 , θ2 , . . . , θk ) ∈ Θ ⊆ IRk , che caratterizzano la densità f X (x; θ) della una v.c. X, che descrive un fenomeno aleatorio oggetto di indagine, avviene ricorrendo ad una opportuna funzione applicata sulle n ≥ 2 v.c. X1 , X2 , . . . , Xn indipendenti e identicamente distribuite (i.i.d.) come X. La funzione T = t(X1 , X2 , . . . , Xn ) = t(X), abitualmente detta stimatore ed individuata in genere in accordo a particolari criteri, ad esempio quello della massimaverosomiglianza o quello dei momenti, è a sua volta una v.c. con densità f T (τ ) e " # tale che2 IE[T ] = θ e IE (T − IE[T ])2 = V ar[T ] ↓ 0, per n ↑ ∞. 5.1 Intervalli di confidenza per un parametro θ Dato il campione casuale X = (X1 , X2 , . . . , Xn ) con densità fX (x, θ), dove θ è un parametro unidimensionale e date le due statistiche T 1 = t1 (X1 , X2 , . . . , Xn ) e T2 = t2 (X1 , X2 , . . . , Xn ), con T1 ≤ T2 , l’intervallo [T1 , T2 ] viene detto intervallo di confidenza al livello 1 − α per il parametro θ se ∀ θ ∈ Θ ⊆ IR: P [T1 ≤ θ ≤ T2 ; θ] = 1 − α (5.1) con 0 ≤ α ≤ 1. In particolare la (5.1) afferma che la probabilità che l’intervallo casuale [T1 , T2 ] contenga il vero ed ignoto valore del parametro θ è 1 − α, qualunque sia il vero valore del parametro assunto nello spazio parametrico. In tal modo le n osservazioni 1 Per approfondimenti: Shao (1999), Schervish (1997). Trattasi delle note proprietà di correttezza e di consistenza, perlomeno asintotica, di uno stimatore. 2 E. D. Isaia, Linguaggio R e applicazioni statistiche campionarie, raccolte nel vettore x, vengono impiegate per individuare un insieme di valori che, con una certa “fiducia”, conterrà il vero valore del parametro. È bene tenere a mente che oltre agli intervalli di confidenza corrispondenti alla (5.1), possiamo considerare intervalli di confidenza unilaterali del tipo: P [T1 ≤ θ; θ] = 1 − α (5.2) P [T2 ≥ θ; θ] = 1 − α (5.3) Dal punto di vista pratico, tra i diversi metodi che consentono la costruzione di intervalli di confidenza, vale la pena ricordare quello basato sulla “quantità pivotale”, cioè una funzione3 delle osservazioni campionarie e del parametro θ, diciamo q (X1 , X2 , . . . , Xn ; θ), la cui distribuzione non dipende dal parametro θ. Ciò premesso, sarà possibile individuare due valori q 1;α e q2;α che verranno a dipendere unicamente da α e tali che: P [q1;α ≤ q (X1 , X2 , . . . , Xn ; θ) ≤ q2;α ; θ] = 1 − α (5.4) A questo punto, se possiamo esprimere l’insieme: {x1 , x2 , . . . , xn : q1;α ≤ q (x1 , x2 , . . . , xn ; θ) ≤ q2;α } nella forma: {x1 , x2 , . . . , xn : t1 (x1 , x2 , . . . , xn ) ≤ θ ≤ t2 (x1 , x2 , . . . , xn )} dove t1 (·) e t2 (·) sono funzioni non dipendenti da θ, allora l’intervallo: [t1 (X1 , X2 , . . . , Xn ) , t2 (X1 , X2 , . . . , Xn )] è un intervallo di confidenza al livello 1 − α per θ. A ben vedere, la relazione (5.4) non necessariamente è soddisfatta da un’unica coppia (q1;α , q2;α ); generalmente questi vengono individuati in modo da lasciare una uguale probabilità, pari ad α/2, nelle code sinistra e destra della distribuzione della quantità pivotale q (X1 , X2 , . . . , Xn ; θ). Dal punto di vista applicativo, grande importanza rivestono gli intervalli di confidenza per campioni tratti da una distribuzione normale, cioè qualora si ipotizzi che le v.c. X1 , X2 , . . . , Xn siano i.i.d. ∼ N (µ, σ 2 ). Sotto tale ipotesi, per gli stimatori: X̄ = n−1 n ! i=1 3 Xi S 2 = (n − 1)−1 n ! , i=1 Xi − X̄ -2 In genere una quantità pivotale non è uno stimatore, dal momento che viene a dipendere da θ. 121 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 risultano le seguenti quantità pivotali: Z= √ X̄ − µ n ∼ N (0, 1) σ W = (n − 1) S2 2 2 ∼ χn−1 σ Ricordando, inoltre, che le v.c. Z e W sono stocasticamente indipendenti, la v.c.: U= √ √ X̄ − µ Z n−1 √ = n S W viene a possedere distribuzione t di Student con ν = n − 1 gradi di libertà. Ciò premesso, vediamo come applicare quanto esposto in alcuni casi pratici. Esempio 5.1.1 La costruzione di un intervallo di confidenza per il parametro θ = µ av( √ X̄ − µ ha viene ricorrendo allo stimatore X̄ = n−1 ni=1 Xi . Dal momento che U = n S 2 distribuzione t di Student con ν = n − 1 gradi di libertà, allora ∀ µ, σ : 1−α = = ) * √ X̄ − µ P |U | ≤ n−1 t1−α/2 = P | n | ≤ n−1 t1−α/2 = S ) * S S P X̄ − n−1 t1−α/2 √ ≤ µ ≤ X̄ + n−1 t1−α/2 √ n n " # dove n−1 t1−α/2 indica il quantile di ordine 1−α/2 della distribuzione t di Student con ν = n−1 gradi di libertà. Pertanto, stabilito il livello di confidenza 1 − α, avremo: ) * S S ICµ = X̄ − ν t1−α/2 √ ; X̄ + ν t1−α/2 √ n n √ Si osservi che la v.c. S/ n, detta abitualmente errore standard, rappresenta la stima della varianza dello stimatore X̄, media campionaria. Desiderando automatizzare quanto esposto, possiamo considerare la seguente: 1 2 3 4 5 6 7 8 9 10 Funzione 5.1.1 (I.C. per µ, σ 2 ignota) > ic.mu<-function(x,alpha=0.05,decimali=4) { n<-length(x) media.x<-mean(x) sd.x<-sd(x) se.x<-sd(x)/sqrt(n) ic.inf<-media.x-qt(1-alpha/2,n-1)*se.x ic.sup<-media.x+qt(1-alpha/2,n-1)*se.x cat("I.C.: ",round(ic.inf,decimali),round(ic.sup,decimali),"\n") } 122 E. D. Isaia, Linguaggio R e applicazioni statistiche Cosı̀, ad esempio, per le n = 12 osservazioni: > x<-c(14.2,13.8,10.1,12.4,11.1,11.3,8.1,11.3,7.8,8.0,9.3,5.9) otteniamo: > ic.mu(x,alpha=.05) I.C.: 8.6576 11.8924 Esempio 5.1.2 La costruzione di un intervallo di confidenza per il parametro θ = σ 2 avviene 2 (n ricorrendo allo stimatore S = (n − 1)−1 i=1 Xi . Dal momento che W = (n − 1) S2 ha σ distribuzione Chi-Quadro con ν = n − 1 gradi di libertà: ) * ) * S2 (n − 1) S 2 2 1 − α = P [W ≤ χn−1;1−α ] = P (n − 1) 2 ≤ χn−1;1−α = P σ ≤ χn−1;1−α σ da cui l’intervallo di confidenza: ICσ2 ) (n − 1) S 2 = 0; χn−1;1−α * Anche in questo caso, desiderando automatizzare quanto esposto, possiamo considerare la seguente: 1 2 3 4 5 6 7 8 Funzione 5.1.2 (I.C. per σ 2 ) > ic.var<-function(x,alpha=0.05,decimali=4) { n<-length(x) var.x<-(n-1)*var(x) ic.inf<-0 ic.sup<-var.x/qchisq(1-alpha/2,n-1) cat("I.C.: ",round(ic.inf,decimali),round(ic.sup,decimali),"\n") } Cosı̀, ad esempio, per le n = 12 osservazioni: > x<-c(14.2,13.8,10.1,12.4,11.1,11.3,8.1,11.3,7.8,8.0,9.3,5.9) abbiamo: > ic.var(x,alpha=.05) I.C.: 0 3.2519 ♥ 123 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Esempio 5.1.3 Siano X1 e X2 due campioni casuali indipendenti, di numerosità rispettivamente n1 e n2 , tratti da altrettante v.c. N (µi , σi2 ), con i = 1, 2. La costruzione di un intervallo di confidenza per la differenza tra due valori medi µ1 − µ2 prende le mosse dalla v.c. X̄1 − X̄2 , a componenti indipendenti. Se le varianze σ12 e σ22 , entrambe ignote, si possano ritenere uguali tra loro, allora la v.c.: U= √ (X̄1 − X̄2 ) − (µ1 − µ2 ) n1 + n 2 Sp (5.5) con: Sp2 = (n1 − 1) S12 + (n2 − 1) S22 n1 + n 2 − 2 risulta avere distribuzione t di Student con ν = n1 + n2 − 2 gradi di libertà. Pertanto: 1−α = = ≤ ) √ (X̄1 − X̄2 ) − (µ1 − µ2 ) | ≤ n1 +n2 −2 t1−α/2 P | n1 + n 2 Sp ) Sp P (X̄1 − X̄2 ) − n1 +n2 −2 t1−α/2 √ ≤ µ1 − µ2 n1 + n 2 * Sp (X̄1 − X̄2 ) + n1 +n2 −2 t1−α/2 √ n1 + n 2 * Quindi l’intervallo di confidenza (ICµ1 −µ2 ) per la differenza tra due valori medi risulta: ) Sp Sp (X̄1 − X̄2 ) − n1 +n2 −2 t1−α/2 √ ; (X̄1 − X̄2 ) + n1 +n2 −2 t1−α/2 √ n1 + n 2 n1 + n 2 * Anche in questo caso, desiderando automatizzare quanto esposto, possiamo considerare la seguente: 1 2 3 4 5 6 7 8 9 10 11 2 2 Funzione 5.1.3 (I.C. per µX − µY , σX = σX ma ignote) > ic.muxy<-function(x,y,alpha=0.05,decimali=4) { nx<-length(x) ny<-length(y) media.dif<-mean(x)-mean(y) sp<-sqrt(((nx-1)*var(x)+(ny-1)*var(y))/ (nx+ny-2))*sqrt((1/nx)+(1/ny)) ic.inf<-media.dif-qt(1-alpha/2,nx+ny-2)*sp ic.sup<-media.dif+qt(1-alpha/2,nx+ny-2)*sp cat("I.C.: ",round(ic.inf,decimali),round(ic.sup,decimali),"\n") } > ic.muxy(x,y,alpha=.05) I.C.: -5.1259 0.6502 124 E. D. Isaia, Linguaggio R e applicazioni statistiche Osservazione 5.1.1 Se l’ipotesi di uguaglianza 4 tra le due varianze σ12 e σ22 non potesse essere assunta, allora si dimostra che la funzione test (5.5) viene ad essere distribuita approssimativamente secondo una t di Student i cui gradi di libertà vengono stimati mediante l’approssimatione di Welch-Satterthwaite: ν= 4 2 −1 S12 n−1 1 + S2 n2 6 S12 n−1 S 2 n−1 1 + 2 2 n1 − 1 n2 − 1 Evidentemente, ν non è necessariamente un intero: in tal caso lo si approssima all’intero immediatamente precedente. Quello che ne risulta è una distribuzione t di Student con numero di gradi di libertà minore di n 1 + n2 − 2 . L’output delle funzioni precedentemente introdotte, può ovviamente essere arricchito con l’aggiunta di commenti ed altre informazioni, oltre al desiderato intervallo di confidenza. Cosı̀, ad esempio, la funzione (5.1.1) potrebbe esere riscritta come: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ic.mu<-function(x,alpha=0.05,decimali=4) { n<-length(x) media.x<-mean(x) sd.x<-sd(x) se.x<-sd(x)/sqrt(n) ic.inf<-media.x-qt(1-alpha/2,n-1)*se.x ic.sup<-media.x+qt(1-alpha/2,n-1)*se.x ris<-c(1:3) ris[1]<-round(media.x, decimali) ris[2]<-round(sd.x, decimali) ris[3]<-round(se.x, decimali) ris<-matrix(ris,ncol=1) dimnames(ris)<-list(c("Media campionaria","Deviazione standard:", "Standard error:"),"") cat("Vettore dei dati individuali: ", deparse(substitute(x)), "\nOsservazioni: ", n,"\n","\n---------------------------", "\n","I.C.: ",round(ic.inf,decimali)," ; ", round(ic.sup,decimali),"\n----------------------------", "\n","\nStatistiche:","\n") ris } 4 In termini tecnici si parla di ipotesi di omoschedasticità tra le varianze. 125 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 A tal proposito, per le n = 12 osservazioni precedentemente impiegate: > x<-c(14.2,13.8,10.1,12.4,11.1,11.3,8.1,11.3,7.8,8.0,9.3,5.9) otteniamo: > ic.mu(x,alpha=.05,decimali=3) Vettore dei dati individuali: x Osservazioni: 12 --------------------------I.C.: 8.658 ; 11.892 ---------------------------Statistiche: Media campionaria 10.275 Deviazione standard: 2.546 Standard error: 0.735 I risultati proposti in questo paragrafo, in virtù del Teorema Limite Centrale, possono essere approssimativamente applicati a campioni tratti da distribuzioni non necessariamente normali, a patto però che la cardinalità n sia sufficientemente grande. Esempio 5.1.4 Una moneta, di cui si ignora se sia equilibrata o no, viene lanciata n = 100 volte. Indicando con π la probabilità, costante, di ottenere “Croce” in un singolo lancio, ci proponiamo la costruzione di un intervallo di confidenza per π, a partire dal campione casuale X1 , X2 , . . . , Xn , le cui componenti Xi risultano v.c. indipendenti con, ciascuna, distribuzione bernoulliana, cioè, ∀ i = 1, 2, . . . , n: Xi = + 0 1 1−π π A tal fine (cfr. Esempio 4.3.5), si immagini che l’esperimento casuale abbia dato luogo ai seguenti valori: > lancio<-sample(c(0,1), 100, replace = TRUE) > lancio [1] 0 1 0 1 1 1 0 0 0 1 1 0 0 0 1 1 0 1 1 1 0 1 1 1 1 1 [27] 0 1 0 1 0 0 0 1 1 1 1 1 1 0 1 1 1 0 1 1 1 1 1 1 0 1 [53] 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 1 0 0 1 1 1 1 1 1 1 1 [79] 1 1 0 1 1 0 0 1 1 0 1 1 1 1 1 1 1 1 1 0 1 0 > dimnames(table(lancio))<-list(Lancio=c("Testa","Croce")) 126 E. D. Isaia, Linguaggio R e applicazioni statistiche > table(lancio) Lancio Testa Croce 40 60 ( Stimatore di π viene ad essere la v.c. X̄ = ni=1 n−1 Xi , detta in tal caso proporzione campionaria, che indica, appunto, la proporzione delle Croci ottenute nella n-pla osservata. Dal momento che n è grande, possiamo fare appello al Teorema Limite Centrale ed affermare che π (1 − π) la distrbuzione di X̄ è approssimativamente Normale con parametri π e . L’intervallo n di confidenza sarà, dunque: : < ; ; x̄ (1 − x̄) x̄ (1 − x̄) ICµ = x̄ − ν t1−α/2 ; x̄ + ν t1−α/2 n n la cui valutazione in R avviene mediante l’istruzione: > ic.mu(lancio,alpha=.05) Vettore dei dati individuali: Osservazioni: 100 lancio --------------------------I.C.: 0.5337 ; 0.7263 ---------------------------Statistiche: Media campionaria Deviazione standard: Standard error: 0.63 0.4852 0.0485 Si osservi che l’intervallo di confidenza ottenuto non contiene il valore 0.5. ♥ Va da sé che qualora non si possa ricorrere al Teorema Limite Centrale occorre individuare la distribuzione esatta degli stimatori dei parametri di interesse, il che generalmente comporta alcuni problemi sopratutto ai fini del calcolo numerico. Senza voler entrare in dettagli, tentiamo di illustrare il problema prendendo spunto dalla situazione di cui all’Esempio 5.1.4. Supponiamo, dunque, che X sia una v.c. con distribuzione bernoulliana di parametro ignoto π. Al fine di stimare π, estratto il campione casuale X1 , X2 , . . . , Xn , di dimensione n, possiamo ricorrere allo stimatore ( T = ni=1 Xi che rappresenta il nmero dei successi ottenuti in X. Manifestamente tale stimatore, in quanto somma di n v.c. i.i.d. bernoulliane, possiede distribuzione binomiale di parametri n e π con 5 con IE[T ] = n π e V ar[T ] = n π (1 − π). 5 Si noti che tra lo stimatore X̄ di cui all’Esempio 5.1.4 e lo stimatore T qui introdotto intercorre la semplice relazione X̄ = n−1 T . 127 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Al fine della costruzione di un intervallo di confidenza per π, al livello di confidenza 1 − α, occorre individuare i quantili di ordine α/2 e 1 − α/2 della distribuzione di T , ossia risolvere rispetto a ki , i = 1, 2, le equazioni: P [T ≤ k1 ] = k1 ! px (1 − p)n−x = α (5.6) P [T ≤ k2 ] = k2 ! px (1 − p)n−x = 1 − α (5.7) t=0 t=0 dove p rappresenta la stima puntuale di π, ovvero p = t(x)/n. Il calcolo dei quantili k1 e k2 , in accordo alle (5.6) e (5.7), può essere eseguito ricorrendo al comando uniroot (cfr. paragrafo ??) applicato sulla funzione di ripartizione di una binomiale di parametri n, p. Pertanto possiamo considerare la seguente: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Funzione 5.1.4 (I.C. esatto per π) ic.p<-function(x,n,livello.conf=0.95) { p<-x/n alpha<-(1-livello.conf)/2 LI<-function(x,alpha) { uniroot(function(p) pbinom(x-1,n,p)-livello.conf,c(0,1))$root } LS<-function(x, alpha) { uniroot(function(p) pbinom(x,n,p)-alpha,c(0,1))$root } IC<-{c(LI(x,alpha), LS(x,alpha))} stima.p<-x/n cat("Stima =",stima.p ,"\n") cat("IC =",IC,"\n") } Esempio 5.1.5 Con riferimento all’esperimento casuale di cui all’Esempio 5.1.4, avendo osservato 60 Croci in 100 lanci di una stessa moneta, l’intervallo di confidenza esatto per il parametro π risulta: > ic.p(60,100) Stima = 0.6 IC = 0.5129658 0.6967233 più piccolo rispetto a quanto ottenuto applicando il Teorema Limite Centrale. 128 ♥ E. D. Isaia, Linguaggio R e applicazioni statistiche 5.2 Verifica di ipotesi statistiche Dato un campione casuale (X1 , X2 , . . . , Xn ) di dimensione n tratto da una v.c. X con densità fX (x; θ) nota a meno dei parametri θ = (θ 1 , θ2 , . . . , θk ) ∈ Θ ⊆ IRk , un’ipotesi statistica può essere intesa quale asserzione sul vettore dei parametri della densità del tipo H : θ ∈ Θ0 , ove Θ0 è un sottoinsieme dello spazio parametrico Θ. In particolare l’ipotesi H viene detta semplice se Θ 0 contiene un solo elemento, composta qualora contenga più elementi. Il problema che ci si pone è stabilire se θ ∈ Θ 0 oppure no. Abitualmente il problema viene posto ricorrendo ad un sistema di ipotesi del tipo: + H0 : θ ∈ Θ0 H1 : θ ∈ Θ1 con Θ0 ∪Θ1 = Θ e Θ0 ∩Θ1 = ∅. La prima asserzione è detta ipotesi nulla e rappresenta l’ipotesi che si desidera testare, la seconda viene detta ipotesi alternativa. Sulla base dei risultati forniti dalla n-pla osservata, si perverrà a decidere se l’ipotesi nulla è sostenuta dai dati o se questi invece sono a favore dell’ipotesi alternativa. Con il termine test statistico si intende appunto la procedura di decisione in favore di H 0 o di H1 . Più precisamente, un test statistico π (x) viene ad essere una funzione che assume valore π0 se i dati campionari portano all’accettazione di H 0 e π1 in caso contrario. In sostanza, esso viene a creare una partizione dello spazio campionario; tutti gli elementi dello spazio campionario per cui π (x) = π 0 vengono a costituire la regione di accettazione di H0 , A = {x : π (x) = π0 }, mentre l’insieme complementare, Ā = {x : π (x) = π1 }, costituisce regione di rifiuto di H 0 . In definitiva, dunque, se x ∈ A si accetta l’ipotesi nulla, la si rigetta qualora x ∈ Ā. Tale modo di procedere, tuttavia, ci espone a due particolari rischi: — rigettare l’ipotesi nulla, quando in realtà essa è vera; — accettare l’ipotesi nulla, quando in realtà essa è falsa. In letteratura, tali errori vengono, rispettivamente detti errore del primo tipo ed errore del secondo tipo. Appare, quindi, intuitivo che un test statistico debba tentare di minimizzare la probabilità di commettere entrambi i due tipi di errore. Per ogni testo statistico possiamo definire la funzione di potenza: " # K (θ) = P X ∈ Ā; θ = P [π (X) = π1 ; θ] (5.8) cioè come la probabilità di rifiutare l’ipotesi nulla per ogni valore del parametro θ. Sotto tale profilo, dunque, un test statistico verrà considerato “ottimo” se al contempo minimizza la (5.8) per θ ∈ Θ0 e viceversa massimizza la (5.8) per θ ∈ Θ 1 . 129 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Evidentemente, tale condizione non può essere verificata poiché i due requisiti sono in conflitto tra loro. In pratica, la risoluzione del problema avviene fissando in modo arbitrario il cosidetto livello di significatività del test, definito: " α = sup K (θ) = sup P X ∈ Ā; θ θ∈Θ0 θ∈Θ0 # (5.9) cioè la probabilità di commettere l’errore del primo tipo. " Osserviamo ancora che, # qualora Θ0 sia semplice, allora il livello del test è α = P X ∈ Ā; θ0 . Quanto alla probabilità di commettere il secondo tipo di errore, questa viene indicata con β (θ) = P [X ∈ A; θ ∈ Θ1 ] = 1 − K (θ). A questo punto, fissato il livello di significatività, nella famiglia dei test di livello preassegnato, verrà scelto un test tale che β (θ) sia uniformemente minimizzata su Θ1 , ovvero tale che K (θ) venga uniformemente massimizzata in Θ 1 . Un siffatto test viene detto uniformemente più potente. Quindi un test ottimo sarà definito come quel test che per α assegnato ha potenza massima. È importante osservare che alla partizione dello spazio campionario, indotta dal test statistico, viene associata una funzione a valori reali detta abitualmente funzione test, e coincidente con una statistica t (x) che assume valori piccoli quando H 0 è vera e valori elevati quando è vera H 1 . Possiamo quindi dire che un test statistico è una procedura basata su un campione casuale tramite una funzione test con la quale H 0 è rigettata a favore di H1 per certi valori estremi della funzione test ed accettata per i restanti valori possibili. Ne seguito ci limitiamo a presentare una collezione di funzioni test 6 utili in svariate situazioni ed implementate in R, mentre non ci occuperemo della costruzione di test ottimali. È importante osservare, Gibbon, Pratt (1975), che è norma comune stabilire qual’è il più piccolo livello per il quale la n-pla osservata conduce al rifiuto dell’ipotesi nulla. Ciò avviene valutando il valore osservato t della funzione test tramite il livello di significatività osservato o p-value, definito: p − value = sup P [t (X) > t; θ] (5.10) θ∈Θ0 Tanto più il p − value è piccolo, tanto minore sarà la probabilità che sotto l’ipotesi nulla la funzione test produca un valore maggiore di quello osservato, mentre è alta la probabilità sotto l’ipotesi alternativa. In pratica tanto più è piccolo il p − value, tanto più saremo propensi ad accettare H 0 . Posto che θ sia il parametro unidimensionale di interesse e indicando con T = t (X) una funzione test, i diversi tipi di ipotesi su θ che affronteremo nel seguito saranno: 6 Funzioni test a potenza massima e basati sul rapporto tra le funzioni di verosomiglianza calcolate sotto H0 e H1 . 130 E. D. Isaia, Linguaggio R e applicazioni statistiche Ipotesi nulla H0 : θ = θ 0 Ipotesi altenative H1 : θ 3= θ0 H1 : θ > θ 0 H1 : θ < θ 0 ipotesi bidirezionale ipotesi unidirezionale ipotesi unidirezionale mentre i corrispondenti p − value saranno calcolati in base alla distrbuzione della funzione test T = t (X) sotto l’ipotesi nulla, ponendo cioè θ = θ 0 . Desiderando in qualche modo chiarire quanto sin qui riassunto, valga il seguente: Esempio 5.2.1 I responsabili di un Istituto di Credito ritengono che l’importo dei prelievi effettuati con il Bancomat, presso il proprio sportello, abbiano una distribuzione approssimativamente normale con valor medio pari a 300.000 lire. Al fine di verificare tale affermazione, è stato estratto un campione casuale di dimensione n = 40 il quale ha fornito i seguenti risultati (in lire x 1000): 350 150 150 200 300 350 400 350 200 250 350 500 450 300 550 450 250 250 500 250 350 250 250 350 250 550 350 250 350 150 350 100 250 250 550 350 300 350 450 350 Si immagini che il sistema di ipotesi statistiche che si desidera sottoporre a verifica sia: + H0 : µ = µ0 = 300 H1 : µ > µ0 = 300 Manifestamente trattasi di una verifica di ipotesi, con alternativa unilaterale, sul valor medio di una distribuzione normale con varianza ignota; la funzione test che verrà utilizzata è quella che prevede la stima di σ 2 mediante la varianza campionaria corretta S 2 , e pertanto: T = t (X) = √ X̄ − µ n S che, sotto H0 , ha distribuzione t di Student con ν = n − 1 gradi di libertà. Per la natura dell’ipotesi alternativa H1 , segue che la regione di rifiuto è Ā = {x : t(x) > k}, dove k indica il valore critico della funzione test determinato in modo da soddisfare la (5.9), cioè: " # P X ∈ Ā; µ0 = P [T > k; µ0 ] = α Se si sceglie di porre α = 0.05, otteniamo, per ν = 39, quale valore critico k = 1.6849 e la √ regola di decisione porterà al rigetto di H0 qualora sia tSper. = 40 x̄ −s300 > k. In R possiamo impartire i comandi: > x<-c(350,300,200,450,250,350,250,350,250,300,150,350,250,300,250, 250,550,150,250,350,150,400,350,550,500,250,350,350,550,450, 200,350,500,450,250,350,250,100,350,350) > alpha<-0.05 > k.critico<-qt(1-alpha,length(x)-1) > t.sper<-(sqrt(40))*(mean(x)-300)/sd(x) 131 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 donde i risulati: > k.critico [1] 1.684875 > t.sper [1] 1.320101 che, per le ipotesi di lavoro fatte, condurrebbero all’accettazione di H0 . Osservazione 5.2.1 Per la simmetria della distribuzione della funzione test risulta t1−α;ν = −tα;ν , pertanto ai fini del calcolo del valore critico del test avremmo potuto impartire il comando: > k.critico<-qt(alpha, length(x)-1, lower=FALSE) del tutto equivalente a: > k.critico<-qt(1-alpha, length(x)-1) oppure a: > k.critico<- -qt(alpha, length(x)-1) Tale approccio, tuttavia, non viene in pratica utilizzato dai pacchetti statistici in commercio, i quali forniscono il p − value associato alla verifica di ipotesi richiesta in accordo alla (5.10). Nel caso in esame, indicando con fT (t; µ0 ) la densità della funzione test sotto H0 , avremo: p.value = = +∞ tSper. fT (t; µ0 ) dt = 1 − = tSper. fT (t; µ0 ) dt −∞ e di conseguenza in R: > p.value<-1-pt(t.sper,length(x)-1) > p.value [1] 0.09724868 il che indica che l’area della coda a destra del quantile tSper. della distribuzione t di Student con ν = 39 gradi di libertà è all’incirca il 10%. Anche sotto tale ottica si è propensi ad accettare H0 . A questo punto, per avere un’idea del potere discriminatorio del test"approntato, # potrebbe essere interessante calcolare la funzione di potenza del test, K (µ) = P X ∈ Ā; µ , perlomeno in corrispondenza ad alcuni valori di µ sotto H1 . Ciò equivale a calcolare il complemento ad uno della funzione di ripartizione di una ditribuzione t di Student, con ν = n − 1 gradi di √ µ −µ libertà e parametro di non centralità n 1 S 0 , in corrispondenza a k = 1.6849. Scelto di porre, sotto H1 , µ1 = 310 e ricordando le Osservazioni 4.0.4 e 5.2.1, in R possiamo impartire i comandi: 132 E. D. Isaia, Linguaggio R e applicazioni statistiche > mu1<-310 > mu0<-300 > sqm<-sd(x) > nonc<-sqrt(length(x))*(mu1-mu0)/sd(x) > pt(qt(alpha, df=length(x)-1), df=length(x)-1, ncp = nonc, lower = FALSE) [1] 0.98578 La potenza del test, in corrispondenza dell’ipotesi alternativa µ1 = 310, vale pertanto 0.98578. In altri termini β (µ1 = 310) = P [X ∈ A; µ1 = 310] = 0.01422, ovvero una probabilità di circa il 1.4% di commettere l’errore del II tipo in corrsIpondenza a µ1 = 310. ♥ Alla luce dell’Esempio proposto, appare evidente come in R possano essere implementate funzioni ad hoc per la verifica di ipotesi statistiche e a tal proposito valga il seguente: Esempio 5.2.2 Desiderando verificare l’ipotesi di omoschedasticità tra due varianze H 0 : 2 2 σX /σY2 = 1 contro l’alternativa H1 : σX /σY2 > 1, in base alle realizzazioni di due campioni 2 indipendenti tratti dalle v.c. X ∼ N (µX , σX ) e Y ∼ N (µY , σY2 ), ricordando che la statistica 2 2 campionaria SX /SY , sotto l’ipotesi nulla, ha distribuzione F di Snedecor con nX − 1 e nY − 1 gradi di libertà rispettivamente a numeratore e denominatore, posiamo introdurre la seguente funzione ad hoc: 1 2 3 4 5 6 7 8 9 10 11 Funzione 5.2.1 (Verifica di ipotesi per due varianze) > var.equal<-function(x,y) { ok <- (!is.na(x) & !is.na(y)) x <- x[ok]; y <- y[ok] nx <- length(x); ny <- length(y) if(nx <= 2 || ny <= 2) stop("not enough observations") Fsper<-sqrt(var(x))/sqrt(var(y)) pvalue<-1-pf(Fsper, nx-1, ny-1) sigma<-list(vx=var(x),vy=var(y),rapporto=Fsper,pval=pvalue) return(sigma) } A commento della funzione proposta: — le righe da [2] a [5] si occupano del controllo dei vettori x e y immessi; — la riga [6] provvede al calcolo del valore sperimentale della funzione test impiegata; — in riga [7] si procede al calcolo del p − value associato al test in accordo alla (5.10). — in riga [8] si crea la lista sigma che contiene i risultati del test (varianze campionarie, valore sperimentale della funzione test e corrispondente p − value); — l’istruzione in riga [9] visualizza la lista sigma. 133 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Lasciamo come esercizio al Lettore il problema del calcolo della potenza del test in corrispon2 denza ad un particolare valore del rapporto σX /σY2 sotto l’ipotesi alternativa7. ♥ Prima di concludere, desideriamo accennare al problema dell’individuazione della dimensione n del campione casuale sı̀ che essa garantisca, a fronte di un dato sistema di ipotesi statistiche, prefissate probabilità di commettere sia l’errore del I tipo che l’errore del II tipo, questa valutata in corrispondenza di un particolare valore cruciale θ ∈ Θ1 . Il problema viene superato, fissate le probabilità α e β(θ ∈ Θ 1 ), risolvendo rispetto ad n l’equazione: K(θ ∈ Θ1 ) = 1 − β(θ ∈ Θ1 ) (5.11) Dal momento che generalmente le funzioni test coinvolte hanno, perlomeno sotto l’ipotesi alternativa, una distribuzione non centrale, il problema può essere risolto ricercando per via numerica le radici dell’equazione (5.11), sfruttando, ad esempio, il comando uniroot, di cui al paragrafo (??). Esempio 5.2.3 Si immagini che il contenuto, in ml, di flaconi di un certo medicinale siano imbottigliati mediante due processi produttivi possa essere modellizzato mediante le due v.c. X1 ∼ N (µ1 , σ 2 ) e X2 ∼ N (µ2 , σ 2 ), dove, in base a indagini precedenti, si ha la stima S 2 = 6. Desiderando sottoporre a verifica le seguenti ipotesi statistiche: + H0 : µ1 − µ2 = 0 H1 : µ1 − µ2 > 0 si vuole determinare la numerosità campionaria che rispetti le seguenti condizioni: — probabilità dell’errore del I tipo pari al 5%, ossia α = 0.05; — potenza del test, in corrispondenza all’ipotesi alternativa µ1 − µ2 = 2 = δ, pari al 98%. Ora, sappiamo che la funzione test, sotto l’ipotesi alternativa, ha distribuzione t di Student > con 2 (n − 1) gradi di libertà e parametro di non centralità n/2 δ2 ; sicché possiamo scrivere S l’espressione per K(δ) come: > potenza<-quote ({ pt(qt(0.05, df=2*(n-1), lower = FALSE), df=2*(n-1), ncp=sqrt(n/2) * 2/sqrt(6), lower = FALSE) }) Quindi, ricorrendo alla funzione uniroot (cfr. Esempio ??), e ricordando che per le ipotesi fatte K(δ) = 0.98, abbiamo: > n<-uniroot(function(n) eval(potenza) - 0.98, c(2, 1e+07))$root > n [1] 33.16656 sı̀ che la numerosità campionaria atta a garantire i vincoli posti sarà n = 2 · 34 = 68. 7 Cfr. Osservazione 4.0.4 ed Esempio 5.2.1. 134 ♥ E. D. Isaia, Linguaggio R e applicazioni statistiche 5.3 La libreria ctest In R è possibile procedere alla verifica di di ipotesi statistiche ricorrendo, come già si disse, alle funzioni contenute nella libreria ctest, acronimo di “Common Tests”. Prima di passare in rassegna ad alcune di esse, vediamo come è possibile accedere ad una libreria, visualizzarne il contenuto ed eventualmente liberare l’area di lavoro dalle librerie in eccesso. I comandi essenzialmente sono: — library(nome della libreria): carica nell’area di lavoro corrente la libreria specificata; — (.packages()): elenca le librerie attive; — help(package=nome della libreria): fornisce, nella finestra di Help, l’elenco delle funzioni della libreria specificata; — detach("package:nome della libreria"): libera l’area di lavoro corrente dalla libreria specificata. Nel nostro caso, essendo interessati alla libreria ctest, potremmo impartire i comandi: > (.packages()) [1] "base" > library(ctest) > (.packages()) [1] "ctest" "base" > detach("package:ctest") > (.packages()) [1] "base" In particolare, poi, il comando help(package=ctest) porge il seguente elenco 8 : ansari.test Ansari-Bradley Test bartlett.test Bartlett Test for Homogeneity of Variances binom.test Exact Binomial Test chisq.test Pearson’s Chi-squared Test for Count Data cor.test Test for Zero Correlation fisher.test Fisher’s Exact Test for Count Data fligner.test Fligner-Killeen Test for Homogeneity of Variances friedman.test Friedman Rank Sum Test kruskal.test Kruskal-Wallis Rank Sum Test 8 Aggiornamento alla data 01.02.2001. 135 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 ks.test Kolmogorov-Smirnov Tests mantelhaen.test Cochran-Mantel-Haenszel Chi-Squared Test for Count Data mcnemar.test McNemar’s Chi-squared Test for Count Data mood.test Mood Two-Sample Test of Scale wise.prop.test Pairwise comparisons of proportions pairwise.t.test Pairwise t tests pairwise.table Tabulate p values for pairwise comparisons pairwise.wilcox.test Pairwise Wilcoxon rank sum tests power.prop.test Power calculations two sample test for of proportions power.t.test Power calculations for one and two sample t tests print.pairwise.htest Print method for pairwise tests print.power.htest Print method for power calculation object prop.test Test for Equal or Given Proportions prop.trend.test Test for trend in proportions quade.test Quade Test shapiro.test Shapiro-Wilk Normality Test t.test Student’s t-Test var.test F Test to Compare Two Variances wilcox.test Wilcoxon Rank Sum and Signed Rank Tests Test su valori medi — t.test La funzione t.test è assai versatile, consentendo all’utente di effettuare una serie piuttosto ampia di verifiche di ipotesi statistiche circa un valor medio o la differenza tra due valori medi. La sintassi estesa della funzione in oggetto è: t.test(x, y=NULL, alternative="two.sided", mu=0, paired = FALSE, var.equal = FALSE, conf.level = 0.95) Volendo procedere, conviene distinguere il caso in cui la verifica di ipotesi coinvolga un solo valor medio da quello in cui si essa sia concentrata sulla differenza tra due valori medi in base alle osservazioni di due campioni indipendenti ovvero appaiati. In tutti i casi, l’output della funzione t.test consiste nella creazione e visualizzazione della lista rval contenente tutte le informazioni relative al test richiesto (valore della statistica test, p-value, intervallo di confidenza, ...) Un solo campione Premesso che la semplice istruzione t.test(x) verifica, sulla base della statistica campionaria x̄, le seguenti ipotesi H 0 : µ = µ0 = 0 contro H1 : µ 3= µ0 , il che è raramente di interesse, ci pare utile soffermarci sugli argomenti della funzione in esame; pertanto: 136 E. D. Isaia, Linguaggio R e applicazioni statistiche — indicato l’oggetto che contiene le determinazioni campionarie, occorre specificare il valore di µ sotto l’ipotesi nulla, poiché come si è detto la situazione di default lo pone uguale a zero; — successivamente, a seconda della struttura dell’ipotesi alternativa si dovrà indicare se il test è di tipo bilaterale ovvero unilaterale a protezione inferiore o superiore; a tal fine, valga la tabella riassuntiva che segue: Ipotesi nulla H0 : µ = µ0 Ipotesi altenative H1 : µ 3= µ0 H1 : µ > µ0 H1 : µ < µ0 parametri (...alternative="two.sided",...) (...,alternative="greater",...) (...,alternative="less",...) — in ultimo l’utente può specificare il livello 1 − α desiderato nella costruzione dell’intervallo di confidenza per il valor medio incognito µ; la situazione di default prevede conf.level=0.95. Esempio 5.3.1 Un produttore di lampade fluorescenti asserisce che le proprie lampade hanno una durata media di corretto funzionamento di 1200 ore. A fine di verificare tale affermazione, abbiamo sottoposto a prova di durata un campione casuale di n = 10 lampade, ottenendo i seguenti risultati circa la durata di corretto funzionamento (espressa in ore): 1179 1235 1180 1250 1220 1010 1000 1150 1277 Il sistema di ipotesi a conflitto è il seguente: H0 : µ = 1200 H1 : µ < 1200 Desiderando procedere, ricorriamo alla funzione t.test: > x<-c(1179,1235,1180,1250,1220,1010,1000,1150,1277,1129) > t.test(x,y=NULL, alternative="less", mu=1200,paired = FALSE, var.equal = FALSE, conf.level = 0.95) One Sample t-test data: x t = -1.2345, df = 9, p-value = 0.1241 alternative hypothesis: true mean is less than 1200 95 percent confidence interval: NA 1217.941 sample estimates: mean of x 1163 137 1129 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Dal momento che il p-value associato al test è maggiore, seppur di poco, di 0.10, siamo portati ad accettare l’ipotesi nulla. Si osservi che il valore di µ sotto l’ipotesi nulla H 0 rientra nell’intervallo di confidenza [0; 1217.941]. ♥ Due campioni indipendenti Nel caso si operi su due campioni casuali indipendenti, (X1 , X2 , . . . , XnX ) e (Y1 , Y2 , . . . , YnY ), e si desideri verificare l’ipotesi che essi provengano da densità caratterizzate da un ugual valor medio, occorrerà: — indicare gli oggetti, ad esempio x e y, che contengono le determinazioni campionarie; — scegliere il tipo di test idoneo a seconda della struttura dell’ipotesi alternativa, come si è visto al punto precedente (alternative="..."); — indicare che trattasi di determinazioni provenienti appunto da campioni indipendenti (paired=FALSE); 2 e σ 2 possono ritenersi tra loro uguali o non, — specificare se le varianze ignote σ X Y ricordando che la situazione di default prevede var.equal=FALSE e in tal caso i gradi di libertà della t di Student coinvolta sono stimati in accordo al metodo proposto da Welch-Satterthwaite (cfr. Osservazione 5.1.1); — stabilire il livello 1 − α desiderato nella costruzione dell’intervallo di confidenza per la differenza tra i valori medi µ X e µY . Esempio 5.3.2 Si immagini che i responsabili della Qualità, di un’azienda operante in campo informatico, al fine di monatre dischi fissi di nuova generazione su propri PC si trovino a dover scegliere tra due fornitori (A e B) che, a parità di prestazioni dichiarate, offrono prezzi unitari tra loro diversi. Ai fini della scelta del componente a prezzo unitario minore, sono state effettuate, per ciascun tipo di prodotto, più misurazioni (espresse in millesimi di secondo) dei tempi di accesso al disco fisso e ciò al fine di verificare, in base ai dati campionari ottenuti, se esistono differenze significative tra i corrispondenti valori medi di universo µA e µB , ottenendo i seguenti risultati: fornitore A fornitore B 30.0 28.7 29.9 28.6 29.2 29.4 29.8 29.7 30.8 29.9 29.8 30.2 30.4 28.7 28.9 29.4 30.5 30.4 29.7 29.7 Il sistema di ipotesi a conflitto è il seguente: H0 : µA = µB H1 : µA #= µB Desiderando procedere, supponendo che le corrispondenti varianze, pur ignote, possano ritenersi uguali, e ricorrendo alla funzione t.test, si ha: 138 E. D. Isaia, Linguaggio R e applicazioni statistiche > x<-c(30.0,29.9,29.2,29.8,30.8,29.8,30.4,28.9,30.5,29.7) > y<-c(28.7,28.6,29.4,29.7,29.9,30.2,28.7,29.4,30.4,29.7) > t.test(x,y, alternative="two.sided", mu=0,paired = FALSE, var.equal = TRUE, conf.level = 0.95) Two Sample t-test data: x and y t = 1.5854, df = 18, p-value = 0.1303 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: -0.1398368 0.9998368 sample estimates: mean of x mean of y 29.90 29.47 Dal momento che il p-value associato al test è maggiore del 10%, i responsabili della Qualità saranno portati ad accettare l’ipotesi nulla9 e, pertanto, a preferire il fornitore che offre un prezzo unitario minore. ♥ Due campioni appaiati In tal caso le osservazioni del primo campione non sono indipendenti da quelle del secondo ed il problema coinvolge, per cosı̀ dire, la nuova v.c. D = X − Y , mentre l’ipotesi nulla risulta H 0 : µD = µ0 = 0. Specificati gli oggetti, ad esempio x e y, contenenti le realizzazioni campionarie, si tratterà unicamente di specificare paired=TRUE. A commento, osserviamo che se definissimo il nuovo oggetto w<-x-y e ricorressimo all’istruzione t.test(w), otterremmo ovviamente gli stessi risultati dell’istruzione t.test(x,y,paired=TRUE). Esempio 5.3.3 Si supponga che al fine di verificare l’efficacia di un nuovo farmaco anticoagulante, si sono effettuate n = 8 misurazione della concentrazione (in %) di protrombina su altrettanti pazienti prima e dopo la somministrazione del farmaco, ottenendo i seguenti risultati: prima X dopo Y 0.016 0.014 0.018 0.016 0.023 0.020 0.015 0.012 0.018 0.018 0.015 0.014 0.017 0.018 0.024 0.022 Il sistama di ipotesi che si desidera sottoporre a verifica si presenta: + H0 : µX − µY = 0 H1 : µX − µY > 0 Dal momento che l’analisi è stata condotta sui medesimi pazienti, siamo di fronte a due campioni appaiati (non indipendenti) e pertanto al fine della verifica delle ipotesi poste, abbiamo: 9 Si osservi che l’intervallo di confidenza [−0.1398368; 0.9998368] contiene lo zero. 139 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > x<-c(0.016,0.018,0.023,0.015,0.018,0.015,0.017,0.024) > y<-c(0.014,0.016,0.020,0.012,0.018,0.014,0.018,0.022) > t.test(x,y, alternative="greater", mu=0,paired = TRUE, var.equal = TRUE, conf.level = 0.95) Paired t-test data: x and y t = 3, df = 7, p-value = 0.009971 alternative hypothesis: true difference in means is greater than 0 95 percent confidence interval: 0.0005527107 NA sample estimates: mean of the differences 0.0015 Risultati che indicano come il nuovo farmaco abbia effettivamente potere anti-coagulante. ♥ Osservazione 5.3.1 Desiderando visualizzare o porre in un nuovo oggetto, per successive elaborazioni, un (solo) risultato di interesse, ad esempio il valore della funzione test, l’intervallo di confidenza, ..., sarà sufficiente aggiungere al comando t.test(...) il suffisso $ seguito da uno dei seguenti nomi convenzionali: statistic per il valore della funzione test, p.value per il p−value associato al test, conf.int per l’intervallo di confidenza. Potenza e progettazione di test su valori medi - power.t.test Come si è già sottolineato, due problemi, essenzialmente, sorgono qualora si considerino test di ipotesi statistiche e precisamente: — valutare il potere discriminatorio della funzione test in corrispondenza ad alcuni valori di interesse del parametro θ sotto l’ipotesi alternativa; — individuare la dimensione n del campione casuale sı̀ che essa garantisca prefissate probabilità di commettere sia l’errore del I tipo che l’errore del II tipo, questa valutata in corrispondenza di un particolare valore critico θ ∈ Θ 1 . La risposta al primo quesito è data calcolando la funzione di potenza del test, K (θ), o equivalentemente la probablità di commettere l’errore del II tipo, β (θ), in corrispondenza ai diversi valori di interesse di θ ∈ Θ 1 . Quanto al secondo problema, che va sotto il nome di progettazione di un test, si tratta di risolvere rispetto ad n l’equazione già posta in (5.11) e precisamente: K(θ ∈ Θ1 ) = 1 − β(θ ∈ Θ1 ) 140 E. D. Isaia, Linguaggio R e applicazioni statistiche una volta fissate le probabilità α e β(θ ∈ Θ 1 ). Nel caso di verifiche di ipotesi statistiche su un valor medio o sulla differenza tra due valori medi, i precedenti problemi in R possono essere risolti facendo ricorso alla funzione power.t.test la cui sintassi completa è: power.t.test(n=NULL, delta=NULL, power=NULL, sd=1, sig.level=0.05, type = c("two.sample","one.sample", "paired"), alternative = c("two.sided", "one.sided")) dove10 n rappresenta la numerosità del campione casuale, delta la differenza tra le medie µ1 − µ0 , power la potenza del test in corrispondenza a µ 1 cioè K(µ1 ), sd lo scarto quadratico medio σ o la sua stima s ed infine sig.level la probabilità α dell’errore del I tipo. Il parametro incognito, nel nostro caso power oppure n, deve obbligatoriamente essere passato alla funzione come NULL. L’output della funzione porge il valore numerico di tutti i parametri della stessa. Analogamente ad altre funzioni, possiamo visualizzare ed eventualmente porre in un nuovo oggetto un (solo) risultato di interesse aggiungendo al comando power.t.test(...) il suffisso $ seguito dal nome del parametro di interesse. Esempio 5.3.4 L’Esempio 5.2.1, concernente un test unidirezionale a protezione superiore per un valor medio, proponeva, tra le altre cose, il calcolo della funzione di potenza del test in corrispondenza all’ipotesi alternativa µ1 = 310, calcolo che venne eseguito applicando direttamente la (5.8) e ricorrendo alla distribuzione t di Student, con ν = n−1 gradi di libertà √ µ −µ e parametro di non centralità n 1 S 0 in corrispondenza a k = 1.6849. In alternativa avremmo potuto ricorrere alla funzione power.t.test nel seguente modo 11 : > power.t.test(n=40,power=NULL,delta=10,sd=113.7854,sig.level=0.95, alternative="one.sided",type="one.sample") One-sample t test power calculation n = 40 delta = 10 sd = 113.7854 sig.level = 0.95 power = 0.98578 alternative = one.sided Si osservi che la probabilità dell’errore del II tipo in corrispondenza a µ1 = 310, ossia β(µ1 ) può essere ottenuta con il comando: 10 11 Perlomeno nel caso di test su un solo valor medio. Per i dati dell’Esempio 5.2.1 lo scarto quadratico medio vale 113.7854. 141 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > power.t.test(n=40,power=NULL,delta=-10,sd=113.7854,sig.level=0.05, alternative="one.sided",type="one.sample") One-sample t test power calculation n = 40 delta = -10 sd = 113.7854 sig.level = 0.05 power = 0.01422000 alternative = one.sided Per concludere, si noti il comportamento del comando: > power.t.test(n=40,power=NULL,delta=delta=10,sd=113.7854,sig.level=0.95 alternative="one.sided",type="one.sample")$power [1] 0.98578 quantità che, come sempre, potrebbe essere immessa in un nuovo oggetto per successive elaborazioni. ♥ Esempio 5.3.5 Sia X v.c. distribuita normalmente con parametri µ ignoto e σ 2 stimata, in base a indagini precedenti, in 225. Desiderando sottoporre a verifica le seguenti ipotesi statistiche: + H0 : µ = µ0 = 100 H1 : µ #= µ0 = 100 si desidera progettare un test che rispetti le seguenti condizioni: — probabilità dell’errore del I tipo pari al 5%, ossia α = 0.05; ! !! — potenza del test in corrispondenza all’ipotesi alternativa µ1 = 120 o µ1 = 80 pari al ! !! 98%, ovvero K(µ1 ) = K(µ1 ) = 0.98. Desiderando fare ricorso, in alternativa a quanto fatto a tal riguardo all’Esempio 5.2.3, alla funzione power.t.test, possiamo porre: n=NULL,power=0.98,delta=20,sd=sqrt(225),sig.level=0.05, alternative="two.sided",type="one.sample" ottenendo: > power.t.test(n=NULL,power=0.98,delta=20,sd=sqrt(225),sig.level=0.05, alternative="two.sided",type="one.sample") One-sample t test power calculation 142 E. D. Isaia, Linguaggio R e applicazioni statistiche n = 11.20446 delta = 20 sd = 15 sig.level = 0.05 power = 0.98 alternative = two.sided sı̀ che la numerosità campionaria atta a garantire i vincoli posti sarà n = 12. ♥ Test su due varianze — var.test Desiderando sottoporre a verifica, sulla base delle realizzazioni di due campioni indi2 ) e Y ∼ N (µ , σ 2 ), l’ipotesi di omoschedapendenti tratti dalle v.c. X ∼ N (µX , σX Y Y 2 /σ 2 = 1, contro una delle alternative: sticità tra le due varianze, cioè H 0 : σX Y 2 H 1 : σX /σY2 3= 1 2 H 1 : σX /σY2 > 1 2 H 1 : σX /σY2 < 1 a parte la funzione (5.2.1) da noi creata ad hoc, possiamo ricorrere alla funzione var.test, la cui sintassi è: var.test(x,y,ratio=1,alternative="less","greater",two.sided", conf.level=0.95) con ovvio significato dei parametri che vi compaiono 12 . Esempio 5.3.6 La verifica di ipotesi sull’uguaglianza tra due valori medi, di cui all’Esempio 2 2 5.3.2, venne condotta presupponendo l’uguaglianza tra le due varianze σA e σB . Al fine di testare tale ipotesi, ricorrendo a var.test, abbiamo: > x<-c(30.0,29.9,29.2,29.8,30.8,29.8,30.4,28.9,30.5,29.7) > y<-c(28.7,28.6,29.4,29.7,29.9,30.2,28.7,29.4,30.4,29.7) > var.test(x,y) F test to compare two variances data: x and y F = 0.8185, num df = 9, denom df = 9, p-value = 0.7702 alternative hypothesis: true ratio of variances is not equal to 1 95 percent confidence interval: 0.203293 3.295101 sample estimates: ratio of variances 0.8184565 12 Cfr. Osservazione 5.3.2. 143 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Visto che il p-value associato al test è decisamente elevato (77%), siamo propensi ad accettare l’ipotesi nulla, nonostante il rapporto tra le varianze campionarie sia 0.81846. ♥ Osservazione 5.3.2 Si noti che la funzione var.test prevede l’opzione ratio=k, 2 /σ 2 = k contro le alternative: con k > 0, consente la verifica dell’ipotesi H 0 : σX Y 2 H 1 : σX /σY2 = k 2 H 1 : σX /σY2 > k 2 H 1 : σX /σY2 < k Test su più varianze — bartlett.test Se consideriamo k > 2 campioni casuali indipendenti, X j ∼ N (µ, σj2 ), ciascuno di cardinalità nj , con j = 1, 2, . . . , k, la verifica dell’ipotesi di omoschedasticità tra le varianze e cioè: H0 : σ12 = σ12 = . . . = σk2 H1 : ∃ (i, j)i$=j σi2 = σj2 può essere effettuata ricorrendo alla funzione bartlett.test. Dal momento che per ciascun campione la stima della varianza è: Sj2 = nj ! , -2 1 Xij − X̄j nj − 1 i=1 il test prende le mosse dalla constatazione che, per ciascun campione, il rapporto: 1 k k n−k A 1 ! 2 (n −1) Sj2 (nj − 1)/ Sj j V = n − k j=1 j=1 è uguale13 all’unità se e solo se tutte le varianze campionarie sono uguali tra loro, altrimenti esso assume valori maggiori dell’unità e aumenta via via con l’accrescersi delle differenze tra le Si2 . Perciò se sotto H0 il rapporto V tenderà ad assumere valori prossimi a 1, mentre sotto H1 esso assumerà valori tendenzialmente maggiori. Ora14 , sotto l’ipotesi nulla, una certa funzione del rapporto V , e precisamente: K2 = n−k ln V Q dove: Q=1+ k ! 1 1 1 − 3 (k − 1) j=1 nj − 1 n − k 13 Trattasi, a ben vedere, del rapproto tra la media aritmetica e la media geometrica delle varianze campionarie pesate con i rispettivi gradi di libertà. 14 Per approfondimenti Bartlett (1937) e, ad esempio, Gartside (1972). 144 E. D. Isaia, Linguaggio R e applicazioni statistiche descrive una v.c. la cui distribuzione può essere approssimata da quella di Chi-Quadro con ν = n − k gradi di libertà, viceversa sotto l’ipotesi alternativa essa descrive una v.c. che tende ad assumere valori sistematicamente maggiori. Scelto, quindi, un appropriato livello di significatività 1−α, si rifiuterà l’ipotesi di omogeneità delle varianze σi2 se e solo se la variabile test K 2 assume valori appartenenti alla regione critica [χ2n−k;1−α ; +∞]. Ritornando alla funzione bartlett.test, la sua sintassi è quanto mai semplice, infatti: bartlett.test(x, g) Tuttavia, in linea di massima, occorre osservare che: — x potrebbe essere un vettore ad elementi numerici corrispondenti alle n osservazioni campionarie; in tal caso è d’obbligo indicare l’oggetto g, di dimensione uguale a x, i cui elementi indicheranno il campione di appartenenza di ciascun elemento di x; — x potrebbe essere una lista i cui k elementi corrispondono alle osservazioni dei k campioni considerati; in tal caso è sufficiente il comando bartlett.test(x). Output della funzione sono la funzione test K 2 di Bartlett (statistic), i corrispondenti gradi di libertà (parameter), nonché il p − value (p.value). Esempio 5.3.7 Si immagini che tre macchinari, A, B e C producano uno stesso componente meccanico una cui caratteristica di vitale importanza è rappresentata dal diametro. Si supponga, altresı̀ che il diametro del componente meccanico possa essere descritto tramite una v.c. X ∼ N (µ, σi2 ), i = 1, 2, 3. Onde verificare se i tre macchinari mostrino una uguale variabilità nel corso della produzione, sono stati approntati altrettanti campioni casuali i quali hanno fornito i seguenti risultati (in mm): A 30.0 29.9 29.2 29.8 30.8 29.8 30.4 28.9 30.5 29.7 B 26.7 28.6 27.4 28.7 29.9 26.2 27.7 C 28.7 28.6 29.4 29.7 29.9 28.7 29.4 29.7 Definiti i tre oggetti a, b e c che contengono i singoli dati campionari, creiamo la lista abc che passeremo alla funzione bartlett.test; pertanto: 145 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > > > > > a<-c(30.0,29.9,29.2,29.8,30.8,29.8,30.4,28.9,30.5,29.7) b<-c(28.7,28.6,29.4,29.7,29.9,28.7,29.4,29.7) c<-c(26.7,28.6,27.4,28.7,29.9,26.2,27.7) abc<-list(a,b,c) bartlett.test(abc) Bartlett test for homogeneity of variances data: abc Bartlett’s K-squared = 6.7661, df = 2, p-value = 0.03394 Essendo il p−value associato alla funzione test decisamente piccolo, siamo propensi a rigettare l’ipotesi di uguaglianza tra tre le varianze. La figura (5.1) riporta i diagrammi a “scatola e baffi” dei valori campionari del diametro dei componenti meccanici, ed è stata ottenuta tramite il comando: 29 28 27 Diametro (mm) 30 > boxplot(abc,main="",xlab="Macchinari",ylab="Diametro (mm)", col="lightgray",names=c("A","B","C")) A B C Macchinari Figura 5.1: Diagrammi a “scatola e baffi” — Esempio 5.3.7 Osserviamo che avremmo effettuare il test organizzando i dati campionari nel seguente modo: 146 E. D. Isaia, Linguaggio R e applicazioni statistiche > dati<-c(30.0,29.9,29.2,29.8,30.8,29.8,30.4,28.9,30.5,29.7,28.7,28.6, 29.4,29.7,29.9,28.7,29.4,29.7,26.7,28.6,27.4,28.7,29.9,26.2,27.7) > gruppi<-c(rep(1,10),rep(2,8),rep(3,7)) > bartlett.test(dati,gruppi) Bartlett test for homogeneity of variances data: dati and gruppi Bartlett’s K-squared = 6.7661, df = 2, p-value = 0.03394 ottenendo, coerentemente, lo stesso risultato. ♥ Il test di Bartlett trova applicazione sopratutto nell’ambito dell’Analisi delal Varianza (ANOVA) e in generale nello studio dei modelii lineari. Test esatto su una proporzione — binom.test Ricorrendo alla funzione binom.test possiamo sottoporre a verifica l’ipotesi statistica H0 : π = π0 contro una delle alternative: H1 : π 3= π0 H1 : π < π0 H1 : π > π0 ( sulla base15 delle realizzazioni della funzione test T = n −1 ni=1 Xi , la quale, sotto l’ipotesi nulla, ha distribuzione binomiale di parametri n, π 0 . Senza entrare in dettagli, la sintassi per accedere a tale funzione è: binom.test(x, n, p = 0.5, alternative = c("two.sided", "less", "greater"), conf.level = 0.95) dove x indica il numero di Successi osservati in n prove indipendenti di un esperimento casuale. L’utente, come sempre, può specificare l’ipotesi alternativa nonché il livello di confidenza richiesto. Si osservi che la situazione di default prevede π 0 = 0.5. Esempio 5.3.8 Da precedenti indagini la proporzione di neonate affette da displasia all’anca era approssimativamente pari al 3%. In base ad una recente indagine condotta su un campione casuale di 120 neonate solo tre sono risultate affette da displasia all’anca. Possiamo affermare la proporzione sia dinimuita? Il sistema di ipotesi a conflitto risulta: + H0 : π = π0 = 0.03 H1 : π < π0 Ricorrendo alla funzione binom.test, abbiamo: 15 Si ricordi quanto detto a tal proposito alla fine del paragrafo5.1 e riassunto dalla Funzione 5.1.4 e dall’Esempio 5.1.5. 147 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > binom.test(3,120,p=0.03,alternative="less",conf.level=0.95) Exact binomial test data: 3 and 120 number of successes = 3, number of trials = 120, p-value = 0.5133 alternative hypothesis: true probability of success is less than 0.03 95 percent confidence interval: 0.00000000 0.06333852 sample estimates: probability of success 0.025 Essendo decisamente elevato il p−value associato al test, siamo propensi ad accettare l’ipotesi nulla e concludere quindi che la proporzione di neonate affette da displasia all’anca non sia mutata nel corso del tempo. ♥ Osservazione 5.3.3 Qualora si desideri effettuare una verifica di ipotesi sulla differenza tra due proporzioni, sulla base di due campioni indipendenti di numerosità elevata, si può ricorrere alla funzione t.test. Esempio 5.3.9 Da un indagine condotta su un campione casuale di 200 individui adulti, di cui 100 di sesso femminile e i restanti di sesso maschile, risulta che il 75% dei maschi fuma, mentre le fumatrici sono il 55%. Si desidera sottoporre a verifica il seguente sistema di ipotesi statistiche: + H0 : πmaschi = πf emmine H1 : πmaschi > πf emmine Ricorrendo alla funzione t.test, occorre dapprima creare i due vettori, maschi e femmine, delle osservazioni campionarie; tali vettori conterranno 100 elementi con opportuna alternanza di 0 (non fumatore/fumatrice) e di 1 (fumatore/fumatrice). Ciò premessso: > maschi<-c(rep(1,75),rep(0,25)) > femmine<-c(rep(1,55),rep(0,45)) > t.test(maschi,femmine, alternative="two.sided", mu=0, paired = FALSE, var.equal = TRUE, conf.level = 0.95) Two Sample t-test data: maschi and femmine t = 3.0172, df = 198, p-value = 0.002886 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: 0.06928128 0.33071872 sample estimates: mean of x mean of y 0.75 0.55 148 E. D. Isaia, Linguaggio R e applicazioni statistiche Essendo decisamente piccolo il p − value associato al test, siamo propensi a rigettare l’ipotesi di uguaglianza tra le due proporzioni. ♥ Test sul coefficiente di correlazione lineare — cor.test Desiderando verificare se due due campioni casuali, X e Y di egual cardinalità n, 2 ) e Y ∼ N (µ , σ 2 ) linearmente indiprovengono da altrettante v.c. X ∼ N (µ X , σX Y Y 16 pendenti , possiamo effettuare un test teso a verificare se il coefficiente di correlazione lineare ρ tra le v.c. X e Y possa ritenersi nullo oppure no. In sostanza, si tratta di sottoporre a verifica le seguenti ipotesi statistiche: + H 0 : ρ = ρ0 = 0 H1 : ρ 3= ρ0 = 0 In tali situazioni abitualmente si ricorre alla funzione test corrispondente al coefficiente di correlazione campionario r del Pearson, definito come: r= SX,Y SX SY o, meglio, alla sua trasformata: r √ n−2 1 − r2 che sotto H0 viene a possedere distribuzione t di Student con ν = n−2 gradi di libertà. Sotto tali condizioni si possono applicare le tecniche generali esposte al paragrafo (5.2). In R possiamo procedere ad un siffatto test di ipotesi ricorrendo alla particolare funzione cor.test, la quale, bene qui sottolinearlo, prevede anche altri tipi di test non parametrici. Nel seguito, tuttavia, considereremo unicamente il caso di test parametrico basato sul rapporto di correlazione del Pearson 17 . Sotto tale profilo, la sintassi della funzione in esame si riduce a: cor.test(x, y) dove, ovviamente, x e y sono due vettori ad elementi numerici e di egual dimensione, cioè tali che length(x)=length(y). Output essenziali sono la funzione test r di Pearson (statistic), i corrispondenti gradi di libertà (parameter), nonché il p − value (p.value). 16 Il che equivale a chiedersi se essi siano estratti da una v.c. Normale bivariata a componenti linearmente indipendenti. 17 Che d’altronde corrisponde alla situazione di default. 149 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Esempio 5.3.10 Si immagini di avere rilevato, su un campione di n = 10 autovetture mediopiccole ad alimentazione a benzina e trazione anteriore, la potenza espressa in CV-Din e la velocità massima dichiarata espressa in km/h, ottenendo i seguenti risultati: Potenza (CV-Din) 45 54 45 50 60 65 70 54 70 60 Velocità (km/h) 135 145 137 140 150 140 160 145 150 150 Organizzate, per comodità, le osservazioni campionarie nel data frame dati, la figura (5.2) porge alcune informazioni circa la dipendenza tra le variabili in esame. 140 145 150 155 160 70 135 55 45 50 0.8 60 65 CV.Din 135 145 155 Vel.max 45 50 55 60 65 70 Figura 5.2: Correlazione tra velocità massima e potenza — Esempio 5.3.10 I comandi atti allo scopo sono: 150 E. D. Isaia, Linguaggio R e applicazioni statistiche > > > > x<-cbind(c(45, 54, 45, 50, 60, 65, 70, 54, 70, 60)) y<-cbind(c(135, 145, 137, 140, 150, 140, 160, 145, 150, 150)) dati<-data.frame(CV.Din=x,Vel.max=y) pairs(dati,panel=panel.fit,diag.panel=panel.hist, upper.panel=panel.cor) Desiderando sottoporre a verifica le seguenti ipotesi statistiche: + H0 : ρ = ρ 0 = 0 H1 : ρ #= ρ0 = 0 ricorrendo alla funzione cor.test avremo: > attach(dati) > cor.test(CV.Din,Vel.max) Pearson’s product-moment correlation data: CV.Din and Vel.max t = 3.6893, df = 8, p-value = 0.006137 alternative hypothesis: true correlation is not equal to 0 sample estimates: cor 0.7936084 > detach(dati) ed evidentemente saremo portati al rigetto di H0 . ♥ È bene notare che a volte si è interessati a verificare, sulla base dei valori campionari osservati, l’ipotesi che il coefficiente di correlazione della popolazione sia uguale ad un valore specificato non nullo, poniamo ρ 0 3= 0. In altri termini si desidera sottoporre a vericfica le le ipotesi statistiche: + H0 : ρ = ρ0 3= 0 H1 : ρ 3= ρ0 In tal caso, si può ricorre alla funzione test: z= √ n−3 + 0.5 ln ) * ) 1+r 1 + ρ0 − 0.5 ln 1−r 1 − ρ0 *D la quale sotto H0 tende a distribuirsi, perlomeno asintoticamente, secondo una N (0, 1). Se tale è il caso, allora possiamo pensare di implementare una funzione ad hoc che potrebbe presentarsi come: 151 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 1 2 3 4 5 6 7 8 9 Funzione 5.3.1 rho.test<-function(rho,x,y) { covar(x,y,print=F) r<-rxy.out n<-length(!is.na(x)) z<-(sqrt(n-3))*(0.5*log((r+1)/(1-r))-0.5*log((rho+1)/(1-rho))) pval<-2*pnorm(-abs(z)) cat("r =",r,"rho =",rho,"p-value=",pval,"\n") } Test di indipendenza chisq.test Dedichiamo questo paragrafo alla presentazione di un particolare test di ipotesi statistiche che si differenzia dai precedenti per il fatto che non viene ipotizzata alcuna forma per la densità della v.c. da cui viene tratto il campione casuale. Tali test vengono abitualmente detti test “non parametrici” Si immagini che due caratteri possano essere descritti in modo congiunto mediante la v.c. bivariata (X, Y ); il problema che tenteremo di risolvere è verificare, sulla base delle realizzazioni di due campioni di ugual numerosità X e Y tratti da (X, Y ), se la v.c. in esame è a componenti stocasticamente indipendenti, in simboli X ⊥ Y . In sostanza si tratta di verificare il seguente sistema di ipotesi statistiche: + H0 : X ⊥ Y H1 : X 3⊥ Y (5.12) Abitualmente le realizzazioni campionarie x e y vengono organizzate in una tabella a doppia entrata di dimensione r × s, dove r indica il numero delle modalità di x e s il numero delle modalità di y, che riporta il numero delle unità campionarie che presentano al contempo modalità i di X e j di Y , cioè le frequenze congiunte n ij , con i = 1, 2, . . . , r e j = 1, 2, . . . , s Al fine della verifica del sistema di ipotesi (5.12) si ricorre alla funzione test, dovuta al Pearson: X2 = r ! s ! (nij − n̂ij )2 i=1 j=1 (5.13) n̂2ij dove n̂ij rappresentano le frequenze congiunte che ci si attenderebbe osservare nel caso di indipendenza stocastica18 tra le componenti la v.c. doppia (X, Y ). 18 E cioè, com’è facile accertare: n̂ij = proposito si veda anche l’Esempio 3.2.3. (r i=1 nij 152 (s j=1 nij / (r i=1 (s j=1 nij = n.j ni. /n. A tal E. D. Isaia, Linguaggio R e applicazioni statistiche Sotto H0 , la funzione test (5.13) è distribuita approssimativamente socondo una ChiQuadro con (r − 1) (s − 1) gradi di libertà. Il test tenderà, dunque, ad accettare l’ipotesi nulla se e solo se il valore osservato della (5.13) è non maggiore di q 1−α , dove, coerentemente con quanto precedentemente esposto: P [X 2 ≤ q1−α ; H0 ] ≈ 1 − α Al fine della verifica del sistema di ipotesi (5.12), organizzate le frequenze osservate in una martrice, diciamo x, di dimensione r × s, possiamo ricorrere alla funzione chisq.test ed impartire il comando: chisq.test(x, correct = FALSE) Senza entrare in dettagli, osserviamo che ponendo correct=TRUE, che rappresenta la situazione di default, la funzione provvede in modo automatico ad applicare correzione dello Yates, cioè ricorre alla funzione test: X2 = r ! s ! (nij − n̂ij − 0.5)2 i=1 j=1 n̂2ij qualora si operi su campioni poco numerosi. Esempio 5.3.11 Un campione casuale di 200 individui adulti è stato classificato in base al sesso e l’occupazione, ottenendo la seguente ditribuzione congiunta di frequenze: Occupazione ↓ Sesso → Occupato Disoccupato Maschio 100 20 Femmina 50 30 Al fine di verificare se vi sia una relazione di dipendeza tra il sesso e l’occupazione, ricorriamo al test chisq.test(): > x<-matrix(c(100,20,50,30),2,2) > chisq.test(x,correct=FALSE) Pearson’s Chi-squared test data: x X-squared = 11.1111, df = 1, p-value = 0.0008581 Dal momento che il p−value associato al test è decisamente piccolo, saremo portati a rigettare l’ipotesi di indipendenza tra i caratteri considerati. ♥ Esempio 5.3.12 Un dado viene lanciato 1000 volte dando luogo alla seguente distribuzione empirica: 153 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Punteggi Frequenze xi ni 1 142 2 186 3 157 4 177 5 176 6 162 Possiamo pensare che il dado sia equilibrato? Il problema può essere risolto confrontando la distribuzione delle frequenze empiriche con la distribuzione delle frequenze che ci aspetteremo di osservare qualora il dado fosse regolare, cioè sotto l’ipotesi H0 : ni = 1000/6 = 166.6667. Ricorriamo, pertanto, ad una verifica di ipotesi basata sulla funzione test (5.13). > dadi<-sample(c(1:6), 1000, replace = TRUE) > table(dadi) 1 2 3 4 5 6 142 186 157 177 176 162 > chisq.test(table(dadi)) Chi-squared test for given probabilities data: table(dadi) X-squared = 7.748, df = 5, p-value = 0.1707 In sostanza possiamo accettare l’ipotesi che il dado sia equilibrato. Si osservi che, se è il caso, possiamo passare in modo diretto i valori delle frequenze teoriche alla funzione chisq.test con l’opzione p=(...), che per default è rep(1/length(x), length(x)). ♥ 154 Capitolo 6 Alcune note sui modelli lineari Nel seguito vedremo come sia possibile affrontare e risolvere in R alcuni problemi che concernono modelli statistici lineari e, in particolare, ci occuperemo, seppur a grandi linee data la vastità dell’argomento, dell’analisi della regressione e dell’analisi della varianza. Diciamo subito che non ci occuperemo della costruzione di routine di caclolo ad hoc, ma piuttosto illustreremo come sfruttare le principali funzioni presenti in R e raccolte nella libreria base che in linea di massima si basano sui comandi lm, acronimo di “linear model”, e aov, acronimo di “analysis of variance”. 6.1 La regressione lineare semplice: il modello teorico Se consideriamo una v.c. doppia (X, Y ) a componenti non indipendenti, è chiaro che la conoscenza del valore assunto da X viene a modificare il nostro grado di incertezza circa la realizzazione di Y ; in generale tale incertezza viene a diminuire, dal momento che la distribuzione di Y condizionata all’evento X = x viene a possedere in media una varianza più piccola1 della varianza di Y . In tutte quelle situazioni in cui si può ipotizzare che un fenomeno, descrivibile mediante la v.c. X abitualmente detta variabile esplicativa o predittiva, possa essere impiegato per “spiegare” quello descritto dalla v.c. Y , detta variabile variabile risposta, si è portati a ricercare un legame funzionale del tipo Y ∗ = f (X) che possa offrire una previsione per Y tramite X; in particolare si tratta di individuare una funzione f tale che IE[Y − f (X)] = 0 ed al contempo sia il più vicino possibile ad Y ad esempio in media quadratica, ovvero minimizzi IE[(Y − f (X)) 2 ]. Dalla teoria è noto che tali condizioni sono soddisfatte ponendo f (X) = IE[Y |X]. Tale funzione, che ad una determinazione x di X associa IE[(Y |X = x], viene detta funzione di regressione di Y rispetto a X e, fissato un sistema di riferimento ortogonale cartesiano, il corrispondente grafico viene indicato quale curva di regressione di Y 1 Il fatto che IE[V ar(Y |X)] ≤ V ar[Y ] discende dal teorema della Scissione della Varianza Totale. Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 rispetto a X. La bontà dell’approssimazione di Y mediante IE[Y |X], lo ricordiamo, viene misurata attraverso il rapporto di correlazione di Pearson, definto come: ηY2 |X = V ar[IE[Y |X]] V ar[Y ] Alla luce di tali considerazioni, possiamo, dunque, porre: Y = IE[Y |X] + - (6.1) dove - = Y − IE[Y |X] rappresenta il residuo della regressione o componente di disturbo; più in particolare si può dimostrare che trattasi di una v.c. non correlata nè con X nè con IE[Y |X], per la quale si ha IE[-] = 0 e V ar[-] = V ar[Y ] (1 − η Y2 |X ). 6.2 La regressione lineare Sorge naturale, a questo punto, il problema della scelta del legame funzionale f (X); a tal proposito, perlomeno dal punto di vista applicativo, notevole importanza 2 riveste il caso in cui per esso si scelga un polinomio di primo grado, cioè si ponga: IE[Y |X] = α + β X sı̀ che la (6.1) diviene: Y = α+βX +- (6.2) Sotto tale ipotesi di lavoro, è facile dedurre: α = IE[Y ] − β IE[X] β= Cov(X, Y ) σY =ρ V ar[X] σX Ciò premesso, la funzione di regressione di Y rispetto a X viene ad assumere la forma: σY Y = IE[Y ] + ρ (X − IE[X]) + (6.3) σX e viene abitualmente detta retta di regressione di Y rispetto a X. Se si considera la varianza di ambo i membri della (6.3): V ar[Y ] = ρ 2 V ar[Y ] +V ar[-], segue: V ar[-] = V ar[Y ] (1 − ρ2 ) (6.4) a riprova che nel caso di regressione lineare: η Y2 |X = ρ2 . 2 Si osservi che qualora la v.c. doppia (X, Y ) possegga distribuzione normale bivariata, allora −2 IE[Y |X = µY + σXY σX (X − µX ), dove σXY = Cov(X, Y ). 156 E. D. Isaia, Linguaggio R e applicazioni statistiche 6.2.1 Stima della retta di regressione in base ai valori campionari Supponendo ora vera l’ipoesi IE[Y |X] = α + β X, e dispondendo di un campione casuale (X, Y) = ((X1 , Y1 ), (X2 , Y2 ), . . . , (Xn , Yn )) di dimensione n > 2 tratto dalla v.c. bivariata (X, Y ), il problema che ci si pone, perlomeno dal punto di vista statistico, è quello della stima dei parametri α e β nonché della varianza del termine di disturbo. Data la n-pla campionaria (xi , yi )i=1,2,...,n , si tratterà, dunque, di individuare i parametri della retta, di equazione poniamo ŷ = a + b x, interpolante la “nuvola di punti” di coordinate (xi , yi ); il ricorso al metodo dei minimi quadrati comporta, com’è noto, la minimizzazione della funzione: F (a, b) = n ! i=1 (yi − ŷi )2 = n ! i=1 (yi − a − b xi )2 ∂F La condizione ∂∂ F a = ∂ b = 0, porge il sistema delle “equazioni normali”: (n i=1 (yi − a − b xi ) = 0 (n i=1 (yi (6.5) − a − b x i ) xi = 0 da cui facilmente: b= !n i=1 (yi − ȳ) (xi − x̄) !n (xi − x̄) 2 i=1 = Cov(x, y) sy =r 2 sx sx a = ȳ − b x̄ (6.6) (6.7) s e quindi ŷ = ȳ + r sy (x − x̄) viene a rappresentare la versione empirica della retta di x regressione posta in (6.3). Chiaramente, al variare della n-pla campionaria (x i , yi ), le grandezze x̄, ȳ, s2x , s2y , r, ŷ, a e b altro non sono che realizzazioni di altrettante v.c.; queste ultime due in particolare sono determinazioni, rispettivamente, degli stimatori A e B definiti: A = Ȳ − B X̄ B= !n i=1 (6.8) (Yi − Ȳ ) (Xi − X̄) !n i=1 (6.9) (Xi − X̄)2 157 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Desiderando procedere, si può dimostrare che trattasi 3 di stimatori corretti, nel senso che IE[A] = α e IE[B] = β, con varianza4 , fissate le realizzazioni xi delle n v.c. Xi : V ar [B] = !n i=1 σ2 (6.10) (xi − x̄)2 1 σ2 x̄2 = V ar [A] = σ 2 + !n + x̄2 V ar [B] n n (xi − x̄)2 (6.11) i=1 Senza voler verificare la veridicità di tale affermazione, ci limitiamo ad osservare che le dimostrazioni partono dalla semplice considerazione che il valore atteso del valore atteso di uno stimatore condizionatamente alle realizzazioni x i delle n v.c. Xi corrisponde al valor medio dello stimatore stesso. Dal momento poi che IE[Y |X = x] = α + β x, possiamo affermare che ŷ = a + b x è una stima corretta di α + β x. Quanto alla varianza dello stimatore Ŷ , avremo: E F (x − x̄) 1 V ar Ŷ = σ 2 + !n n (xi − x̄)2 2 (6.12) i=1 È bene osservare che il parametro incognito σ 2 , che compare in modo esplicito nelle (6.10), (6.11) e (6.12), altro non è che la varianza delle Y i , date le realizzazioni xi delle v.c. Xi , cioè: σ 2 = V ar[Yi |Xi = xi ] = V ar[-] Quale sua stima sorge spontaneo ricorrere alla varianza campionaria dei residui: Se2 = !n i=1 (Yi − Ŷi )2 n−1 tuttavia tale stimatore non risulta corretto. Infatti si può dimostrare che: n ! i=1 (Yi − Ŷi )2 = σ 2 n ! i=1 (1 − hi ) = σ 2 (n − n ! i=1 hi ) = σ 2 (n − 2) (6.13) dove, per X = xi fissato: hi = 3 !n i=1 n x2i − 2 xi !n i=1 !n i=1 ! n x2i − ( xi + n x2i i=1 xi )2 (6.14) In verità essi risultano stimatori corretti a varianza minima. Per inciso tali stimatori non risultano tra loro stocasticamente inipendenti. 4 E ciò indipendentemente dalla legge di distribuzione delle v.c. coinvolte. 158 E. D. Isaia, Linguaggio R e applicazioni statistiche e quindi stimatore corretto di σ 2 risulta: S2 = 6.2.2 !n i=1 (Yi − Ŷi )2 (6.15) n−2 Verifiche di ipotesi circa i parametri della retta di regressione I risultati sin qui proposti prendevano le mosse dalla semplice considerazione che la funzione di regressione di Y rispetto a X fosse esprimibile mediante un polinomio di primo grado, cioè IE[Y |X] = α + β X; in sostanza senza fare alcuna ipotesi circa le distribuzioni delle v.c. coinvolte. , Ipotizzando, ora, che la v.c. - abbia distribuzione N 0, σ 2 , allora la v.c. Y |X = x , segue una distribuzione N α + β x, σ 2 e pertanto: 1 x̄2 ) A ∼ N β, σ 2 ( + !n n (xi − x̄)2 i=1 B ∼ N β, !n σ2 i=1 (xi − x̄)2 Ŷ ∼ N α + β x, σ 2 ( 1 (x − x̄) + !n ) n (xi − x̄)2 2 i=1 (n − 2) S 2 viene a possedere distribuzione χ2n−2 ; inoltre, si dimostra σ2 che essa è indipendente da Ȳ , A e B. Sotto tali ipotesi, dunque, le v.c. (statistiche test): mentre la v.c. Ta = A−α G H H1 S I + !n n Tb = i=1 (xi − x̄)2 B−β G H H S I !n i=1 (6.16) x̄2 1 = (B − β) SX √ n−1 S (6.17) (xi − x̄)2 vengono entrambe a possedere distribuzione t di Student con n − 2 gradi di libertà. 159 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Tali considerazioni consentono di costruire di intervalli di confidenza o effettuare verifiche di ipotesi sui parametri del modello. A tal proposito, le ipotesi che abitualmente vengono poste a confronto sono del tipo: + + H0 : α = 0 H1 : α 3= 0 (6.18) H0 : β = 0 H1 : β 3= 0 (6.19) Per completezza, presentiamo un test che, basandosi sull’analisi della varianza della regressione, offre indicazioni circa la la bontà di adattamento dei dati alla retta di regressione. Dal momento che la devianza (totale) di Y può essere scissa come: n ! i=1 J (Yi − Ȳ )2 = abbiamo: KL M SST ot n ! i=1 J (Yi − Ŷ )2 + KL SSE M n ! i=1 J (Ŷi − Ȳ )2 KL SSR (6.20) M — per cose ormai note: n ! i=1 (Yi − Ŷ )2 σ2 = SSE ∼ χ2n−2 σ2 — se, e solo se, è vera l’ipotesi H 0 : β = 0: n ! i=1 (Yi − Ȳ )2 σ 2 = SST ot ∼ χ2n−1 2 σ ed inoltre5 : n ! i=1 5 (Ŷi − Ȳ )2 σ 2 = SSR = σ2 n ! i=1 Si ricordi che per le ipotesi di lavoro σ una N (0, 1). −2 B (Xi − X̄)2 σ 2 (n i=1 160 ∼ χ21 (B − β) (Xi − X̄)2 ∼ χ21 in quanto quadrato di E. D. Isaia, Linguaggio R e applicazioni statistiche ( ( n n 2 2 Osservando infine, l’indipendenza tra le v.c. i=1 (Yi − Ŷ ) e i=1 (Ŷi − Ȳ ) , vera l’ipotesi H0 : β = 0, il rapporto tra le devianze SS R e SSE ciascuna delle quali divisa per i rispettivi gradi di libertà, cioè: (n − 2) n ! i=1 n ! i=1 (Ŷi − Ȳ )2 (Yi − Ŷ ) 2 = (n − 2) SSR SSE (6.21) viene a possedere6 distribuzione F di Snedecor con un grado di libertà a numeratore ed n − 2 gradi di libertà a denominatore. L’adeguatezza del modello di regressione può pertanto essere verificata in base al p − value associato al valore di F sperimentale. Valori di F sperimentale prossimi allo zero possono essere spiegati da elevati valori di σ 2 oppure possono suggerire che il modello non spieghi in modo esaustivo il comportamento della variabile risposta. Osservazione 6.2.1 Nel caso di modello di regressione lineare, il test di adeguatezza appena illustrato viene a corrispondere al test circa il coefficiente di correlazione lineare: + H0 : ρ = 0 H1 : ρ 3= 0 (6.22) Infatti, nel caso in esame, se osserviamo che: 4 6 n−1 1 !n (Yi − Ŷ )2 = 1 − R2 SY2 i=1 n n il rapporto posto in (6.21) può essere riscritto come: (n − 2) R2 1 − R2 Tale v.c., sotto l’ipotesi nulla ρ = 0 viene a possedere distribuzione t di Student con (n − 2) gadi di libertà; ora, per cose note, risulta (T n−2 )2 = F (1; n − 2). 6 In virtù del Teorema di Cochran. 161 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 6.2.3 Alcune considerazioni circa la previsione Si immagini di volere prevedere, tramite il modello di regressione, il valore della variabile risposta Y in corrispondenza ad un’ulteriore determinazione di interesse x 0 di X non osservata. Una sua stima puntuale, Ŷ0 , la si ottiene semplicemente ponendo Ŷ0 = a + b x0 , ma per cose ovvie essa di per sé è di scarso interesse. Nel seguito si vedrà come sia possibile pervenire alla costruzione di un “intervallo di previsione” per per la stima stessa. Da quanto esposto al paragrafo precedente, le v.c. Ŷ0 e Y |X = x0 posseggono distribuzione Normale entrambe con valor medio α + β x 0 e varianza rispettivamente: (x0 − x̄)2 1 V ar[Ŷ0 ] = σ 2 + !n n (xi − x̄)2 i=1 e: V ar[Y |X = x0 ] = σ 2 Ora, mentre Ŷ0 dipende dalla n-pla di valori osservati x 1 , x2 , . . . , xn , Y |X = x0 dipende unicamente dal valore “futuro” x0 ; quindi, supponendo indipendenti le realizzazioni della v.c. disturbo -, possiamo affermare l’indipendenza tra le v.c. Ŷ0 e Y |X = x0 . Segue, dunque, che la v.c. (Y |X = x0 ) − Ŷ0 possiede distribuzione Normale con valor medio nullo e varianza: (x0 − x̄)2 1 V ar[(Y |X = x0 ) − Ŷ0 ] = σ 2 1 + + !n n (xi − x̄)2 i=1 Si osservi come la varianza dell’errore di previsione dipende da due fattori e precisamente: dalla varianza intrinseca della v.c. Y |X = x 0 , cioè σ 2 , e dalla variabilità indotta dalle stime dei parametri α e β del modello di regressione, che contrariamente alla prima può essere ridotta aumentando la dimensione del campione. Da quanto sopra, la v.c. standardizzata: (Y |X = x0 ) − Ŷ0 G H H 1 (x0 − x̄)2 S I1 + + !n n i=1 (xi − x̄)2 viene a possedere distribuzione t di Student con n − 2 gradi di libertà, per cui l’intervallo di previsione per la stima ŷ 0 , sarà: G H H 1 (x0 − x̄)2 ŷ0 ± n−2 t1−α/2 s I1 + + !n n i=1 (xi − x̄)2 162 (6.23) E. D. Isaia, Linguaggio R e applicazioni statistiche Si noti come l’intervallo di previsione sia più ampio, a parità di α, del corrispondente intervallo di confidenza per ŷ i : G H H1 (xi − x̄)2 ŷi ± n−2 t1−α/2 s I + !n n 6.2.4 i=1 (xi − x̄)2 (6.24) Alcune considerazioni sull’analisi dei residui L’analisi dei residui yi − ŷi riveste un ruolo non secondario in quanto essa può essere di aiuto per (a) la verifica di alcune ipotesi di base, quali la linearità, l’omoshedasticità, la normalità degli errori stessi, ...; (b) l’individuazione di eventuali valori anomali e/o di osservazioni che hanno un peso determinante nel processo di stima del modello di regressione. Generalmente e sicuramente in prima battuta, tale analisi viene condotta per via empirica ricorrendo ai seguenti diagrammi a dispersione: — residui yi − ŷi in funzione dei valori teorici ŷ i ; — residui standardizzati7 s yi − ŷi > 1 − hi in funzione dei valori teorici ŷ i ; — quantili empirici dei residui in funzione dei quantili teorici di una N (0, 1). i quali non devono lasciare trasparire alcuna tendenza. Quanto al precedente punto (b), oltre all’analisi grafica testé proposta, può essere di aiuto lo studio delle cosidette “distanze di Cook” le quali (Cook, Weisberg 1982) consentono di individuare l’influenza esercitata sulla stima del coefficiente di regressione β da ciascuna osservazione xi . Senza entrare in dettagli, osserviamo che, per ciascun xi , esse possono essere definite: di = 2 yi − ŷi s (1 − hi ) 32 hi 2 (6.25) Dal punto di vista pratico, un valore di di prossimo o maggiore dell’unità indica un’influenza anormale sulla stima. Si tenga presente, per concludere, che ad un residuo elevato può corrispondere un valore anomalo, tuttavia un’osservazione anomala può presentare un residuo piccolo o adirittura nullo. Per approfondimenti sull’argomento si confronti, ad esempio, il testo di Belsley, Kuh e Welsch (1980). 7 A tal proposito si ricordi la (6.13) e la (6.14). 163 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 6.3 La regressione lineare semplice in R Desiderando effettuare un’analisi della regressione lineare in R, cosı̀ come delineata nei paragrafi precedenti, si può ricorrere alla funzione lm(), il cui output è un oggetto con struttura di lista, i cui elementi possono essere visualizzati e/o acquisiti per successive elaboarazioni nel corso di una seduta di lavoro. Dal momento che trattasi di una funzione assai flessibile e ricca di una vasta gamma di opzioni, nel seguito introdurremo dapprima i comandi di base, rimandando ai paragrafi successivi la descrizione di alcune opzioni di interesse. 6.3.1 La funzione lm(): definizione del modello di regressione Raccolte le osservazioni campionarie (x i , yi )i=1,2,...,n nei due oggetti x e y, il primo passo consiste nella definizione del modello di regressione; per il modello lineare posto in (6.2), è sufficiente il comando: > lm(formula = y~x) o più semplicemente: > lm(y~x) In seguito a tale comando, R visualizza, per default, le stime dei parametri α e β del modello e ciò in accordo alla (6.7) e (6.6). Esempio 6.3.1 Com’è noto la concentrazione di ozono (Y ), espressa in mg per m 3 , nelle grandi aree metropolitane dipende, oltre che da altri fattori, in gran misura dalla temperatura ambientale (X). I dati che seguono riguardano un campione di n = 26 osservazioni, tratte casualmente da una banca dati delle misurazioni registrate da una centralina di controllo in altrettanti giorni feriali dei mesi di giugno e luglio alle ore 12.00 nei pressi di un’importante crocevia: xi yi xi yi 22 9 28 28 24 23 29 35 25 21 30 44 25 22 30 73 26 31 30 78 26 44 31 66 26 45 32 89 26 59 32 110 27 9 32 122 27 39 34 85 27 65 34 118 27 128 36 76 28 16 36 84 Posto che la relazione che lega la concentrazione di ozono e la temperatura ambientale possa essere riassumibile dal modello lineare Y = α + β X, la stima dei parametri ci viene offerta dalle istruzioni: > x<-c(22,24,25,25,26,26,26,26,27,27,27,27,28, 28,29,30,30,30,31,32,32,32,34,34,36,36) > y<-c(9,23,21,22,31,44,45,59,9,39,65,128,16, 164 E. D. Isaia, Linguaggio R e applicazioni statistiche 28,35,44,73,78,66,89,110,122,85,118,76,84) > lm(y~x) Call: lm(formula = y ~ x) Coefficients: (Intercept) -131.332 x 6.578 sı̀ che la stima della retta di regressione diviene ŷi = −131.332 + 6.578 xi . ♥ A proposito della fase di definizione del modello di regressione lineare, è bene tenere a mente che, posti x e y gli oggetti contenenti le n osservazioni campionarie, le istruzioni: > lm(y~x) > lm(y~+1+x) sono equivalenti e definiscono entrambe il modello di regressione Y = α+ β X, mentre le istruzioni: > lm(y~0+x) > lm(y~-1+x) > lm(y~x-1) definiscono il modello Y = β X, privo quindi della costante α. Concludiamo osservando che, anche se non necessario, è tuttavia buona norma: — strutturare le osservazioni campionarie sottoforma di data frame e impartire successivamente il comando lm(formula=...,data=data.frame); in tal caso, i dati sono disponibili senza dover ricorrere all’istruzione attach(); — introdurre un nuovo oggetto, con struttura di formula, che servirà appunto a definire il modello di regresione lineare di interesse. Ad esempio valgano le istruzioni: > x<-c(...) > y<-c(...) > dati<-data.frame(Risposta=y,Predittore=x) > formulayx<-as.formula(paste(names(dati)[1],"~",names(dati)[2])) > formulayx Risposta ~ Predittore 165 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — definire un nuovo oggetto che conterrà sia il modello che i risultati dell’analisi di regressione richiesta; a tal fine sarà sufficiente, ad esempio, l’istruzione modello.analisi.1<-lm(formula=...,data=...). L’espressione del modello di regressione in esame può essere visualizzata in qualsiasi istante con l’istruzione formula(modello.analisi.1) Esempio 6.3.2 Con riferimento alla situazione di cui all’Esempio 6.3.1, risultati del tutto equivalenti, ma in forma più ordinata, si ottengono ricorrendo alle seguenti istruzioni: > x<-c(22,24,25,25,26,26,26,26,27,27,27,27,28, 28,29,30,30,30,31,32,32,32,34,34,36,36) > y<-c(9,23,21,22,31,44,45,59,9,39,65,128,16, 28,35,44,73,78,66,89,110,122,85,118,76,84) > (ozono.yx<-data.frame(Temperatura=x,Risposta=y)) Temperatura Risposta 1 22 9 2 24 23 3 25 21 ... ... ... 24 34 118 25 36 76 26 36 84 > (formula.es1<-as.formula(paste(names(ozono.yx)[2],"~",names(ozono.yx)[1]))) Risposta ~ Temperatura > modello.es1<-lm(formula.es1,data=ozono.yx) > modello.es1 Call: lm(formula = formula.es1, data = ozono.yx) Coefficients: (Intercept) Temperatura -131.332 6.578 > formula(modello.es1) Risposta ~ Temperatura Va da sé che, alla luce di quanto sopra, avremmo potuto definire: > formula.es1<-as.formula(paste(names(ozono.yx)[2],"~1+",names(ozono.yx)[1])) > formula.es1 Risposta ~ 1 + Temperatura ottenendo, coerentemente, gli stessi risultati. 166 ♥ E. D. Isaia, Linguaggio R e applicazioni statistiche 6.3.2 La funzione lm(): oggetti creati in modo automatico Come già si è detto, l’output completo della funzione lm() consiste in un oggetto con struttura di lista, i cui elementi possono essere elencati mediante il comando names(lm(formula=...,...)), il quale porge, appunto: > names(lm(formula=...,...)) [1] "coefficients" "residuals" [4] "rank" "fitted.values" [7] "qr" "df.residual" [10] "call" "terms" "effects" "assign" "xlevels" "model" Ciascun elemento di tale lista può essere visualizzato o acquisito per successive elaborazioni tramite il comando lm(...)$nome.elemento o, in modo del tutto equivalente, con nome.elemento(lm(...)); ad esempio: lm(...)$coefficients lm(...)$fitted.values lm(...)$residuals ↔ ↔ ↔ coefficients(lm(...)) fitted.values(lm(...)) residuals(lm(...)) Esempio 6.3.3 Sempre con riferimento alla situazione di cui agli Esempi 6.3.1 e 6.3.2, le stime del modello di regressione lineare in esame nonché i valori teorici (o stimati) ŷ i , con i = 1, 2, . . . , n, possono essere visualizzati, con un’approssimazione alla seconda cifra decimale, mediante le istruzioni: > coefficients(modello.es1) (Intercept) Temperatura -131.332357 6.578188 > round(fitted.values(modello.es1),2) 1 2 3 4 5 6 13.39 26.54 33.12 33.12 39.70 39.70 12 13 14 15 16 17 46.28 52.86 52.86 59.44 66.01 66.01 23 24 25 26 92.33 92.33 105.48 105.48 7 39.70 18 66.01 8 39.70 19 72.59 9 46.28 20 79.17 10 46.28 21 79.17 11 46.28 22 79.17 A questo punto, siamo in grado di costruire un grafico come quello proposto in figura (??.a); a tal fine, infatti, sopperiscono le istruzioni: > attach(ozono.yx) > plot(Temperatura,Risposta,xlim=c(20,40),ylim=c(0,150),frame.plot = FALSE, xlab="Temperatura (x)",ylab="Ozono (y)",pch=20,col="blue") > lines(Temperatura,modello.es1$fitted,col="red",cex=1.5) > detach(ozono.yx) > grid() 167 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 oppure, in modo più diretto: > plot(ozono.yx,xlim=c(20,40),ylim=c(0,150),frame.plot = FALSE, xlab="Temperatura (x)",ylab="Ozono (y)", pch=20,col="blue") > abline(modello.es1,col="red",cex=1.5) > grid() ottenendo il grafico proposto in figura (??.b). 6.3.3 La funzione lm(): verifiche di ipotesi sulle stime Come è noto, alla stima puntuale dei parametri di un modello di regressione si dovrà affiancare la verifica di ipotesi cosı̀ come, poste in (6.18) e (6.19). In R ciò è possibile, 2 ferma restando l’assunzione che - ∼ N 0, σ , ricorrendo all’istruzione: > summary(lm(formula=... ,...))$coefficients la quale porge, quale sottoforma di tabella, le stime (puntuali) dei parametri del modello specificato, i rispettivi errori standard, i corrispondenti valori sperimentali delle statistiche test adottate, in accordo alle (6.16) e (6.17), nonché il p − value ad essi associato. A tal propostio è bene tenere a mente che, nonostante l’equivalenza, asserita al paragrafo precedente, tra le istruzioni: > lm(formula=... ,...)$coefficients > coefficients(lm(formula=... ,...)) l’output del comando summary(coefficients(lm(formula=... ,...))) non avrebbe alcun senso, in quanto esso porgerebbe, per le stime ottenute, la media, i quartili, nonché il minimo ed il massimo. Esempio 6.3.4 Con riferimento alla situazione di cui all’Esempio 6.3.1, abbiamo: > summary(modello.es1)$coefficients Estimate Std. Error t value Pr(>|t|) (Intercept) -131.332357 42.474389 -3.092036 0.0049817779 Temperatura 6.578188 1.460964 4.502636 0.0001471189 Dal momento che i p − value ottenuti sono prossimi allo zero, siamo portati a rifiutare le ipotesi nulle H0 : α = 0 e H0 : β = 0. Si noti come il risultato dell’istruzione: > summary(coefficients(modello.es1)) Min. 1st Qu. Median Mean 3rd Qu. -131.300 -96.850 -62.380 -62.380 -27.900 168 Max. 6.578 E. D. Isaia, Linguaggio R e applicazioni statistiche verrebbe ad essere del tutto privo di senso. ♥ Desiderando visualizzare anche il valore sperimentale della statistica test (6.21) ed il corrispondente p − value, onde avere un’idea circa la bontà di adattamento del modello di regressione specificato, conviene ricorrere all’istruzione: > summary(lm(formula=... ,...)) la quale porge: — alcune statistiche riassuntive circa i residui della regressione; — la tabella riguardante la verifica delle ipotesi (6.18) e (6.19) concernenti le stime dei parametri del modello; — l’errore standard dei residui s, in accordo alla (6.15), con i rispettivi gradi di libertà; — il valore del quadrato del coefficiente di correlazione lineare r, nonché il corrispondente valore “corretto” (cfr. Osservazione 6.4.1); — il valore sperimentale della statistica (6.21), con i relativi gradi di libertà a numeratore e denominatore, nonché il p − value corrispondente. Esempio 6.3.5 Sempre con riferimento alla situazione di cui all’Esempio 6.3.1, da quanto sopra, abbiamo: > summary(modello.es1) Call: lm(formula = formula.es1, data = ozono.yx) Residuals: Min 1Q Median -37.28 -19.14 -5.49 3Q 11.45 Max 81.72 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) -131.332 42.474 -3.092 0.004982 ** Temperatura 6.578 1.461 4.503 0.000147 *** --Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ Residual standard error: 26.99 on 24 degrees of freedom Multiple R-Squared: 0.4579,Adjusted R-squared: 0.4353 F-statistic: 20.27 on 1 and 24 degrees of freedom,p-value: 0.0001471 169 1 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Nonostante un basso valore sperimentale del coefficiente di correlazione lineare (r = 0.2097), il p − value prossimo a zero associato al valore sperimentale della statistica test (6.21) ci consente di affermare che i dati campionari ben si adeguano al modello di regressione lineare proposto. ♥ Qui nel seguito riportiamo i comandi permettono di estrarre in modo diretto alcuni elementi dell’output generato da summary(lm(formula=...,...)): — summary(lm(formula=...,...))$sigma: l’errore standard s; — df.residual(lm(formula=...,...)): i gradi di libertà impiegati per il calcolo di s2 ; — deviance(lm(formula=...,...)): la devianza tra valori effettivi e teorici, cioè il numeratore di s2 ; — summary(lm(formula=...,...))$r.squared: la “frazione della varianza spiegata dalla retta di regressione” ovvero il quadrato del coefficiente di correlazione; — summary(lm(formula=...,...))$fstatistic: il valore sperimentale della statistica F con i corrispondenti gradi di libertà. Esempio 6.3.6 Con riferimento all’analisi di cui all’Esempio 6.3.5 ed alla luce di quanto sopra, si considerimo le istruzioni: > summary(modello.es1)$sigma [1] 26.99364 > df.residual(modello.es1) [1] 24 > deviance(modello.es1) [1] 17487.76 > (summary(modello.es1)$sigma)^2*df.residual(modello.es1) [1] 17487.76 > summary(modello.es1)$r.squared [1] 0.4579178 > summary(modello.es1)$fstatistic value numdf dendf 20.27373 1.00000 24.00000 L’output di summary(modello.es1)$fstatistic è un vettore numerico di tre elementi, il primo dei quali, il valore di F sperimentale, può essere acquisito, ad esempio, con l’istruzione > summary(modello.es1)$fstatistic[1] value 20.27373 170 E. D. Isaia, Linguaggio R e applicazioni statistiche Si osservi, infine, che l’output dell’istruzione summary(modello.es1)$coefficients è rappresentato da una matrice di ordine 2 × 4 e quindi desiderando estrarre, ad esempio, l’errore standard associato alla stima del coefficiente β, sarà sufficiente l’istruzione: > summary(modello.es1)$coefficients[2,3] [1] 4.502636 ♥ Osservazione 6.3.1 La funzione summary(...) sin qui impiegata è assai generica; nel caso dell’analisi della regressione si dovrebbe, a rigore di logica, ricorre alla funzione specifica summary.lm(...), nonostante i risultati siano del tutto equivalenti. Il lettore, tuttavia, può ottenere utili informazioni consultando l’aiuto in linea di summary.lm. 6.3.4 La funzione predict.lm(): intervalli di confidenza e di previsione Una volta stimata la retta di regressione e verificatane la bontà di adattamento, può essere di interesse determinare, perlomeno in corrispondenza ad alcuni valori di interesse del predittore, gli itervalli di condifenza e/o gli intervalli di previsione per la variabile risposta, cosı̀ come indicato al paragrafo 6.2.3. A tal fine, nonostante sia sempre possibile redarre una funzione ad hoc basata sulle (6.24) e (6.23), vediamo come sfruttare la particolare funzione predict.lm(...), la cui sintassi minima è: predict.lm(object,data,interval=...,level=...) dove: — object: è l’oggetto, di classe lm, che definisce il modello di regressione in esame; — data: è il data frame contenente le osservazioni campionarie di interesse (valori osservati e/o valori “futuri” del predittore); — interval=: indica se trattasi di un intervallo di confidenza (confidence) ovvero di previsione (prediction); — level=: specifica il consueto livello di significatività 1 − α da utilizzare. Per default, level=0.95. L’output della funzione è una matrice di dimensione n × 3 contenente, in corrispondenza a ciascuno degli n valori del data frame specificato in data, la stima ŷ (fit), il limite inferiore (lwr) e quello superiore (upr) dell’intervallo di interesse. 171 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 A tal proposito, desiderando ottenere un intervallo di confidenza e/o di previsione per uno o più particolari valori del predittore, siano essi interni e/o esterni al range dei valori osservati, si dovrà creare un nuovo data fame ad hoc, contenente, appunto, tali valori. Esempio 6.3.7 Sempre con riferimento alla situazione di cui all’Esempio 6.3.1, gli intervalli di confidenza e di previsione, al livello di condifenza del 95%, in corrispondenza a ciascuna delle n = 26 osservazioni campionarie, si ottengono facilmente con le istruzioni: > predict.lm(modello.es1,ozono.yx,interval="confidence",level=0.95) fit lwr upr 1 13.38779 -9.968481 36.74406 2 26.54416 8.298502 44.78983 3 33.12235 17.188915 49.05579 ... ... ... ... 24 92.32605 73.329223 111.32287 25 105.48242 81.302257 129.66259 26 105.48242 81.302257 129.66259 > predict.lm(modello.es1,ozono.yx,interval="prediction",level=0.95) fit lwr upr 1 13.38779 -47.022124 73.79770 2 26.54416 -32.079605 85.16793 3 33.12235 -24.823454 91.06816 ... ... ... ... 24 92.32605 33.464163 151.18793 25 105.48242 44.749216 166.21563 26 105.48242 44.749216 166.21563 Desideando, ora, costruire un intervallo di previsione, al livello di condifenza del 90%, per la concentrazione di ozono in corrispondenza ad una temperatura ambientale di 23 e 38 gradi Celsius, possiamo impartire le istruzioni: > ozono.yx.new<-data.frame(Temperatura=c(23,38)) > predict.lm(modello.es1,ozono.yx.new,interval="prediction",level=0.90) fit lwr upr 1 19.96598 -29.3131 69.24505 2 118.63880 66.3090 170.96861 Si osservi che le istruzioni: > > > > new<-data.frame(Temperatura=c(20:40)) IC.modello.es1<-predict(modello.es1,new,interval="confidence",level=.95) IP.modello.es1<-predict(modello.es1,new,interval="prediction",level=.95) matplot(new$Temperatura,cbind(IC.modello.es1,IP.modello.es1[,-1]), xlim=c(20,40),ylim=c(0,150),frame.plot=FALSE,type="l", lty=c(1,2,2,5,5),col=c("blue","red","red","black","black"), 172 E. D. Isaia, Linguaggio R e applicazioni statistiche ylab="Concentrazione di ozono",xlab="Temperatura ambientale") > testo<-c("Stime","Retta di regressione","I.C. (95%)","I.P. (95%)") > legend(20,148,lty=c(0,1,2,5),merge=TRUE,pch=c("+",-1,-1,-1), legend=testo,col=c("green","blue","red","black"),cex=.85,bty="n") > grid() > points(ozono.yx$Temperatura,drop(modello.es1$fitted),type="p",pch="+", cex=2,col="green") consentono di ottenere la figura (??) che riporta il grafico della nuvola di punti di coordinate (xi , yi ), della stima della retta di regressione, nonché i rami di iperbole corrispondenti ai limiti inferiore e superiore degli intervalli di confidenza e di previsione testè ottenuti. ♥ 6.3.5 Per un’analisi dei residui Alla stima ed alla verifica delle ipotesi statistiche concernenti i parametri di un modello di regressione è buona norma, per i motivi di cui già si è detto, far seguire un’analisi empirica dei residui, In R ciò è possibile semplicemente ricorrendo alla funzione plot(lm(formula=...)), la quale porge, in modo del tutto automatico, i grafici di cui si disse al paragrafo 6.2.4. Esempio 6.3.8 Sempre riprendendo i dati di cui all’Esempio 6.3.1, le istruzioni: > par(mfrow=c(2,2)) > plot(modello.es1,col="blue") > par(mfrow=c(1,1)) producono i grafici riportati in figura (??). *** eventuale commento *** Val qui la pena vedere in dettaglio le possibili istruzioni che consentono di ottenere i residui standardizzati nonché le “distanze di Cook”. Dal momento che entrambe dipendono in modo esplicito dalle quantià h i , che come si è visto concorrono alla stima della varianza dei residui σ 2 , vediamo dapprima come calcolare tali grandezze. Posto che gli oggetti xi e yi contengano le n osservazioni campionarie (x i , yi ), definito il modello di regressione lineare modello<-lm(yi~xi), ricordando la (6.14), abbiamo: > hi<-(sum(xi^2)-2*xi*sum(xi)+n*xi^2)/(n*sum(xi^2)-(sum(xi))^2) da cui, introdotti gli oggetti: > residui<-modello$residuals > summary.lm(modello)$sigma essendo i residui standardizzati s yi − ŷi , si ha: > 1 − hi 173 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > residui.std<-residui/(s*sqrt(1-hi)) ed infine, ricordando la (6.25): distanze.cook<-(residui/(s*(1-hi)))^2*(hi/2) Tuttavia R prevede una particolari funzioni che consentono il calcolo diretto di tali grandezze, più precisamente trattasi delle funzioni: — lm.influence(lm(formula=...,...)): essa fornisce, sottoforma di lista, i seguenti oggetti: – hat: i valori hi in corrispondenza a ciascuna realizzazione x i di X; – coefficients: le differenze8 a − a−i , b − b−i , ovvero le differenze tra le stime di α e di β e quelle che si otterrebbero qualora si escludesse la i-esima osservazione campionaria, e ciò ∀ i = 1, 2, . . . , n; – sigma: le stime s2−i di σ 2 qualora si escludesse la i-esima osservazione campionaria, e ciò ∀ i = 1, 2, . . . , n; I valori contenuti in coefficients e sigma possono essere utilizzati per individuare quali sono le realizzazioni x i di X che hanno un peso determinante nel processo di stima del modello di regressione. — rstandard(lm(formula=...,...)): fornisce i residui standardizzati; — cook.distance(lm(formula=...,...)): porge le “distanze di Cook”. Esempio 6.3.9 Sempre riprendendo i dati di cui all’Esempio 6.3.1, le istruzioni: *** DA FARE *** > *** *** eventuale commento *** Ricordiamo, infine, la possibilità di ricorrere alle seguenti due funzioni: — rstudent(lm(formula=...,...)): fornisce i residui “studentizzati”, cioè i residui standardizzati ricorrendo alla stima s 2−i di σ 2 ; 8 Acquisibili ricorrendo alle istruzioni lm.influence(lm(formula=...,...))$coefficients[,1] e lm.influence(lm(formula=...,...))$coefficients[,2]. 174 E. D. Isaia, Linguaggio R e applicazioni statistiche — influence.measures(lm(formula=...,...)): porge, sottoforma di tabella ed in corrispondenza a ciascuna determinazione x i di X, alcune misure riassuntive di diagnosi dei residui9 con indicazione, mediante asterisco, dei valori campionari “sospetti”. Esempio 6.3.10 Sempre riprendendo i dati di cui all’Esempio 6.3.1, le istruzioni: *** DA FARE *** > influence.measures(modello.es1) *** eventuale commento *** 6.4 4 Sulla regressione multipla: il modello y, X β, σ 2 In 6 Cappellino Si immagini che le misurazioni, effettuate su n individui, di p+1 variabili quantitative siano rappresentabili mediante i vettori di y, x 1 , x2 , . . . , xp ∈ IRn, ed altresı̀ si supponga di volere “spiegare” la variabile y mediante i p predittori (o variabili esplicative) xj . Abitualmente tali predittori vengono supposti essere linearmente indipendenti, il che non implica che essi lo siano anche sotto il profilo statistico 10 . Si immagini che i vettori x1 , x2 , . . . , xp , y ∈ IRn costituiscano un campione casuale di dimensione n di altrettante realizzazioni di p + 1 v.c. X 1 , X2 , . . . , Xp , Y . Per cose note, la migliore approssimazione di Y mediante una funzione delle p v.c. Xj , abitualmente dette predittori o variabili esplicative, corrisponde al valor medio condizionato IE[Y |X1 , X2 , . . . , Xp ]. Se introduciamo, ora, l’ipotesi: IE[Y |X1 , X2 , . . . , Xp ] = β0 + p ! β0 Xj (6.26) j=0 perveniamo al modello di regressione lineare multipla: Y = β0 + p ! β0 Xj + - j=0 dove - è una v.c. non correlata con le v.c. X j , con valor medio nullo e varianza σ 2 . Per le ipotesi fatte, tra le realizzazioni campionarie x i1 , xi2 , . . . , xip , -i , yi delle v.c. X1 , X2 , . . . , Xp , -, Y sussiste, per j = 1, 2, . . . , p e i = 1, 2, . . . , n, la relazione: yi = β0 + p ! β0 Xij + -i j=0 9 10 Tra esse i valori di hi e di di . Inserire in nota un esempio semplice e breve. 175 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 che può essere posta nella forma compatta: y = Xβ + % (6.27) dove y = [y1 , y2 , . . . , yn ]t è il vettore delle n realizzazioni campionarie indipendenti y i di Y , β = [β0 , β1 , . . . , βp ]t rappresenta il vettore dei parametri incogniti del modello, % = [-1 , -2 , . . . , -n ]t è il vettore degli errori -i mentre: 1 1 X= . . . 1 x11 x21 ... xn1 x12 x22 ... xn2 ... ... ... ... x1p x2p ... xnp (6.28) è una matrice di ordine n × (p + 1) la cui prima colonna contiene i coefficienti della costante del modello e le colonne successive le realizzazioni campionarie indipendenti delle p v.c. Xj . Seguento la letteratura, indichiamo il modello di regressione lineare multipla corri, 2 spondente alla (6.27) con la tripla y, X β, σ In , dove chiaramente In è una matrice identità di dimensione n × n. 6.4.1 Stima e verifica di ipotesi sui parametri del modello Il problema che ci si pone è la stima dei parametri β O , β1 , . . . , βp del modello nonché della varianza del termine di disturbo -. Il ricorso al metodo dei minimi quadrati comporta la minimizzazione, rispetto ai p + 1 parametri del modello, della funzione: F (β0 , β1 , . . . , βp ) = n ! i=1 (yi − β0 − p ! βj xij )2 j=1 Ora, come facilmente si può verificare, i coefficienti del sistema delle equazioni normali corrispondono al prodotto matriciale X t X, infatti: X X= t (n n i=1 xi1 ( (n n 2 i=1 xi1 i=1 xi1 ( ( n n x i=1 i2 i=1 xi1 xi2 .. ( . n i=1 xip (n (n i=1 i=1 (n xi2 ... xi1 xi2 . . . i=1 x2i2 ... .. .. . . ... (n (n i=1 xi1 xip i=1 xi2 xip . . . 176 (n (n i=1 i=1 (n xip xi1 xip xi2 xip .. . (n 2 i=1 xip i=1 E. D. Isaia, Linguaggio R e applicazioni statistiche mentre i termini noti del sistema delle equazioni normali corrispondono al vettore X y, infatti: ( n yi i=1 ( n i=1 xi1 yi ( n X y = i=1 xi2 yi .. . ( n i=1 xip yi Pertanto la condizione dei minimi quadrati porge, quale stima di β, il vettore: 4 6−1 b = Xt X (6.29) Xt y Ciò premesso, è immediato dimostare che lo stimatore b,ottenuto in accordo al metodo dei minimi quadrati, è uno stimatore corretto di β. Infatti, dal momento che X è una costante ed osservando che IE[y] = X β, si ha: IE[b] = IE[(Xt X)−1 Xt y] = (Xt X)−1 Xt X β = β Con un ragionamento simile, otteniamo la varianza dello stimatore b; ricordando che V ar[y] = V ar[%] = σ 2 In , sarà: V ar[b] = V ar[(Xt X)−1 Xt y] = (Xt X)−1 (Xt X)−1 Xt V ar[y] X = = σ 2 (Xt X)−1 (Xt X)−1 Xt In X = σ 2 (Xt X)−1 (6.30) mentre una stima corretta della varianza σ 2 è offerta dallo stimatore: S2 = ||y − ŷ||2 ||y − X b||2 = n−p−1 n−p−1 (6.31) È qui appena il caso di osservare che tra tutti gli stimatori corretti di β, b è quello a varianza minima; tale proprietà nonché quella circa la correttezza dello stimatore posto in (6.31) discendono dal teorema di Gauss-Markov generalizzato. Per approfondimenti a tal riguardo, si rimanda ai testi di McCullagh, Nelder (2000) e Saporta (1990). Se introdiciamo, ora, l’ipotesi che ∀ i = 1, 2, . . . , n - i ∼ N (0, 1), y può allora essere inteso quale vettore gaussiano multidimensionale, cioè: 4 6 y ∼ Nn X β, σ 2 In ) 177 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 con densità di probabilità, quindi: L(y, β, σ ) = 2 = : 1 (y − X β)t (y − X β) √ exp − 2 σ2 σ n ( 2 π)n : < 1 y yt − 2 β t Xt y − β t Xt X β √ exp − 2 σ2 σ n ( 2 π)n < Sotto tale ipotesi, la stima di massimaverosomiglianza per β viene a coincidere con la stima proposta in (6.29) e ottenuta con il metodo dei minimi quadrati; in più, essendo b una trasformata lineare di un vettore gaussiano, si ha: 4 b ∼ Np+1 β, σ 2 (Xt X)−1 6 (6.32) Quanto alla varianza σ 2 , il metodo della massimaverosomiglianza porge la stima n−1 ||y−X b||2 , la quale dovrà, quindi, essere corretta, in accordo alla (6.31), mediante il fattore n − n p − 1 . A tal proposito, si dimostra, poi, che: ||y − X b||2 (n − p − 1) S 2 = ∼ χ2n−p−1 σ2 σ2 (6.33) Focalizzando l’attenzione sul j-esimo coefficiente di regressione empirico b j , in virtù della (6.30) sarà: V ar[bj ] = σb2j = σ 2 (Xt X)−1 jj (6.34) dove (Xt X)jj indica l’elemento jj-esimo di (Xt X)−1 e, ricordando la (6.31), la stima corretta di σb2j è offerta da: s2bj = ||y − X b||2 (Xt X)−1 jj n−p−1 Ne segue11 , che la variabile test: Tbj = bj − βj bj − βj =N sbj ||y − X b||2 (Xt X)−1 jj n−p−1 viene a possedere ditribuzione t di Student con n − p − 1 gradi di libertà. 11 Si noti che, per le ipotesi fatte, bj ∼ N (βj , σb2j ). 178 (6.35) E. D. Isaia, Linguaggio R e applicazioni statistiche Tali considerazioni consentono di pervenire alla costruzionione di intervalli di confidenza, ad un prefissato livello 1 − α, per i p + 1 parametri incogniti β 0 , β1 , . . . , βp o di sottoporre a verifica le seguenti ipotesi statistiche, ∀ j = 0, 1, 2, . . . , p: + H0 : βj = 0 H1 : βj 3= 0 (6.36) con l’avvertenza che le statistiche test coinvolte non risultano tra loro indipendenti, non essendolo i coefficienti bj tra loro. 6.4.2 Sul coefficiente di correlazione multipla Com’è noto, il coefficiente di correlazione multipla tra Y e le p+1 variabili esplicative 12 può essere calcolato direttamente in base alla matrice X dei coefficienti del modello di regressione lineare; infatti, indicando con X ∗ la matrice “centrata” di X13 e con y∗ il vettore “centrato” di y 14 , risulta: t R2 = t t y∗ X∗ (X∗ X∗ )−1 X∗ y∗ (6.37) t y∗ y∗ Ora, un semplice calcolo consente di porre la (6.37) nella forma: R2 = ||y − ȳ||2 − ||y − X b||2 ||y − ȳ||2 il che indica che il quadrato del coefficiente di regressione multipla può essere inteso quale rapporto tra la varianza spiegata dal modello di regressione e la varianza totale di Y . Tale considerazione (cfr. Osservazione 6.4.1) ci permette effettuare un test circa la bontà di adattamento del modello di regressione sulla base di un’opportuna trasformata di R2 . Infatti, dal momento che: ||y − ȳ||2 = ||y − X b||2 + ||X b − ȳ||2 e tenendo presente l’ipotesi intordotta sulle - i , si ha: — ∀ β: ||y − X b||2 ∼ χ2n−p−1 σ2 12 Includendo la costante. ¯ j , con Ossia la matrice di dimensione n × p + 1 le cui colonne contengono gli scarti xij − x̄ ( di( p ¯j = n ovviamente x̄ x . i=1 j=1 ij 14 Leggasi il vettore degli scarti yi − ȳ. 13 179 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 — vera l’ipotesi βj = 0, con j = 1, 2, . . . , p e β0 qualsiasi: ||X b − ȳ||2 ∼ χ2p σ2 — vera l’ipotesi βj = 0, con j = 1, 2, . . . , p e β0 qualsiasi: ||y − ȳ||2 ∼ χ2n−1 σ2 La bontà di adattamento del modello di regressione multipla può essere misurata ricorrendo al rapporto tra la varianza spiegata dal modello di regressione e la varianza ||X b − ȳ||2 R2 . residua, in simboli 2 = ||y − X b|| 1 − R2 Ora, sotto l’ipotesi βj = 0, con j = 1, 2, . . . , p e β0 qualsiasi, risulta: R2 n − p − 1 ∼ Fp;n−p−1 p 1 − R2 dove, come di consueto, Fp;n−p−1 indica la ditribuzione F di Snedecor con, rispettivamente, p gradi di libertà a numeratore e n − p − 1 gradi di libertà a denominatore. Si tenga presente che la lettura del solo valore empirico del coefficiente di correlazione multipla potrebbe trarre in inganno; infatti si potrebbe osservare un R 2 prossimo all’unità e al contempo accettare “in blocco” le ipotesi H 0 : bj = 0. Tale è certamente il caso se i predittori sono fortemente correlati tra loro (cfr. paragrafo 6.4.4). Osservazione 6.4.1 L’accettazione, ∀j = 1, 2, . . . , p, delle ipotesi di nullità dei coefficienti di regressione (H0 : βj = 0, con β0 qualunque) equivale pertanto all’accettazione che il coefficiente di correlazione multiplo (teorico) ρ sia nullo, cioè dell’ipotesi di non-regressione. Se tale è il caso, allora ρ viene a possedere distribuzione Beta di parametri p/2 e (n − p − 1)/2, per cui: IE[R2 ] = p n−1 V ar[R2 ] = 2 p (n − p − 1 (n2 − 1) (n − 1) Viceversa se l’ipotesi di non-regressione è rifiutata (ρ 3= 0), allora la distribuzione di R2 assume una forma più complessa ed R 2 viene ad essere uno stimatore distorto. A p (1 − ρ) + O(n−1 ). Per tali motivi tal propostito si dimostra che IE[R 2 ] = ρ2 + n − 1 a volte si ricorre ad un valore di R 2 “corretto” (adjusted R squared): ∗ R2 = (n − 1) R2 − p n−p−1 che presenta, però, lo svantaggio di condurre a valori negativi (!) se il coefficiente di correlazione multipla è prossimo allo zero. 180 E. D. Isaia, Linguaggio R e applicazioni statistiche 6.4.3 Sulla previsione e l’analisi dei residui Dal momento che su tali argomenti valgono, in generale, le considerazioni fatte in occasione dell’analisi della regressione lineare semplice, nel seguito ci limitiamo a presentare alcuni risultati di interesse, rimandando per dettagli ai paragrafi 6.2.3 e 6.2.4. — intervallo di previsione: posto x0 = [1, x10 , x20 , . . . , xp0 ]t il vettore contenente i valori di interesse dei predittori i corrispondenza ai quali si desidera “prevedere” il valore di y, la v.c. ŷ0 = xt0 b, sotto le ipotesi fatte circa le -i , ha distribuzione normale di parametri xt0 β0 e σ 2 xt0 (Xt X)−1 x0 . Posto y0 = IE[y|X1 = x10 ∩ . . . ∩ Xp = xp0 ] la v.c. standardizzata y0 − ŷ0 , utilizzando lo stimatore corretto posto in (6.31): S / y0 − ŷ0 1 + xt0 (Xt X)−1 x0 viene a possedere distribuzione t di Student con n − p − 1 gradi di libertà., da cui l’intervallo di previsione per y0 : ŷ0 ± n−p−1 t1−α/2 s / 1 + xt0 (Xt X)−1 x0 — i residui standardizzati: prendendo le mosse dall’uguaglianza y = y − X b+ X b e ricordando che (y − X b) ⊥ X b, si ha: V ar[y] = V ar[y − X b] + V ar[X b] da cui: V ar[y − X b] = σ 2 [In − X (Xt X)−1 Xt ] Indicando con hi il generico i-esimo termine della diagonale di X (X t X)−1 Xt , ( con n−1 ≤ hi ≤ 1 e ni=1 hi = n − p − 1, abbiamo σy2i −ŷi = σ 2 (1 − hi ), donde, sostituendo a σ 2 la sua stima corretta, la stima della varianza dei residui: s2yi −ŷi = s2 (1 − hi ) 181 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 6.4.4 Sulla multicollinearità La principale fonte di instabilità della stima di β è rappresentata dall’ordine di grandezza delle varianze σb2j ; tenendo a mente la (6.34), è facile intuire che qualora il determinante di Xt X fosse prossimo a zero, gli elementi di (X t X)−1 tenderebbero ad assumere valori elevati e di conseguenza le σ b2j , sı̀ che i parametri del modello verrebbero ad essere stimati in modo impreciso. Tra le svariate cause che producono tale anomalia, una è certamente la la correlazione tra le variabili esplicative; tale situazione viene indicata con il termine di multicollinearità. Desiderando, in qualche modo, verificare tale affermazione, posto, per semplicità, ∗ X una matrice “standardizzata”15 di dimensione n × p ed indicando con con R la matrice di correlazione tra i p predittori, è facile verificare la relazione n R = ∗ Xt ∗ X. Ciò premesso, si ha V ar[b] = σ 2 n−1 R−1 e, pertanto, con riferimento al suo j-esimo elemento, la corrispondente stima corretta può essere posta nella forma: s2bj = σ2 (R−1 )jj n (6.38) dove, chiaramente, (R−1 )jj indica il j-esimo termine della diagonale di R −1 . Per inciso, si osservi che (R−1 )jj = (1 − Rj2 )−1 , dove Rj2 corrisponde al quadrato del coefficiente di correlazione multipla tra j-esimo predittore e le restanti p − 1 variabili esplicative. Evidentemente, qualora i predittori fossero tra loro ortogonali si avrebbe, ∀ j = 1, 2, . . . , p, Rj2 = 0 e di conseguenza s2bj = σ 2 n−1 . In particolare, poi, i termini (1 − Rj2 )−1 vengono abitulamente detti fattori di inflazione della varianza (VIF), e la loro media può essere considerata quale indice globale di multicollinearità. Il problema della multicollinearità tra i predittori può essere risolto, o perlomeno attenuato, ricorrendo a diverse strategie 16 proposte in letteratura, quali ad esempio, la regressione per componenti principali, la ridge regression, o le tecniche di selezione, quali la backward regression, la forward regression o, ancora, la stepwise regression. Gli algoritmi più diffusi, e implementati sulla maggior parte dei pacchetti statistici in commercio, sono senza dubbio quelli basati sulle tecniche di selezione, anche se queste non sono esenti da critiche, ad esempio mal si prestano là dove si richiede la stima di un modello di previsione. Sostanzialmente tali tecniche tendono a ridurre un problema di regressione multipla a p variabili esplicative ad un analogo a q < p predittori, questi ultimi scelti tra quelli che apportano il maggior contributo ad R 2 . In particolare: 15 In altri termini, si suppone, cioè che tutte le variabili del modello di regressione multipla siano standardizzate. Ovviamente, sotto tali ipotesi, si ha b = (Xt X)−1 = (∗ Xt ∗ X)−1 . 16 Presupponendo una certa discrezionalità, da parte del ricercatore, sul numero dei predittori che concorrono a spiegare y. 182 E. D. Isaia, Linguaggio R e applicazioni statistiche — con la backward regression si inizia con la stima del modello completo a p predittori e si elimina la variabile esplicativa che ha la minore influenza su R 2 , o equivalentemente quella che presenta il maggior p − value associato al test su βj . Quindi si effettua una nuova stima del modello a p − 1 predittori e cosı̀ via sino all’eliminazione di p − 1 variabili esplicative o al raggiungimento di una condizione di arresto. — con la forward regression si inizia con la stima del modello ad una sola variabile esplicativa, quella che ha maggior influenza su R 2 , e via, via, secondo lo stesso criterio, si aggiungono i restanti predittori. Il processo iterativo ha termine non appena R2 raggiunge una soglia prefissata. — la stepwise regression può essere intesa come un perfezionamento dell’algoritmo della forward regression, nel senso che ad ogni passo viene effettuato un test (su βj o su R2 ) teso a non introdurre un predittore non significativo oppure ad eliminare le eventuali variabili esplicative non più significative una volta inserita nel modello l’ultima variabile selezionata. Abitualmente il processo ha termine non appena R2 raggiunge una soglia prefissata. 6.5 La regressione multipla in R Nel caso si debba affrontare un’analisi di regressione lineare multipla in R si ricorre alla funzione lm() già affrontata in dettaglio e per la quale, in linea generale, valgono le considerazioni fatte ai paragrafi 6.3 e successivi. Nel seguito, pertanto, focalizzeremo la nostra attenzione alla risoluzione di problemi più specifici, quali ... *** 6.5.1 Definizione del modello e l’istruzione model.matrix(lm(...)) Come già si disse, in R è buona norma organizzare le ossevazioni campionarie in un data frame, introdurre in modo esplicito il modello di regressione lineare mediante , 2 un’opportuna formula, che nel caso del modello y, X β, σ In a p predittori potrebbe presentarsi: > formula<-as.formula(Risposta~var1+var2+ ... +varp) o, in modeo del tutto equivalente: > formula<-as.formula(Risposta~.) e successivamente definire l’oggetto di classe lm che conterrà i risultati di interesse nonché altre informazioni necessarie per uleriori elaborazioni; ad esempio mediante l’istruzione: 183 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 > modello<-lm(formula,data=data frame) Un differente modo di procedere consiste nel definire la formula a partire dal vettore delle n osservazioni campionarie di Y e dalla matrice delle realizzazioni campionarie dei p predittori Xj , oggetti che potrebbero coincidere con gli elementi del data frame; seguendo tale approccio, potrebbero valere le istruzioni: > formula<-as.formula(y~Xp) > modello<-lm(formula) dove, è bene tenerlo a mente, Xp è una matrice di ordine n × p. Esempio 6.5.1 A puro scopo didattico, si immagini che per un modello di regressione lineare multipla a due sole variabili esplicative si siano ottenute le seguenti osservazioni campionarie: xi1 xi2 yi 8.04 7.46 10.2 6.95 6.77 8.5 7.58 12.74 13.1 8.81 7.11 9.0 8.33 7.81 11.5 9.96 8.84 14.9 7.24 6.08 6.5 4.26 5.39 4.0 10.84 8.15 12.2 4.82 6.42 7.0 5.68 5.73 5.5 Scelto di raccogliere tali informazioni nel data frame dati composto dai tre oggetti x1, x2 e Risposta: > dati<-data.frame( x1=c(8.04,6.95,7.58,8.81,8.33,9.96,7.24,4.26,10.84,4.82,5.68), x2=c(7.46,6.77,12.74,7.11,7.81,8.84,6.08,5.39,8.15,6.42,5.73), Risposta=c(10.2,8.5,13.1,9.0,11.5,14.9,6.5,4.0,12.2,7.0,5.5)) possiamo definire la formula per il modello di regressione Y = β0 + β1 X1 + β2 X2 + * e, successivamente, l’oggetto modello.1 di classe lm tramite le consuete istruzioni: > formula.1<-as.formula(Risposta~.) > modello.1<-lm(formula,data=dati) Alternativamente, ferma restando la sruttura del data frame dati, introdotta la matrice Xp delle n realizzazioni campionarie yi1 e xi2 : > attach(dati) > Xp<-as.matrix(cbind(x1,x2)) > detach(dati) possiamo definire la formula e successivamente l’oggetto modello.2 di classe lm come: > formula.2<-as.formula(Risposta~Xp) > modello.2<-lm(formula.2,data=dati) 184 E. D. Isaia, Linguaggio R e applicazioni statistiche Naturalmente, i due oggetti modello.1 e modello.2 sono equivalenti e si riferiscono al medesimo modello di regressione. ♥ Ora, perlomeno in alcune situazioni, potrebbe tornare utile operare direttamente sulla , 2 matrice X del modello y, X β, σ In . Naturalmente, questa potrebbe essere definita in modo esplicito, ricorrendo ad esempio all’struzione: > X<-cbind(c(rep(1,length(var1))),var1+var2+ ... +varp) dove c(rep(1,length(var1))) crea un vettore colonna di n =length(var1) elementi unitari. Tuttavia in R possiamo automatizzare tale processo ricorrendo alla semplice istruzione: > X<-model.matrix(modello) Esempio 6.5.2 Come si disse, gli oggetti modello.1 e modello.2, definiti all’Esempio 6.5.1, (2 si riferiscono entrambi al modello di regressione Y = β0 + j=1 βj Xj + *; entrambi, quindi, saranno dotati della stessa matrice X, la cui trasposta (X t ) risulta infatti: > t(model.matrix(modello.1)) 1 2 3 4 (Intercept) 1.00 1.00 1.00 1.00 x1 8.04 6.95 7.58 8.81 x2 7.46 6.77 12.74 7.11 attr(,"assign") [1] 0 1 2 > t(model.matrix(modello.2)) 1 2 3 4 (Intercept) 1.00 1.00 1.00 1.00 Xpx1 8.04 6.95 7.58 8.81 Xpx2 7.46 6.77 12.74 7.11 attr(,"assign") [1] 0 1 1 5 6 7 8 9 10 11 1.00 1.00 1.00 1.00 1.00 1.00 1.00 8.33 9.96 7.24 4.26 10.84 4.82 5.68 7.81 8.84 6.08 5.39 8.15 6.42 5.73 5 6 7 8 9 10 11 1.00 1.00 1.00 1.00 1.00 1.00 1.00 8.33 9.96 7.24 4.26 10.84 4.82 5.68 7.81 8.84 6.08 5.39 8.15 6.42 5.73 Nonostante l’aspetto, l’output di model.matrix(...) è, a tutti gli effetti una matrice, infatti: > is.matrix(model.matrix(modello.1)) [1] TRUE e di conseguenza può essere utilizzato per successive elaborazioni. ♥ Palesemente, le considerazioni sin’ora fatte si applicano, mutatis mutandi, ad un modello di regressione lineare semplice, per cui evidentemente risulta p = 1. 185 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Esempio 6.5.3 Con riferimento alla situazione di cui all’Esempio 6.3.1, definita la matrice X come X<-model.matrix(modello.es1), il vettore delle stime dei parametri β 0 e β1 del modello di regressione semplice Y = β0 + β1 X1 + * può essere calcolato in modo diretto come: > solve(t(X)%*%X)%*%t(X)%*%y [,1] [1,] -131.332357 [2,] 6.578188 risultato ovviamente coincidente con l’ouput di modello.es1. 6.5.2 ♥ Ridefinizione del modello: l’istruzione update(lm(...)) A volte, per svariati motivi, nel corso di una sessione di lavoro può accadere di dovere ridefinire un modello di regressione: aggiungere o eliminare alcuni predittori, sopprimere la costante, ... Anziché ridefinire il modello ex-novo, R prevede la funzione update(lm(...)), la cui sintassi autoesplicativa è: update(lm(<old>),lm(<new>)) Posto di avere precedentemente definito l’oggetto modello<-lm(y~x1), si immagini di volere vedere l’effetto sul coefficiente di correlazione multipla R dell’inserimento di un secondo predittore x2; ciò può avvenire ricorrendo alla semplice istruzione: > sqrt(summary(update(modello,y~x1+x2))$r.squared) o, tpiù brevemente ancora: > sqrt(summary(update(modello,.~.+x2))$r.squared) Naturalmente desiderando ridefinire il modello in modo permanente si potrà ricorrere ad un assegnazione del tipo modello<-update(modello,. .+x2). È appena il caso di ricordare che, qualora l’oggetto di classe lm fosse definito in base ad una formula, questa può essere “aggiornata”, nel senso di cui sopra, ricorrendo all’istruzione update.formula(). Esempio 6.5.4 Con riferimento alla situazione di cui all’Esempio 6.3.1, definito, per il modello di regressione Y = β0 + β1 X1 + *, l’oggetto di classe lm: > modello<-lm(Risposta~x1,data=dati) la frazione della varianza totale di Y spiegata dal modello, ovvero R 2 , è circa il 68%, infatti: 186 E. D. Isaia, Linguaggio R e applicazioni statistiche > summary(modello)$r.squared [1] 0.6796644 L’introduzione nel modello del secondo predittore X2 riduce ulteriormente tale indicatore e precisamente del 21%, risultando: > summary(update(modello,.~.+x2))$r.squared [1] 0.8933146 A tal proposito si osservi il comportamento delle istruzioni: > formula<-as.formula(Risposta~x1) > summary(lm(formula,data=dati))$r.squared [1] 0.6796644 > summary(lm(update.formula(formula, ~ . + x2),data=dati))$r.squared [1] 0.8933146 che evidentemente porgono gli stessi risultati. 6.5.3 ♥ Sulla multicollinearità e la stepwise regression Come si è già osservato, in alcune situazioni, può accadere che i test sui parametri βj conducano all’accettazione delle ipotesi nulle e ciò indipendentemente dal valore assunto da R2 . Una delle possibili cause di tale comporamento è imputabile alla varianza delle stime, la quale, come si accennò al paragrafo 6.4.4, viene a sua volta dipendere dalla matrice di correlazione tra le variabili esplicative. Nel caso, dunque, di multicollinearità, si può tentare di pervenire ad un modello di regressione stabile operando discrezionalmente sul numero dei predittori da inserire nel modello stesso. L’Esempio che segue presenta un semplice problema di regressione multipla in presenza di multicollarineità tra i predittori, risolvibile effettuando una selezione “manuale” delle variabili esplicative. Esempio 6.5.5 Un campione casuale di n = 10 autovetture di piccola cilindrata ad alimentazione a benzina ha fornito i seguenti risultati in corrispondenza a quattro variabili di interesse: Cilindrata Potenza Peso Consumi (cc) (cv.Din) (kg) 1075 1255 1075 1306 1455 1055 1175 1175 1375 1255 45 62 45 72 60 53 57 54 72 75 750 805 710 805 820 850 755 815 810 805 (l × 100) 187 5.0 6.5 4.8 6.7 6.5 6.3 4.8 5.9 6.4 6.5 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Desiderando spiegare il Consumo di carburante in funzione dei tre predittori, scegliamo di (3 ricorrere al modello di regressione multipla Y = β0 + j=1 βj Xj + *. Dal punto di vista pratico, inserite le osservazioni campionarie nel data frame auto e definito il modello di regressione a tre predittori: > auto<-data.frame( Cilindrata=c(10.75, 12.55, 10.75, 13.06, 14.55, 10.55, 11.75,11.75, 13.75, 12.55)*100, CV.Din=c(45, 62, 45, 72, 60, 53, 57, 54, 72, 75), Peso=c(750, 805, 710, 805, 820, 850, 755, 815, 810, 805), Consumo=c(5, 6.5, 4.8, 6.7, 6.5, 6.3, 4.8, 5.9, 6.4, 6.5)) > modello<-lm(Consumo~.,data=auto) otteniamo17 i seguenti risultati: > summary(modello)$coefficients Estimate Std. Error t value (Intercept) -5.7378368 2.288926 -2.5068 Cilindrata 0.0009164 0.001188 0.7713 CV.Din 0.0230951 0.015522 1.4879 Peso 0.0115907 0.003114 3.7221 Pr(>|t|) 0.046103 0.469800 0.187354 0.009828 sicché saremo propensi ad accettare le ipotesi nulle circa i coefficienti β1 e β2 . Tuttavia, tale soluzione non è certo soddisfaciente! La natura stessa dei predittori Cilindrata e Potenza fa sı̀ che essi siano correlati tra loro, ed infatti18 : > (R<-cor(model.matrix(update(modello,.~.-1)))) Cilindrata CV.Din Peso Cilindrata 1.0000 0.7167 0.4091 CV.Din 0.7167 1.0000 0.5015 Peso 0.4091 0.5015 1.0000 donde i fattori di inflazione della varianza (VIF): > (vif<-diag(solve(R))) [1] 2.070 2.303 1.345 nonché i coefficienti di correlazione multipla tra i predittori: > 1-(1/vif) [1] 0.5170 0.5658 0.2566 Si noti che questi ultimi potrebbero essere calcolati in modo diretto ricorrendo, ad esempio, all’istruzione: 17 18 Ipotizzando la normalità del termine di disturbo. Per una migliore leggibilità dei risultati, si è scelto di porre options(digits=4). 188 E. D. Isaia, Linguaggio R e applicazioni statistiche > cbind(summary(update(modello,Cilindrata~CV.Din+Peso))$r.squared, summary(update(modello,CV.Din~Cilindrata+Peso))$r.squared, summary(update(modello,Peso~Cilindrata+CV.Din))$r.squared) [,1] [,2] [,3] [1,] 0.517 0.5658 0.2566 Ciò premesso, possiamo pensare di eliminare una delle due variabili esplicative al modello e ri-sottoporre a verifica i parametri dello stesso. > summary(update(modello,.~Cilindrata+Peso))$coefficients Estimate Std. Error t value Pr(>|t|) (Intercept) -6.963191 2.3133772 -3.010 0.019663 Cilindrata 0.002062 0.0009802 2.103 0.073507 Peso 0.013107 0.0031873 4.112 0.004502 > summary(update(modello,.~CV.Din+Peso))$coefficients Estimate Std. Error t value Pr(>|t|) (Intercept) -5.23809 2.130841 -2.458 0.043579 CV.Din 0.03085 0.011476 2.689 0.031152 Peso 0.01179 0.003012 3.913 0.005798 Un’attenta lettura dei risultati, ci porta a ritenere che il Consumo possa essere “spiegato” mediante le varibili Peso e Potenza. Si noti che saremmo giunti alle stesse conclusioni valutando: — la frazione della varianza spiegata dai due modelli a due predittori: > summary(update(modello,.~Cilindrata+Peso))$r.squared [1] 0.8298 > summary(update(modello,.~CV.Din+Peso))$r.squared [1] 0.8633 — la sitma della varianza σ 2 offerta dai due modelli a due predittori: > summary(update(modello,.~Cilindrata+Peso))$sigma [1] 0.3605 > summary(update(modello,.~CV.Din+Peso))$sigma [1] 0.3230 ♥ Il problema della identificazione dei predittori nel caso di multicollinearità può essere affrontato, come si disse al paragrafo 6.4.4, ricorrendo alla stepwise regression, tenica implementata in R quale funzione step, la cui sintassi, perlomeno nella sua veste più dimessa, è: step(modello, trace=1, test="F") 189 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 A tal proposito è bene tenere a mente che: — modello è un oggetto di classe lm definito via lm(formula=..., ...); — con l’opzione trace=0 viene soppressa la visualizzazione dei passi intermedi che conducono al modello definitivo; la situazione di default prevede trace=1; — l’opzione test="F" stabilisce quale criterio di selezione dei predittori quello basato su R2 ; — in modo automatico, alla fine del processo, vengono elencati i predittori selezionati e le corrispondenti stime dei parametri; — step(...) è, a sua volta, un oggetto di classe lm e, in quanto tale, per esso valgono le considerazioni fatte a proposito di tali oggetti. Ad esempio con model.matrix(step(...,...)) viene visualizzata la matrice X associata al modello di regressione con i k ≤ p predittori selezionati. Esempio 6.5.6 Con riferimento alla situazione di cui all’Esempio 6.5.6, la risoluzione del problema di multicollinearità viene risolta, ricorrendo alla funzione step, mediante le istruzioni: > step(modello,trace=1,test="F") Start: AIC= -19.11 Consumo ~ Cilindrata + CV.Din + Peso Df Sum of Sq RSS AIC F value Pr(F) - Cilindrata 1 0.0659 0.7303 -20.1685 0.5949 0.469800 <none> 0.6644 -19.1139 - CV.Din 1 0.2451 0.9096 -17.9735 2.2137 0.187354 - Peso 1 1.5342 2.1987 -9.1474 13.8542 0.009828 ** --Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 ‘ ’ 1 Step: AIC= -20.17 Consumo ~ CV.Din + Peso Df Sum of Sq RSS AIC F value Pr(F) <none> 0.7303 -20.1685 - CV.Din 1 0.7541 1.4845 -15.0754 7.2282 0.031152 * - Peso 1 1.5979 2.3282 -10.5750 15.3151 0.005798 ** --Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ Call: 190 0.1 E. D. Isaia, Linguaggio R e applicazioni statistiche lm(formula = Consumo ~ CV.Din + Peso, data = auto) Coefficients: (Intercept) -5.23809 CV.Din 0.03085 Peso 0.01179 Per concludere, osserviamo che la matrice delle osservazioni associata al modello di regressione a due predittori e il data frame contenente le sole realizzazioni delle (tre) variabili di interesse, possono ottenersi con le istruzioni19 : > t(model.matrix(step(modello,trace=0,test="F"))) 1 2 3 4 5 6 7 8 9 10 (Intercept) 1 1 1 1 1 1 1 1 1 1 CV.Din 45 62 45 72 60 53 57 54 72 75 Peso 750 805 710 805 820 850 755 815 810 805 attr(,"assign") [1] 0 1 2 > t(model.frame(step(modello,trace=0,test="F"))) 1 2 3 4 5 6 7 8 9 10 Consumo 5 6.5 4.8 6.7 6.5 6.3 4.8 5.9 6.4 6.5 CV.Din 45 62.0 45.0 72.0 60.0 53.0 57.0 54.0 72.0 75.0 Peso 750 805.0 710.0 805.0 820.0 850.0 755.0 815.0 810.0 805.0 utili al fine di successive elaborazioni. 6.6 ♥ L’analisi della varianza Una delle tecniche statistiche di impiego più frequente nelle ricerche sperimentali è rappresentata dall’analisi della varianza (ANOVA); com’è noto, essa consente essenzialmente, a partire da campioni indipendenti estratti da popolazioni con distribuzione normale, di verificare se le medie delle popolazioni poste a confronto possono essere ritenute statisticamente uguali, ad un prefissato livello di significatività. Data la vastità dell’argomento, nel seguito considereremo unicamente l’analisi della varianza per esperimenti ad uno e due fattori. In R possiamo procedere in modo diretto all’analisi della varianza ricorrendo al comando aov(formula=,data=). Oltre alla consueta tabella ANOVA riassuntiva, tale funzione restituisce, sottoforma di lista, una serie piuttosto estesa di risultati che possono, come vedremo, essere ripresi per ulteriori analisi mirate *** ANOVA per esperimenti ad un fattore Immaginiamo di voler studiare l’influenza di un certo fattore A su di una grandezza quantitativa Y . Indicati con a 1 , a2 , . . . , ak 19 Per ovvi motivi si presentano le trasposte delle corrispondenti matrici. 191 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 le varie e distinte condizioni sperimentali (livelli, classi o trattamenti) in cui può presentarsi il fattore A, organizziamo un esperimento che preveda: n1 n2 ... nk misurazioni di Y con il fattore A al livello a 1 misurazioni di Y con il fattore A al livello a 2 ...................................... misurazioni di Y con il fattore A al livello a k È quasi il caso di notare come il problema posto sia analogo a quello di avere a che fare con k diversi campioni indipendenti, ciascuno di dimensione n i , tratti da altrettante popolazioni. Supposto che i k campioni casuali (Y i1 , Yi2 , . . . , Yini ), siano indipendenti e provengano da popolazioni normali con valor medio µ + α i e comune varianza σ 2 , possiamo introdurre un modello che considera le v.c. Y ij come una combinazione lineare del tipo Yij = µ + αi + -ij , dove le eij sono v.c. i.i.d. N (0, σ 2 ). Se i diversi livelli del fattore A influenzano i dati del campione allo stesso modo, è lecito formulare l’ipotesi nulla che siano uguali i corrispondenti valori medi da sottoporre a verifica contro l’ipotesi alternativa che almeno due di essi siano diversi tra loro; in simboli: + H 0 : µ1 = µ2 = . . . = µ k = µ0 H1 : ∃ i, j; i 3= j : µi 3= µj (6.39) L’ANOVA è lo strumento adatto appunto alla verifica di tali ipotesi statistiche; essa si basa essenzialmente sul concetto di scissione della devianza di Y nelle due componenti SSA e SSE ; la prima rappresenta la devianza imputabile ai diversi livelli del fattore A, la seconda quella derivante dall’effetto di altre cause non esplicitamente prese in considerazione. Se H0 è vera, SSA dipenderà unicamente dalla varianza σ 2 , mentre in caso contrario dipenderà, oltre che dalla varianza, anche dai parametri a i . Ai fini dell’ANOVA è pertanto necessario confrontare tra loro la devianza SS A con la devianza SSE . Se SSA è significativamente maggiore di SS E , si può concludere che le quantità ai risultano diverse da zero; in altri termini, il fattore A influenza il valor medio della v.c. osservata Y , ovvero la popolazione oggetto di studio non è omogenea rispetto al fattore di classificazione. Ricordando che il rapporto tra due v.c. χ 2 indipendenti divise per i rispettivi gradi di libertà ha distribuzione F di Snedecor, l’ANOVA assumerà quale funzione test il rapporto: n − k SSA k − 1 SSE che, vera H0 , ha appunto distribuzione F di Snedecor con (k − 1) gradi di libertà a numeratore e (n − k) gradi di libertà a denominatore. 192 E. D. Isaia, Linguaggio R e applicazioni statistiche Esempio 6.6.1 Si immagini che i dati che seguono rappresentino il risultato di una serie di misurazioni (espresse in Kg/m2 ) del valore di resistenza a compressione di esemplari di cemento sottoposti a cinque diversi trattamenti Ai , i = 1, 2, . . . , 5: A1 59.1 60.2 58.9 60.1 59.3 A2 62.7 62.3 59.9 60.3 59.7 A3 58.9 60.2 59.7 60.5 59.9 A4 60.5 62.0 62.3 59.7 61.4 A5 59.8 60.6 61.7 61.3 60.2 È interessante verificare se i risultati sperimentali ottenuti siano, in media, influenzati dal particolare tipo di trattamento a cui sono stati sottoposti gli esemplari. Creato, per comodità, il data frame cemento contenente i risultati sperimentali: > y<-c(59.1,62.7,58.9,60.5,59.8,60.2,62.3,60.2,62.0,60.6, 58.9,59.9,59.7,62.3,61.7,60.1,60.3,60.5,59.7,61.3, 59.3,59.7,59.9,61.4,60.2) > a<-factor(c(rep(c(1:5),5))) > (cemento<-data.frame(tratta=factor(a),risposta=y)) tratta risposta 1 1 59.1 2 2 62.7 3 3 58.9 4 4 60.5 5 5 59.8 .................. 21 1 59.3 22 2 59.7 23 3 59.9 24 4 61.4 25 5 60.2 > rm(y,a) > attach(cemento) è facile verificare che, per ciascun tipo di trattamento, media e varianza campionarie risultano: > for (i in 1:length(unique(tratta))){ cat("A=",i," media =>",round(mean(split(risposta,tratta)[[i]]),2), " varianza =>",var(split(risposta,tratta)[[i]]),"\n")} A= A= A= A= A= 1 2 3 4 5 media media media media media => => => => => 59.52 60.98 59.84 61.18 60.72 varianza varianza varianza varianza varianza => => => => => 0.352 1.992 0.368 1.157 0.607 193 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Verificata l’omoschedasticità delle varianze tramite il test di Bartlett (cfr. paragrafo 5.3): > bartlett.test(risposta,tratta) Bartlett test for homogeneity of variances data: risposta and tratta Bartlett’s K-squared = 4.1982, df = 4, p-value = 0.3798 > detach(cemento) se assumiamo che i risultati sperimentali siano determinazioni di altrettanti campioni casuali Xj ∼ N (µj , σ), ciascuno di cardinalità n = 5, con j = 1, 2, . . . , 5, possiamo procedere alla verifica delle seguenti ipotesi statistiche: H0 : µ1 = µ2 = µ3 = µ4 = µ5 H1 : ∃ (i, j)i$=j µi = µj cioè effettuare un’analisi della varianza ad un solo fattore di classificazione (il tipo di trattamento) sulla grandezza quantitativa Y , la resistenza a compressione. A tal fine, definiamo l’oggetto my.anova, che conterrà il modello statistico, la sorgente dei dati e le informazioni di base per la verifica delle ipotesi di interesse, tramite il comando: > (my.anova<-aov(risposta ~ tratta,data=cemento)) Call: aov(formula = risposta ~ tratta, data = cemento) Terms: tratta Residuals Sum of Squares 10.6184 17.9040 Deg. of Freedom 4 20 Residual standard error: 0.94615 Desiderando procedere, ovvero calcolare il p − value associato al test, possiamo ricorrere al comando summary(), il quale coerentemente fornisce: > summary(my.anova) Df Sum Sq Mean Sq F value Pr(>F) tratta 4 10.6184 2.6546 2.9654 0.04486 * Residuals 20 17.9040 0.8952 --Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 In sostanza saremo portati (ad un livello di significatività di poco inferiore al 5%) a rifiutare l‘ipotesi nulla e a ritenere che i diversi tipi di trattamento effettivamente influiscono sulla capacità di resistenza a compressione del cemento. Osserviamo che il ricorso al comando model.tables() consente di visualizzare alcune utili informazioni circa i valori medi campionari; infatti: 194 E. D. Isaia, Linguaggio R e applicazioni statistiche > model.tables(my.anova, type="means") Tables of means Grand mean 60.448 tratta 1 2 3 4 59.52 60.98 59.84 61.18 60.72 5 ♥ ANOVA per esperimenti a due fattori senza replicazioni Si immagini, ora, di voler studiare l’effetto di due fattori, diciamo A e B, su di una certa grandezza quantitativa Y e si supponga che al fattore A siano associati r distinti livelli a 1 , . . . , ai , . . . , ar , convenzionalmente detti trattamenti, ed analogamente al fattore B siano associati s distinti livelli b1 , . . . , bj , . . . , bs , convenzionalmente detti blocchi, di modo che siano complessivamente possibili r × s differenti condizioni sperimentali. Si ipotizzi, altresı̀, di effettuare per ciascuna combinazione dei livelli dei fattori in esame un’unica osservazione Yij , con i = 1, 2, . . . , r; j = 1, 2, . . . , s. Tali risultati sperimentali sono interpretabili come determinazioni campionarie di altrettante v.c. Y ij i.i.d. secondo una N (µ + αi + βj , σ 2 ). In altri termini possiamo modellizzare le v.c. Y ij come una combinazione lineare del tipo Yij = µ + αi + βj + -ij , dove µ indica il valor medio di Y , mentre α i = µi. − µ e βj = µ.j − µ rappresentano, rispettivamente l’effetto del i-esimo trattamento e del j-esimo blocco e le -ij sono v.c. i.i.d. N (0, σ 2 ). Se i diversi livelli del fattore A influenzano Y nella stessa misura, è lecito formulare (1) l’ipotesi che i diversi trattamenti abbiano ugual valor medio, cioè H 0 : αi = 0, ∀ i da (1) sottoporre a verifica contro l’ipotesi alternativa H 1 : ∃ i : αi 3= 0. In modo del tutto analogo, per il fattore B possiamo ipotizzare che i diversi blocchi abbiano ugual valor (2) medio, ovvero H0 : βj = 0, ∀ j da sottoporre a verifica contro l’ipotesi alternativa (2) H1 : ∃ j : βj 3= 0. Riasumendo consideriamo i seguenti sistemi di ipotesi: O O (1) H0 : αi = 0 (1) H1 : ∃ i : αi 3= 0 (6.40) (2) H0 : βj = 0 (2) H1 : ∃ i : βi 3= 0 (6.41) Anche in questo caso, con opportuni passaggi, si può scindere la devianza totale di Yij nei tre addendi SSA , SSB e SSE , che rappresentano, rispettivamente, la devianza tra i trattamenti, la devianza tra i blocchi e la devianza residua. 195 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Il procedimento per verificare le ipotesi statistiche precedentemente poste, si basa (1) (2) sulla seguente osservazione: se H 0 e H0 sono vere, SSA e SSB dipendono unicamente da σ 2 , mentre in caso contrario dipenderanno anche dai parametri α i e βj rispettivamente. Ai fini dell’ANOVA si tratterà, pertanto, di confrontare le devianze SS A e SSB rispetto a SSE . Le funzioni test atte a tal fine sono: SSA r−1 SSE (r − 1) (s − 1) SSB s−1 SSE (r − 1) (s − 1) che, vere le corrispondenti ipotesi nulle, si ditribuiscono secondo una F di Snedecor con, rispettivamente, (r − 1) e (s − 1) gradi di libertà a numeratore e (r − 1) · (s − 1) gradi di libertà a denominatore. Esempio 6.6.2 Si immagini che al fine di una simulazione numerica siano state approntate tre routine di calcolo (r1 , r2 , r3 ), ciascuna delle quali redatta in accordo a tre diversi algoritmi; al fine di verificare la velocità di esecuzione (Y ), si è fatto ricorso ad un esperimento che prevedeva la misurazione dei tempi di esecuzione (in secondi) delle tre routine (fattore A a tre livelli) su altrettanti PC (fattore B a tre livelli o blocchi),con uguali caratteristiche, ottenendo i seguenti risultati sperimentali: Routine ↓ Pc → r1 r2 r3 pc1 2.42 2.45 2.46 pc2 2.44 2.44 2.47 pc3 2.43 2.46 2.48 Trattasi evidentemente di un esperimento a due fattori (A,B) a tre livelli ciascuno con una sola replicazione per cella. Procedendo, creiamo, per comodità, il data frame dati contenente i risultati sperimentali: > > > > 1 2 3 4 5 6 7 8 9 > y<-c(2.44,2.42,2.43,2.45,2.44,2.46,2.46,2.47,2.48) a<-factor(c(1,1,1,2,2,2,3,3,3)) b<-factor(c(1,2,3,1,2,3,1,2,3 )) (dati<-data.frame(fattoreA=a,fattoreB=b,risposta=y)) fattoreA fattoreB risposta 1 1 2.44 1 2 2.42 1 3 2.43 2 1 2.45 2 2 2.44 2 3 2.46 3 1 2.46 3 2 2.47 3 3 2.48 rm(a,b,y) 196 E. D. Isaia, Linguaggio R e applicazioni statistiche e successivamente, al fine di verificare le ipotesi statistiche (6.40) e (6.41), definiamo l’oggetto my.anova, che conterrà il modello statistico, la sorgente dei dati nonché le informazioni di base per la verifica delle ipotesi di interesse, tramite il comando: > (my.anova<-aov(risposta ~ fattoreA+fattoreB,data=dati)) Call: aov(formula = risposta ~ fattoreA + fattoreB, data = dati) Terms: fattoreA fattoreB Residuals Sum of Squares 0.0024000000 0.0002666667 0.0003333333 Deg. of Freedom 2 2 4 Residual standard error: 0.00912871 A questo punto ricorrendo al comando summary(), otteniamo i risultati desiderati: > summary(my.anova) Df Sum Sq fattoreA 2 0.00240000 fattoreB 2 0.00026667 Residuals 4 0.00033333 --Signif. codes: 0 ‘***’ Mean Sq F value Pr(>F) 0.00120000 14.4 0.01487 * 0.00013333 1.6 0.30864 0.00008333 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 Risultati che ci portano a ritenere che le tre routine abbiano, perlomeno dal punto di vista sta(1) tistico, un diverso comportamento (si rifiuta H0 ), mentre, come auspicabile, non emergono (2) differenze significative circa il comportamento dei PC (si accetta H0 ). ♥ ANOVA per esperimenti a due fattori con replicazioni Nello schema di classificazione illustrato al punto precedente si assumeva l’assenza di interazione tra i fattori A e B. Per potere individuare la presenza di un’eventuale interazione tra i fattori, è necessario disporre di più osservazioni per ciascuna delle r × s situazioni sperimentali. Nel seguito supporremo che ogni cella contenga un ugual numero n > 1 di osservazioni, sı̀ che risultati sperimentali possano essere indicati Y ijk , dove k = 1, 2, . . . , n rappresenta la k-esima osservazione relativa alla ij-esima cella. Possiamo affermare che i valori sperimentali costituiscono determinazioni campionarie di altrettante v.c. Yijk i.i.d. N (µ + αi + βj + λij , σ 2 ). Ricordando che µij. = E[Ȳij. ], µi.. = E[Ȳi.. ], µ.j. = E[Ȳ.j. ], µ = E[Ȳ... ], possiamo esprimere le v.c. Yijk quale combinazione lineare Yijk = µ + αi + βj + λij + -ijk , dove αi = µi.. − µ rappresenta l’effetto del i-esimo livello del fattore A, βj = µ.j. − µ quello del j-esimo livello del fattore B, λij = µij. − µi.. − µ.j. + µ quello dell’effetto congiunto del i-esimo livello del fattore A e del j-esimo livello del fattore B, mentre - ijk sono v.c. i.i.d. N (O, σ 2 ). 197 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Le ipotesi statistiche che sottoponiamo a verifica saranno dunque: H02 : αi = 0, ∀ i H12 : ∃ i : αi 3= 0 (6.42) H02 : βj = 0, ∀ j H12 : ∃ j : βj 3= 0 (6.43) H03 : λij = 0, ∀ i, j H13 : ∃ i, j; i 3= j : λij 3= 0 (6.44) Anche in questo caso, con opportuni passaggi, si può scindere la devianza totale di Yijk nei quattro addendi SSA , SSB , SSAB e SSE , che rappresentano, rispettivamente, la devianza tra i trattamenti, la devianza tra i blocchi, la devianza imputabile all’interazione fra trattamenti e blocchi e la devianza residua. Ai fini dell’ANOVA si tratterà di confrontare le devianze SS A , SSB e SSAB rispetto a SSE ; le statistiche test atte a tal fine sono: SSAB (r − 1) (s − 1) SSE r s (n − 1) SSB s−1 SSE r s (n − 1) SSA r−1 SSE r s (n − 1) che, vere le corrispondenti ipotesi nulle, si ditribuiscono secondo una F di Snedecor con, rispettivamente, (r − 1), (s − 1) e (r − 1) · (s − 1) gradi di libertà a numeratore e r s (n − 1) gradi di libertà a denominatore. Esempio 6.6.3 I responsabili del Controllo di Qualità di un importante lanificio ritengono che le proprietà meccaniche e dimensionali (individuabili ricorrendo a specifici parametri) del tessuto siano influenzate, nel corso del processo di decantissaggio in autoclave, da due particolari fattori; la posizione (fattore A) del tessuto all’interno del cilindro di decantissaggio e la differenza (fattore B) fra pezza e pezza di uno stesso tipo di tessuto. Per verificare tale convinzione venne progettato un esperimento che prevedeva la misurazione dei succitati parametri su campioni di stoffa prelevati casualmente in corrispondenza a diverse combinazioni dei due fattori A e B. In particolare, per ciascun fattore si sono considerati tre livelli e per ciascuna delle nove condizioni sperimentali si sono effettuate cinque misurazioni. Trattasi, manifestamente, di un esperimento a due fattori di classificazione con un ugual numero di osservazioni per cella, di cui il fattore A costituisce il fattore di interesse dell’indagine mentre il fattore B esprime la variabilit, non eliminabile, del processo produttivo. Le ipotesi che si vogliono verificare, limitatamente alla sola grandezza di interesse Y sono: (1) H0 : (2) H0 : (3) H0 : il fattore A non ha alcuna influenza su Y ; il fattore B non ha alcuna influenza su Y ; non esiste interazione tra i fattori A e B. sulla base delle seguenti realizzazioni sperimentali: 198 E. D. Isaia, Linguaggio R e applicazioni statistiche A 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 B 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 Y 476 474 465 477 490 481 487 492 485 469 490 486 473 475 479 A 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 B 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 Y 517 499 501 503 485 491 501 487 504 498 514 495 506 525 503 A 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 B 513 483 507 504 483 501 517 505 495 510 533 514 525 510 504 Y > y<-c(476,474,465,477,490,481,487,492,485,469,490,486,473,475,479, 517,499,501,503,485,491,501,487,504,498,514,495,506,525,503, 513,483,507,504,483,501,517,505,495,510,533,514,525,510,504) > a<-c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3) > b<-c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3, 1,1,1,1,1,2,2,2,2,2,3,3,3,3,3) > dati<-data.frame(fattoreA=factor(a),fattoreB=factor(b),risposta=y) > my.anova<-aov(risposta ~ fattoreA+fattoreB+fattoreA*fattoreB,data=dati) porgono la seguente tabella ANOVA: > summary(my.anova) Df Sum Sq Mean Sq F value Pr(>F) fattoreA 2 6190.0 3095.0 30.1690 2.019e-08 *** fattoreB 2 844.9 422.5 4.1181 0.02452 * fattoreA:fattoreB 4 586.7 146.7 1.4297 0.24407 Residuals 36 3693.2 102.6 --Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 In sostanza siamo portati a credere che i due fattori A e B influenzano singolarmente, ma non congiuntamente la grandezza Y in esame. ♥ 199 Capitolo 7 Elementi di simulazione *** da rifare Affrontiamo, ora, alcuni specifici problemi connessi alla simulazione. Si tratta di semplici esempi di specie che tendono ad illustrare, ancora una volta, le potenzialità del linguaggio di programmazione. 7.1 Sul lancio simultaneo di n monete Con riferimento ad un esperimento casuale che consiste nel lancio simultaneo di n ≥ 1 monete, il numero di Teste apparse può essere descritto mediante una v.c. X che, per cose note, possiede distribuzione binomiale di parametri n e p, per x = 0, 1, . . . , n. Nel seuito ci proponiamo di simulare la ripetizione, poniamo k > 1 volte, di tale esperimento casuale e di ottenere la distribuzione di frequenze empirica del numero di Teste apparse ad ogni lancio. A tal fine definiamo la seguente funzione lancio i cui input sono k, n e p: 1 2 3 4 5 6 7 8 9 > lancio<-function(k,n,p,graph=FALSE) { x<-sort(rbinom(k,n,p)) fi<-diag(table(x,x)) lancio.out<<-list(n.teste=x,detx=unique(x),freq=fi) if(graph) plot(unique(x),fi,type="h",xlim=c(-1,max(unique(x))+1), xlab="Determinazioni x",ylab="Frequenze empiriche") } A commento: — in riga [3] viene definita e generata la sequenza delle determinazioni di X in ciascuna delle k repliche dell’esperimento; E. D. Isaia, Linguaggio R e applicazioni statistiche — in fi immettiamo le frequenze corrispondenti ad ogni valore di xi (riga [4]). Si noti il ricorso all’istruzione table di cui si considerano i valori appartenenti alla sola diagonale principale, essendo nulli altrove; — in riga [5] viene creata la lista lancio.out contenente i risultati della simulazione; — in riga [7] viene proposto, a patto che graph=TRUE, il grafico della distribuzione empirica; si noti che unique(x) porge, in ordine crescente, le possibili determinazioni x = 0, 1, . . . , n di X in ciascuna prova. Cosı̀, ad esempio: > > 0 1 lancio(20,5,.5,graph=FALSE) lancio.out$freq 1 2 3 4 5 3 4 5 5 2 simula il lancio, ripetuto 20 volte, di cinque monete regolari. 7.2 Sulle catene di Markov Si immagini che un gioco consista nel lancio di una moneta e che in caso si ottenga Testa si vincano 100 lire, mentre in caso contrario se ne perdano 100 e che inoltre il gioco abbia termine non appena si siano perse o guadagnate 500 lire. È interessante indagare sui tempi di durata gioco, o perlomeno farsi un’idea della durata media dello stesso. Se, accanto alla v.c. X che indica il numero di Teste ottenute dal lancio, introduciamo le v.c.: g(Xt ) = + −100 +100 Xt = Croce Xt =Testa Ct = + 0 Ct−1 + g(Xt) t=0 t = 1, 2, . . . possiamo modelizzare il gioco quale catena di Markov a tempi discreti definita sugli stati Ei per cui Ct = i, con i = −5, −4, . . . , 4, 5. Gli stati E−5 ed E5 , in accordo alle premesse fatte, sono di tipo assorbente, mentre i restanti sono transienti. La catena proposta, a ben vedere, è la modellizzazione di un ben noto processo stocastico abitualmente detto “passeggiata casuale tra due barriere assorbenti” che si presta, anche in forme alternative a quella presentata, a diverse applicazioni anche in campo economico ed industriale. Se si osserva, poi, che i passaggi tra gli stati E i a Ei+1 o ad Ei−1 avvengono con probabilità p e 1 − p rispettivamente, la matrice dei transizione del primo ordine 201 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 della catena, avendo cura di riordinare gli stati come E −5 , E5 , E−4 , . . . , E4 , verrà ad assumere la forma: 1 0 1 − p 0 0 P= 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p 0 p 0 0 0 0 0 0 0 1−p In sostanza la matrice P può essere vista come: P= : R S W Q 0 0 0 0 0 0 0 0 0 p 0 < dove Q ne rappresenta cosidetta “matrice fondamentale”. Desiderando indagare sulla durata media della “passeggiata”, tralasciando volutamente la ricerca di una soluzione analitica che potremmo individuare ricorrendo ad un’equazione alle differenze con opportuni vincoli, sfruttiamo il seguente risultato, dovuto a Brook, Evans (1982), che consente, appunto di ottenere il vettore dei momenti primi della v.c. TEi che rappresenta il numero di transizioni che occorrono, partendo da un prefissato stato “iniziale” non transiente E i , i = −4, . . . , 4,, per raggiungere uno degli stati assorbenti: µEi = (I − Q)−1 1 Ancor più interessante è analizzare il comportamento di µ Ei , abitualmente detto Average Run Length, al variare di p, cioè sotto l’ipotesi di non correttezza della moneta. A tal fine è suffficiente far variare i valori di p in (0, 1) o meglio, per la simmetria, in (0.5, 1). Per il nostro scopo, ricordando che concentriamo la nostra attenzione al valor medio di TE0 , sono sufficienti le istruzioni che seguono: 1 2 3 > n<-51; p<-.5; q<-1-p > I <- matrix(0,nrow=9,ncol=9); I[row(I)==col(I)] <- 1 > one<-cbind(diag(I)) 202 E. D. Isaia, Linguaggio R e applicazioni statistiche 4 5 6 7 8 9 10 11 12 13 14 15 16 > arl<-real(n) > for (i in 1:n){ Q<-matrix(c(0,q,0,0,0,0,0,0,0,p,0,q,0,0,0,0,0,0, 0,p,0,q,0,0,0,0,0,0,0,p,0,q,0,0,0,0,0,0,0,p,0,q,0,0,0, 0,0,0,0,p,0,q,0,0,0,0,p,0,0,p,0,q,0,0,0,0,0,0,0,p,0,q, 0,0,0,0,0,0,0,p,0),nrow=9,ncol=9) W<-((solve(I-Q))%*%one) arl[i]<-(((solve(I-Q))%*%one))[5,] p<-p+0.01; q<-1-p} > plot(seq(.5,1,by=0.01),arl,type="p",main="",ylab=" A.R.L.", xlab="p=P[X=1]",col="blue") > lines(seq(.5,1,by=0.01),arl,col="red") > grid() A commento, osserviamo: — in riga [2] e [3] definiamo la matrice identità (9x9) ed il vettore colonna unitario; — in riga [4] definiamo l’oggetto arl che conterrà le soluzioni desiderate; — dalla riga [5] alla [12] vi è il ciclo di calcolo vero e proprio. Si noti che arl dovrà contenere il valor medio relativo allo stato E 0 , cioè il quinto elemento dei vettori (I − Q)−1 1 via via calcolati. I risultati ottenuti per i valori di p = 0.50, (0.01), 1 sono: 340.000 61.042 27.579 16.500 11.460 8.729 7.074 5.982 5.210 214.880 51.813 24.963 15.406 10.892 8.397 6.862 5.835 5.102 151.775 44.665 22.741 14.430 10.377 8.092 6.663 5.697 5.000 114.447 39.005 20.837 13.561 9.909 7.808 6.477 5.565 90.155 34.436 19.192 12.784 9.481 7.546 6.302 5.441 73.297 30.691 17.762 12.088 9.089 7.302 6.137 5.322 mentre in figura (7.1) se ne riporta il grafico. 7.3 Sul teorema limite centrale Immaginiamo di estrarre k > 1 campioni di numerosità n da una specifica densità f (x), di calcolare, per ciascuno di essi, il valor medio x̄ e quindi rappresentare graficamente la distribuzione empirica di X̄, che sappiamo distribuirsi asintoticamente secondo una N (µ, σk −1/2 ) e ciò indipendentemente dalla forma di f (x). 203 200 150 0 50 100 A.R.L. 250 300 350 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 0.5 0.6 0.7 0.8 0.9 1.0 p=P[X=1] Figura 7.1: Numero medio di giocate al variare di p in (0.5, 1) A titolo di esempio, posto: densità f (x) = 2−1 , 0 < x < 2 n 5 k 2000 il problema può essere risolto semplicemente ricorrendo alle istruzioni: > > > > k<-2000 medie.x<-real(k) for (i in 1:k) {x<-runif(5,0,2); medie.x[i]<-mean(x)} hist(medie.x,breaks=20,freq=FALSE,main="",xlab="Medie campionarie", ylab="Frequenze empiriche",col="lightgray",xlim=c(0,2)) In figura (7.2) è riportato l’istogramma dei risultati dalla simulazione. Una variante, lasciando al Lettore il “gusto” della programmazione, potrebbe essere quella di ripetere la simulazione proposta per diversi valori di k. A titolo di esempio in figura (7.3) riportiamo i risultati di una simulazione caratterizzata da: 204 1.0 0.5 0.0 Frequenze empiriche 1.5 E. D. Isaia, Linguaggio R e applicazioni statistiche 0.0 0.5 1.0 1.5 2.0 Medie campionarie Figura 7.2: Distribuzione delle medie campionarie densità f (x) = 2−1 , 0 < x < 20 7.4 n 5 k 10i , i = 1, 2, 3, 4 Sulla funzione di ripartizione empirica Dato un campione casuale ordinato (X(1) , X(2) , . . . , X(n) ) tratto da una v.c. X, la funzione di ripartizione empirica o campionaria, F n (x), è definita: Fn (x) = 0 i/n 1 x < X(1) X(1) ≤ x < X(n) x ≥ X(n) Evidentemente trattasi di una funzione a “scalini” che si avvicina alla funzione di ripartizione F (x) della v.c. X; nel caso sia vera l’ipotesi che il campione provenga da X, le differenze Fn (x) − F (x) sono da attribuirsi unicamente al caso. Per inciso, osserviamo che tali considerazioni costituiscono la base dei cosiddetti test basati sulla funzione di distribuzione empirica (EDF test), tra i quali merita un 205 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 1.0 1.5 2.0 1.5 1.0 0.5 2.0 0.0 0.5 1.0 1.5 Medie campionarie k=1000 k=10000 1.0 1.5 2.0 1.0 0.5 0.0 Frequenze empiriche 1.0 0.5 0.5 0.0 Medie campionarie 2.0 1.5 Medie campionarie 0.0 0.0 0.0 Frequenze empiriche 1.5 2.0 1.0 0.5 0.5 1.5 0.0 Frequenze empiriche k=100 0.0 Frequenze empiriche k=10 0.5 1.0 1.5 2.0 Medie campionarie Figura 7.3: Distribuzione delle medie campionarie posto, per cosı̀ dire, di primo piano, perlomeno dal punto di vista storico, quello di Kolmogorov-Smirnov. Riprendendo in parte quanto detto in (7.3), la funzione di ripartizione empirica della ( v.c. media campionaria, X̄ = k −1 ki=1 X̄i , dovrebbe, per k ↑ ∞, avvicinarsi a quella di una N (µ, σk −1/2 ). A titolo illustrativo, si immagini di aver tratto k > 1 campioni di numerosità n da una distribuzione Uniforme in (80, 120) e di aver calcolato, per ciascuno di essi, il valor medio x̄ e di volere rappresentare graficamente sia la funzione di ripartizione empirica Fk (x̄) sia quella di una N (µ = 100, 10k −1/2 ). A tal fine, scelto arbitrariamente di porre k = 30 ed n = 20, sono sufficienti le seguenti istruzioni: > k<-30 > n<-20 206 E. D. Isaia, Linguaggio R e applicazioni statistiche > > > > > > > medie.x<-real(k) Femp<-real(0) for (i in 1:k) {medie.x[i]<-mean(runif(20,80,120))} medie.x<-sort(medie.x) Fteor<-pnorm(medie.x,100,10/sqrt(k)) for (i in 1:k){Femp<-append(Femp,i/k)} plot(medie.x,Femp,type="s",main="",ylab="Funzione di ripartizione empirica e teorica",xlab="Determinazioni campionarie",col="blue") > lines(medie.x,Fteor,col="red") > grid() 1.0 0.8 0.6 0.4 0.2 0.0 Funzione di ripartizione empirica e teorica L’andamento delle due funzioni di ripartizione è proposto in figura (7.4). 96 98 100 102 104 Determinazioni campionarie Figura 7.4: Funzioni di ripartizione empirica e teorica 207 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 7.5 Sul bootstrap Nel seguito descriviamo come sia possibile raggiungere alcuni semplici risultati concernenti la tecnica bootstrap. Tale tecnica non-parametrica, com’è noto, viene applicata ad uno stimatore θ̂(x1 , x2 , . . . , xn ) mediante il ricampionamento con rimessa effettuato k > 1 volte della n−pla campionaria osservata (x 1 , x2 , . . . , xn ) in modo da ottenere altrettanti campioni bootstrap (x∗1 , x∗2 , . . . , x∗n ) su ciascuno dei quali verrà calcolato θ̂ ∗ = θ̂(x∗1 , x∗2 , . . . , x∗n ). La distribuzione dei valori θ ∗ servirà quale base per la stima del parametro θ. Per maggiori ragguagli, il Lettore può consultare il testo, assai ricco di spunti ed esempi applicativi, di Efron, Tibshirani (1993). Vediamo ora come sia possibile applicare tale tecnica perlomeno nel caso di stima del valor medio µ. Pertanto, dati i seguenti valori campionari: 8.00 8.34 8.45 8.50 8.00 8.35 8.49 8.50 8.00 8.35 8.49 8.50 8.15 8.36 8.49 8.52 8.20 8.40 8.50 8.70 8.25 8.40 8.50 8.75 8.25 8.40 8.50 8.78 8.30 8.40 8.50 7.51 8.30 8.40 8.50 7.75 8.34 8.00 8.50 7.90 definiamo, ora, il massimo numero di itrazioni desiderate (maxloop) e al contempo l’oggetto medie.bootstrap che conterrà, appunto, le medie bootstrap via, via ottenute, mediante le istruzioni: > maxloop<-5000; medie.bootstrap<-real(maxloop) A questo punto, procediamo all’estrazione con rimessa di 5.000 campioni casuali estratti senza rimessa da (x1 , x2 , . . . , xn ) e, per ciascuno di essi, calcoliamo il valor medio che inseriamo in media.bootstrap. A ciò sopperisce il ciclo: > for(i in (1:maxloop)) { medie.bootstrap[i]<-mean(sample(x,replace=TRUE)) } > hist(medie.bootstrap,xlim=c(8.1,8.5),breaks=20,main="", xlab="Medie Boostrap",ylab="Frequenze empiriche",col="lightblue") In figura (7.5) riportiamo l’istogramma dei risultati ottenuti che sintetizziamo in: originale bootstrap valor medio 8.338 8.340044 deviazione standard 0.2592019 0.04044345 208 errore standard 0.04098342 0.0005719567 400 300 200 100 0 Frequenze empiriche 500 E. D. Isaia, Linguaggio R e applicazioni statistiche 8.1 8.2 8.3 8.4 Medie Boostrap Figura 7.5: Risultati del bootstrap 209 8.5 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 7.6 La libreria rnotes e gli archivi di dati Per completezza e a vantaggio dell’utente si è pensato di raccogliere tutte le funzioni presentate nel corso della trattazione nella libreria rnotes posta nella directory ...\library\rnotes\R; parimenti la directory \library\rnotes\data conetiene tutti gli archivi di dati *** formato *** 7.7 Esercizi vari Riportiamo nel seguito, in modo piuttosto informale, alcuni esercizi che possono essere risolti facilmente in R ed offrono, confidiamo, spunto per ulteriori applicazioni. Esercizio 7.7.1 Calcolare la media aritmetica, la media quadratica e la media armonica dei seguenti valori: 12, 10, 11, 11, 12, 13, 15, 16, 17, 10. ♥ Esercizio 7.7.2 Calcolare la mediana e la varianza dei valori riportati in (7.7.1). ♥ Esercizio 7.7.3 Dato l’oggetto x contenente i primi dieci interi consecutivi, ridefinirlo in modo che esso contenga gli stessi elementi, la loro media e quindi gli stessi elementi ancora ma ordinati in senso decrescente. ♥ Esercizio 7.7.4 A partire dalle seguenti osservazioni individuali: 12 10 11 12 13 14 14 13 15 10 12 11 10 11 costruire una tabella di frequenze relative. ♥ Esercizio 7.7.5 Dati i valori {20, 21, 24, 20, 21, 23, 24, 25, 27, 30, 25}, creare un oggetto che contega le frequenze relative cumulate di essi. ♥ Esercizio 7.7.6 Date le seguenti osservazioni individuali: sesso: Prov: M To M To M Cn F At F To M At F Vc M To F Cn F At F AL costruire una tabella doppia di frequenze relative. Esercizio 7.7.7 Rappresentare graficamente nel piano (x, y) la funzione y 2 = x2 (1 − x2 ). 210 M Vc F Cn ♥ ♥ E. D. Isaia, Linguaggio R e applicazioni statistiche Esercizio 7.7.8 Rappresentare graficamente nel piano (x, y) la funzione y 2 = x1/2 (1 − x1/2 ). ♥ Esercizio 7.7.9 Dati: " x = 0.8 0.2 # 0.2 0.8 Y = 0.3 0.7 0.5 0.5 calcolare Z = xY e, successivamente, Zxt . ♥ Esercizio 7.7.10 Una mutabile statistica doppia presenta la seguente distribuzione congiunta: B/A b1 b2 b3 a1 2 4 10 a2 5 6 9 a3 7 7 6 a4 10 7 4 a5 12 9 2 a6 15 10 1 individuare le distribuzioni marginali dei due caratteri A e B e rappresentarle mediante un diagramma a torta. ♥ Esercizio 7.7.11 Con riferimento all’Esempio posto in (7.7.10), costruire la tabella doppia delle frequenze relative. ♥ Esercizio 7.7.12 Con riferimento all’Esempio posto in (7.7.10), individuare le distribuzioni condizionate A|B = bi , con i = 1, 2, 3. ♥ Esercizio 7.7.13 Le misurazioni del peso (Kg) e dell’altezza (cm) effettuate su un gruppo di individui di sesso maschile porgono la seguente tabella a doppia entrata: Altezza/Peso 140-150 150-160 160-150 170-180 180-190 50-60 5 4 2 1 0 60-70 2 12 12 2 0 70-80 1 7 13 8 10 80-90 0 1 11 10 15 Si costruiscano, a partire da essa, le matrici di varianza-covarianza e di correlazione. ♥ Esercizio 7.7.14 Con riferimento alla situazione di cui al punto (7.7.13), si rappresenti nel piano (x, y) la spezzata di regressione e si proceda, altresı̀ al calcolo di η. ♥ 211 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Esercizio 7.7.15 Sia Data la seguente matrice delle varianze-covarianze: 2 1 3 CovX,Y = 1 4 1 2 1 2 estrarre da essa gli elementi per cui risulta ρX,Y ≥ 0.35. ♥ Esercizio 7.7.16 Si risolva il seguente sistema di equazioni: O 1.2x + 2.5y − z = 10 2.5x − 1.5y + z x+y+z = -10 =0 e si verifichi la correttezza dei risultati ottenuti. ♥ Esercizio 7.7.17 Rappresentare graficamente la funzione di ripartizione di una variabile casuale (v.c.) con distribuzione Binomiale di parametri n = 10 e p = .5 ♥ Esercizio 7.7.18 Rappresentare graficamente le funzioni di densità di probabilità di una v.c. con distribuzione Binomiale di parametri n = 10 e p = .75 ♥ Esercizio 7.7.19 Posto X una v.c. con distribuzione Binomiale di parametri n = 50 e p = .15, calcolare la probabilità attinente agli eventi {0 < X < 20} e {X ≥ 20}. ♥ Esercizio 7.7.20 Si rappresentino graficamente le v.c. χ2 con, rispettivamente, 10, 20, 30 e 40 gradi di libertà. ♥ Esercizio 7.7.21 Generare un campione casuale di dimensione n = 20 tratto da una densità Normale di parametri µ = 100 e σ 2 = 25 e calcolarne il valor medio x̄. ♥ Esercizio 7.7.22 Generato un campione casuale di dimensione n = 50 tratto da una densità Uniforme in (20, 35), costruire l’intervallo di confidenza per il valor medio µ al 98.6%. ♥ Esercizio 7.7.23 Generare un campione casuale di dimensione n = 60 tratto da una densità bimodale. ♥ Esercizio 7.7.24 Con riferimento all’Esempio (7.7.23), si costruisca un’istogramma con 4 (7) (10) classi di egual modulo e ad esso si sovraimponga il grafico di una Normale di parametri (µ̂, σ̂ 2 ) stimati in base ai valori campoionari ottenuti. ♥ 212 E. D. Isaia, Linguaggio R e applicazioni statistiche Esercizio 7.7.25 I valori che seguono rappresentano i tassi medi di interesse sui obbligazioni triennali applicati da 29 diverse banche in un periodo di sei mesi: 8.40 8.00 8.33 8.50 8.00 7.56 8.51 8.00 7.57 7.82 8.05 7.71 7.82 8.05 8.55 7.90 8.06 8.57 8.00 8.11 8.65 8.65 8.17 8.00 8.71 8.30 8.00 8.00 8.33 Si costruisca e si visualizzi la funzione di ripartizione empirica Fn (x). ♥ Esercizio 7.7.26 Con riferimento ai dati di cui al punto (7.7.25), si analizzi graficamente la trasformata “integrale” Y = Fn (x). ♥ Esercizio 7.7.27 Da un’indagine condotta su 100 famiglie residenti in provicia di XX, i rediti mensili netti sono (x 1000 lit.): 3092.547 3190.741 2973.432 2866.213 3467.562 3261.697 3358.325 3306.863 2871.082 3452.798 3434.806 3285.799 3504.032 3627.119 3265.104 3616.714 3937.908 3469.574 3188.127 3367.155 2883.179 3578.601 2988.463 2970.571 3538.944 2957.559 3689.683 3300.451 3338.512 2870.496 2979.124 3522.844 3056.764 2982.205 3648.595 3143.831 2936.208 3312.634 3467.826 3595.635 3043.293 2907.338 3410.187 3212.386 2849.832 3580.035 3207.700 3132.004 3377.674 3391.259 3056.114 2966.232 3315.047 3492.316 2931.252 3214.972 3514.857 2615.924 3425.463 2860.557 3403.109 3277.373 3363.479 3306.835 3002.333 2979.684 3760.060 3670.399 3792.698 3065.804 3089.623 3593.312 3556.721 3297.671 3153.467 3388.534 3555.429 3048.985 3537.857 3219.749 3481.956 3353.335 3233.259 2970.686 3341.397 3076.497 3050.536 2900.712 3270.383 3126.800 3531.567 3151.945 3344.409 3334.146 3206.523 3883.942 3451.231 3042.290 2866.378 3310.131 Si costruiscano e si visualizzino la funzione di ripartizione empirica Fn (x) e la funzione di ripartizione di una v.c. Normale con parametri µ = x̄ e σ = s. “Ad occhio” è plausibile ipotizzare la normalità della distribuzione del reddito sulla base del campione sorteggiato? ♥ Esercizio 7.7.28 Approntare una funzione che, rispetto ad un vettore di dati x, porga il grafico della curva di concentrazione del Lorenz con, a lato, il valore dell’indice del Gini. ♥ 213 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 Esercizio 7.7.29 Si scriva una funzione che consenta di individuare la matrice delle contingenze delle seguente tabella a doppia entrata: B/A b1 b2 a1 22 4 a2 15 10 a3 10 17 a4 6 27 e si verifichi che essa è a somma nulla. ♥ Esercizio 7.7.30 Si immagini che le misurazioni di una certa grandezza di interesse (Y ) siano influenzate dai possibili livelli di un fattore (X). Un eseprimento atto a verificare tale ipotesi, ha fornito i seguenti risultati: X↓ x1 x2 x3 x4 110.2 111.5 109.7 112.3 Y 109.2 112.1 109.8 111.1 112.0 111.9 110.1 112.2 110.7 111.9 110.2 110.7 111.2 112.0 111.1 111.6 Approntare una funzione che, per ciascun livello del fattore, porga valor medio, scarto quadratico medio, numero di misurazioni e l’intervallo di confidenza al livello 1 − β1 . ♥ Esercizio 7.7.31 Al fine di analizzare il consumo di carburante (miglia x gallone) di un nuovo tipo di autovettura, è stato approntato un’esperimento che prevedeva l’impiego di quattro autovetture A, B, C e D ed altrettanti piloti a, b, c e d e l’assegnazione, in ciascuno dei quattro turni di prove, dei piloti alle autovetture. I risultati ottenuti sono: turno 1 2 3 4 A 9.44 9.61 9.06 8.71 B 9.83 9.22 9.02 9.02 C 9.02 9.39 9.88 9.23 D 9.68 8.76 8.88 9.73 Si proceda all’analisi della varianza ed alla verifica dell’ipotesi che il consumo di carburante non sia influenzato dal particolare pilota; ♥ Esercizio 7.7.32 Si approntino due funzioni che consentano la stima dei parametri dei modelli: — — Y = β1 + β I]10,∞) x + * Y = α + β x2 + * ♥ 214 E. D. Isaia, Linguaggio R e applicazioni statistiche Esercizio 7.7.33 Si costruisca una funzione che simuli il lancio ripetuto poniamo n > 1 volte di una moneta. Ciò ipotizzando che la moneta sia regolare e sia che essa risulti irregolare. ♥ Esercizio 7.7.34 Si scriva una funzione che consenta di individuare la distribuzione dell’ipotenusa di un triangolo rettangolo le cui misure dei cateti siano determinazioni di altrettante v.c. i.i.d secondo una Uniforme di parametri a = 11 e b = 14. ♥ Esercizio 7.7.35 Si immagini di lanciare quattro monete e di ripetere l’esperimento finché: o si ottiene una sequenza di quattro Teste o quattro Croci, oppure si ottengono in successione due sequenze contenenti un egual numero di Croci e Teste. Si appronti una funzione che consenta il calcolo della durata media del gioco, tenendo conto della possibilità che le monete siano truccate. (Si modellizzi l’esperimento sottoforma di catena di Markov ...) ♥ Esercizio 7.7.36 Si metta a punto una routine che consenta, mediante la tecnica boostrap, di ottenere una stima per il parametro ignoto σ e ciò sulla base della n−pla campionaria: {10.1, 11.0, 10.5, 11.7, 12.5, 10.2, 10.7, 12.9, 12.4} ♥ Esercizio 7.7.37 Con riferimento al punto (7.7.36), si costruisca un intervallo di confidenza per σ al livello 1 − α = .90(.01).95. ♥ 215 Bibliografia BARTLETT, M. S.,Properties of sufficiency and statistical tests, Proceedings of the Royal Statistical Society, Series A, 160, 268-282, 1937 BELSLEY, D. A., KUH, E., WELSCH, R. E., Regression Diagnostics,John Wiley, New York, 1980 BOWMAN A.W., AZZALINI A. (1997), Applied Smoothing Techniques for Data Analysis. The Kernel Approach with S-Plus, Clarendon Press, Oxford BRENT R., Algorithms for Minimization without Derivatives, BROOK D., EVANS D.A., An Approach to the Probability Distribution of CUSUM Run Length, Biometrika, 59, 539-549, 1982 Prentice Hall, Englewood Cliffs, New Jersey, 1973 CHAMBERS J. M., HASTIE T. J., Statistical models in S, Chapman and Hall, New York, 1992 CLEVELAND, W. S., LOWESS: A Program for Smoothing Scatterplots by Robust Locally Weighted Regression, The American Statistician, 35, 54, 1981 COOK, R. D., WEISBERG, S., Residuals and Influence in Regression, Chapman and Hall, London, 1982 DONGARRA, J. J., BUNCH J. R., MOLER C. B., STEWART G. W., LINPACK Users Guide, SIAM Publications, Philadelphia, 1978 EFRON B., TIBSHIRANI R., An Introduction to the Bootstrap, Chapman and Hall, New York, 1993 GARTSIDE P.S., A Study of Methods for Comparing Several Variances, Journal of The Ametican Statistical Association, 67, 1972 GENTLEMAN E., IHAKA R., Notes on R: A Programming Environment for Data Analysis and Graphics, Dep. of Statistics, Univeristy of Auckland, 1997 E. D. Isaia, Linguaggio R e applicazioni statistiche GIBBONS J.D., PRATT, J.W., P-Values: Interpretation and Methodology, The American Statistician, 29, 1975, IHAKA R., GENTLEMAN E., R: A Language for Data Analysis and Graphics, Journal of Computational and Graphical Statistics, 5, 299-314, 1996 MARSAGLIA, G., A Random Number Generator for C, Discussion paper, Usenet newsgroup ‘sci.stat.math’ on September 29, 1997. McCULLAGH, P., NELDER, J. A., Generalized Linear Models, Chapman & Hall, II Edition, New York, 2000. R Core Team, R Reference Index,The R Core Team, 2000 SAPORTA G., Probabilités, Analyse des Données et Statistique, Édition Technip, Paris, 1990 SCHERVISH J. M., Theory of Statistics, Springer-Verlag, New York, 1997 SHAO J., Mathematical Statistics, Springer-Verlag, New York, 1999 VENABLES W.N., RIPLEY B.D., Modern Applied Statistics with S-Plus, Springer, New York, 2nd edition, 1997 VENABLES B., SMITH D., Notes on R: A Programming Environment for Data Analysis and Graphics, Dep. of Statistics, Univeristy of Adelaide, 1992 WAND M.P., JONES M.C. (1995), Kernel Smoothing, Chapman & Hall, London WICHMANN, B. A., HILL I. D., Algorithm AS 183: An Efficient and Portable Pseudo-random Number Generator, Applied Statistics, 31, 188-190, 1982 217 Indice 1 Introduzione ad R 1.1 L’ambiente di lavoro . . . . . . . . . . . . . . . . . . . . 1.2 Primi passi in R . . . . . . . . . . . . . . . . . . . . . . 1.2.1 Creazione di oggetti elementari . . . . . . . . . . 1.2.2 Creazione di oggetti contenenti sequenze regolari 1.2.3 Manipolazione di oggetti elementari . . . . . . . 1.2.4 Operatori aritmetici e funzioni matematiche . . . 1.2.5 Su alcune funzioni statistiche . . . . . . . . . . . 1.2.6 Alcune funzioni di utilità generale . . . . . . . . 1.3 Vettori e Matrici . . . . . . . . . . . . . . . . . . . . . . 1.4 Oggetti complessi . . . . . . . . . . . . . . . . . . . . . . 1.4.1 Liste . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.2 Data frame . . . . . . . . . . . . . . . . . . . . . 1.5 Modalità e struttura di un’oggetto . . . . . . . . . . . . 1.6 Funzioni definibili dall’utente . . . . . . . . . . . . . . . 1.7 Su alcune funzioni matematiche . . . . . . . . . . . . . . 1.8 Lettura e registrazione di archivi . . . . . . . . . . . . . 1.8.1 I comandi scan() e write() . . . . . . . . . . . 1.8.2 I comandi read.table() e write.table() . . . 1.8.3 Il comando data() . . . . . . . . . . . . . . . . . 1.9 Personalizzazione dell’ambiente di lavoro . . . . . . . . . 1.10 Le librerie e loro gestione . . . . . . . . . . . . . . . . . 2 Cenni sulle procedure grafiche 2.1 Funzioni grafiche di “primo livello” . . . . . 2.1.1 Funzione plot(x,y) . . . . . . . . . 2.1.2 Funzione matplot(x,y) . . . . . . . 2.1.3 Funzione hist(x) . . . . . . . . . . 2.1.4 Funzione boxplot(x,y,z,...) . . . 2.1.5 Funzioni qqplot(x,y) e qqnorm(x) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 4 4 6 8 11 13 15 24 34 34 36 37 39 44 48 48 49 50 51 53 . . . . . . 55 55 55 57 57 58 59 Dipartimento di Statistica e Matematica “Diego de Castro”, nota tecnica 2, 2OO1 2.1.6 Funzione barplot(x) e piechart(x) . . . 2.1.7 Funzione polygon(x,y) . . . . . . . . . . . 2.1.8 Funzione curve(espressione) . . . . . . . 2.1.9 Funzione grid(nx,ny) . . . . . . . . . . . . 2.1.10 La funzione rect(xmin,xmax,ymin,ymax) . 2.1.11 Funzione persp(x,y,z) . . . . . . . . . . . 2.1.12 Funzione pairs(x) . . . . . . . . . . . . . . 2.1.13 Altre funzioni grafiche . . . . . . . . . . . . Funzioni grafiche di “secondo livello” . . . . . . . . Parametri grafici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 59 60 60 60 61 62 63 63 64 3 Argomenti di statistica descrittiva 3.1 Mutabili e variabili statistiche univariate . . . . . . 3.1.1 Costruzione di semplici tabelle di frequenze 3.1.2 Rappresentazioni grafiche . . . . . . . . . . 3.1.3 Su alcune misure di sintesi . . . . . . . . . . 3.1.4 Sulla concentrazione . . . . . . . . . . . . . 3.2 Mutabili e variabili statistiche bivariate . . . . . . 3.2.1 Tabelle di frequenze doppie . . . . . . . . . 3.2.2 L’indice di dipendenza chi-quadro . . . . . 3.2.3 L’indice di dipendenza in media . . . . . . . 3.2.4 Sulla correlazione lineare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 68 68 72 80 89 89 89 89 89 89 4 Elementi di calcolo delle probabilità 4.1 Semplici esercizi sul calcolo delle probabilità . . . . . . . . . . . . . . . 4.2 Generazione di numeri pseudo-casuali . . . . . . . . . . . . . . . . . . 4.3 Il campionamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 110 114 117 5 Elementi di statistica inferenziale 5.1 Intervalli di confidenza per un parametro θ . . . . . . . . . . . . . . . 5.2 Verifica di ipotesi statistiche . . . . . . . . . . . . . . . . . . . . . . . . 5.3 La libreria ctest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 120 129 135 6 Alcune note sui modelli lineari 6.1 La regressione lineare semplice: il modello teorico . . . . . . . . . . . 6.2 La regressione lineare . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Stima della retta di regressione in base ai valori campionari . 6.2.2 Verifiche di ipotesi circa i parametri della retta di regressione 6.2.3 Alcune considerazioni circa la previsione . . . . . . . . . . . . 6.2.4 Alcune considerazioni sull’analisi dei residui . . . . . . . . . . 6.3 La regressione lineare semplice in R . . . . . . . . . . . . . . . . . . 155 155 156 157 159 162 163 164 2.2 2.3 2 . . . . . . . E. D. Isaia, Linguaggio R e applicazioni statistiche 6.4 6.5 6.6 6.3.1 La funzione lm(): definizione del modello di regressione . . . . 164 6.3.2 La funzione lm(): oggetti creati in modo automatico . . . . . . 167 6.3.3 La funzione lm(): verifiche di ipotesi sulle stime . . . . . . . . 168 6.3.4 La funzione predict.lm(): intervalli di confidenza e di previsione171 6.3.5 Per un’analisi dei residui . . . ,. . . . . . . . - . . . . . . . . . . . 173 Sulla regressione multipla: il modello y, X β, σ 2 In . . . . . . . . . . 175 6.4.1 Stima e verifica di ipotesi sui parametri del modello . . . . . . 176 6.4.2 Sul coefficiente di correlazione multipla . . . . . . . . . . . . . 179 6.4.3 Sulla previsione e l’analisi dei residui . . . . . . . . . . . . . . . 181 6.4.4 Sulla multicollinearità . . . . . . . . . . . . . . . . . . . . . . . 182 La regressione multipla in R . . . . . . . . . . . . . . . . . . . . . . . . 183 6.5.1 Definizione del modello e l’istruzione model.matrix(lm(...)) 183 6.5.2 Ridefinizione del modello: l’istruzione update(lm(...)) . . . . 186 6.5.3 Sulla multicollinearità e la stepwise regression . . . . . . . . . . 187 L’analisi della varianza . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 7 Elementi di simulazione *** da rifare 7.1 Sul lancio simultaneo di n monete . . 7.2 Sulle catene di Markov . . . . . . . . . 7.3 Sul teorema limite centrale . . . . . . 7.4 Sulla funzione di ripartizione empirica 7.5 Sul bootstrap . . . . . . . . . . . . . . 7.6 La libreria rnotes e gli archivi di dati 7.7 Esercizi vari . . . . . . . . . . . . . . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 200 201 203 205 208 210 210