Sei sulla pagina 1di 103

Materiale didattico del corso

Tecniche di Analisi dei Dati

CLaM.EPE
Anno Accademico 2013–2014

Autore: Prof. Paola Bortot


Capitolo 1

Introduzione a R

1.1 Che cos’è R


R è un linguaggio statistico freeware per la manipolazione, l’analisi e la
rappresentazione grafica dei dati, nato come estensione del linguaggio S (da
cui trae origine anche il pacchetto commerciale S-PLUS). Una copia gratuita
di R può essere scaricata all’indirizzo web

http://cran.r-project.org

dove è possibile recuperare anche diversa documentazione, incluso un ma-


nuale introduttivo.

1.2 Iniziare e chiudere una sessione di R


Per iniziare una sessione di R fare un doppio click con il mouse sull’icona di
R. Una volta avviato R, apparirà una nuova finestra con il prompt

>

che indica che l’ambiente è pronto a ricevere istruzioni.


Per uscire da R, dal prompt > si digita il comando q() oppure si seleziona
con il mouse l’icona File della linea dei comandi e si sceglie Exit. L’uscita
dall’ambiente determina la comparsa del messaggio Save workspace image?.
Se la risposta è sı̀, le modifiche apportate durante la seduta vengono salvate
sul file di lavoro e R viene chiuso; in questo modo tutti gli oggetti creati
durante la seduta di lavoro potranno essere recuperati nelle sedute successive.
Se la risposta è no, l’ambiente viene chiuso senza alcun salvataggio; se viene
scelto Annulla si ritorna al prompt di R.
R dispone di un ottimo sistema di aiuto in linea a cui si può accedere
selezionando, ad esempio, l’opzione Html help dal menu Help.

1
1.3 Un pò di aritmetica, matematica e logi-
ca...
Gli operatori aritmetici vengono usati in R in modo analogo ad una calco-
latrice: + per l’addizione, - per la sottrazione, * per la moltiplicazione, /
per la divisione e ^ per l’elevamento a potenza. Per definire un’espressione
algebrica è necessario usare le parentesi tonde. Ad esempio,

> 7+2*3
[1] 13
> (7+2)*3
[1] 27

Si noti che in R qualunque cosa venga scritta al prompt viene valutata.

> 3/2^2
[1] 0.75
> (3/2)^2
[1] 2.25
> (2+1)^(1/2)
[1] 1.732051

Per la radice quadrata, in alternativa a ^(1/2), si può usare la funzione sqrt:

> sqrt(2+1)
[1] 1.732051

R mette a disposizione molte funzioni matematiche. Tutte le funzioni


matematiche richiedono che l’argomento sia specificato tra parentesi tonde;
alcuni esempi sono:

> log(5)
[1] 1.609438
> log10(6)
[1] 0.7781513
> exp(3)
[1] 20.08554
> abs(-5)
[1] 5
> cos(pi)
[1] -1

Il comando pi restituisce la costante fondamentale π = 3.14 . . ..


Le funzioni possono essere annidate:

2
> exp(sqrt(30/2))
[1] 48.08563

Gli operatori di confronto sono: < per minore, > per maggiore, <= per
minore o uguale, >= per maggiore o uguale, == per uguale e != per diverso.
Il confronto restituisce una risposta logica, ad esempio

> 4>2
[1] TRUE
> 4>5
[1] FALSE
> 5!=5
[1] FALSE

1.4 Assegnazioni di valori


Si può salvare un valore assegnandolo ad una variabile mediante il comando
<-

> x<-sqrt(2)

o in modo abbreviato con

> x=sqrt(2)

Per visualizzare il contenuto di una variabile basterà digitare il nome della


variabile stessa:

> x
[1] 1.414214

Il valore di una variabile può essere modificato in qualsiasi momento tramite


una nuova assegnazione. Ad esempio, si può assegnare il nuovo valore 4 a x:

> x<-4
> x
[1] 4

C’è differenza tra l’uso delle lettere maiuscole e minuscole per i nomi sia
delle variabili che delle funzioni; pertanto, x e X rappresentano due variabili
diverse.
Possiamo assegnare ad una variabile anche valori logici e stringhe di
caratteri

3
> y<-x>5
> y
[1] FALSE
> Y<-x<= 5
> Y
[1] TRUE
> z<-"Esempio"
> z
[1] "Esempio"
Per ottenere l’elenco di tutti gli oggetti presenti nell’area di lavoro si usa
il comando ls():
> ls()
[1] "x" "y" "Y" "z"
Per cancellare una variabile ci si avvale della funzione rm; ad esempio, con
> rm(x)
viene cancellata la variabile x. Per cancellare più di una variabile, basterà
dare come argomento di rm l’elenco delle variabili separate da una virgola.
> rm(y,Y)
> ls()
[1] "z"

1.5 Salvataggio dei dati


Come accennato nel paragrafo 1.2, al termine di una sessione, R ci chiede se
vogliamo salvare il nostro lavoro. Se diamo una risposta positiva tutto ciò
che abbiamo creato e modificato verrà salvato su un unico file (tipicamente
chiamato .RData) nella directory di lavoro, che se non altrimenti specificato
è la directory da cui R viene avviato.
Per salvare i dati in una directory personale, seguiamo questa procedu-
ra. Creiamo una directory personale sul disco fisso, ad esempio la directo-
ry mywork su C:. Da R selezioniamo l’opzione Save Workspace dal menu
File. Nella finestra che apparirà si selezioni la directory mywork di C:, la-
sciando inalterato il nome del file .RData, quindi si selezioni l’opzione Salva.
Abbiamo, cosı̀, salvato i nostri dati nel file .RData della directory mywork.
Per rendere mywork la directory di lavoro per tutta la restante sessione
si selezioni l’opzione Change dir dal menu File e nella finestra che apparirà
si specifichi la directory mywork di C:. In questo modo, quando al termine
della sessione daremo una risposta affermativa alla richiesta di salvataggio dei

4
dati, il nostro lavoro verrà direttamente salvato nel file .RData della directory
mywork.
Per le sessioni successive, se clicchiamo due volte con il mouse sul file
.RData della directory mywork, non solo R verrà avviato automaticamente,
ma caricherà tutti i dati che avevamo precedentemente salvato in .RData e
userà mywork come directory di lavoro. Questo è il metodo consigliato per
l’apertura delle successive sessioni di R .
I comandi dati durante una sessione sono mantenuti in memoria e pos-
sono essere richiamati usando la freccia ‘su’. Se in qualsiasi momento si
vuole salvare il trascritto della sessione, scegliere Save History dal menu Fi-
le. I comandi vengono cosı̀ salvati su un file di testo (tipicamente chiamato
.Rhistory) nella directory di lavoro a cui possiamo accedere per richiamare
comandi dati precedentemente. In alternativa, si può copiare e incollare i
comandi su un file di testo tramite un editor, quale Notepad.

1.6 I vettori
1.6.1 Creazione di un vettore
I vettori possono essere creati in modi diversi. Il più frequente è tramite la
funzione c che esegue una concatenazione degli oggetti elencati:

> x<-c(1,2,3)
> x
[1] 1 2 3
> y<-c(1,6)
> z<-c(x,y)
> z
[1] 1 2 3 1 6

Le successioni di numeri possono essere create con il comando a:b, ad


esempio con

> x<-1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10

creiamo un vettore che contiene la successione di numeri da 1 a 10 con un


passo di 1. Un’altra funzione per creare successioni è seq che permette una
maggiore flessibilità rispetto a :. Per esempio con

> seq(1,9,by=2)
[1] 1 3 5 7 9

5
creiamo un vettore che contiene la successione di numeri da 1 a 9 con un
passo di 2, mentre con
> seq(8,20,length=6)
[1] 8.0 10.4 12.8 15.2 17.6 20.0
creiamo un vettore di lunghezza 6 che contiene la successione di numeri da
8 a 20 (il passo è determinato automaticamente da R per raggiungere la
lunghezza prescelta).
Gli ultimi due esempi mostrano come le funzioni in R possano avere ar-
gomenti opzionali. Ad esempio, per seq sono opzioni la lunghezza del passo,
specificata tramite by, o la lunghezza totale della successione, specificata tra-
mite length (non ha senso usare entrambe). Se le opzioni sono omesse, R
fa una scelta di default. Con seq il default è prendere un passo pari a 1,
cosı̀ seq(1,10) produce lo stesso risultato di 1:10. Per avere dettagli sulle
opzioni disponibili per ogni funzione e sulle scelte di default avvalersi sempre
del Help di R.
Una funzione utile per creare un vettore in cui siano ripetuti degli schemi
è rep. Ad esempio,
> x<-rep(1,10)
> x
[1] 1 1 1 1 1 1 1 1 1 1
> x<-rep(c(1,5),3)
> x
[1] 1 5 1 5 1 5
> y<-c(rep(2,3),4,5,rep(1,5))
> y
[1] 2 2 2 4 5 1 1 1 1 1
I vettori possono essere anche di stringhe di caratteri o logici. Ad esempio,
> y<-c("questo", "e", "un esempio")
> y
[1] "questo" "e" "un esempio"
> z<-c(5<2,3>1,1==0)
> z
[1] FALSE TRUE FALSE
Non è però prevista la possibilità di avere vettori di tipo misto.

1.6.2 Manipolazione dei vettori


Ai vettori numerici possiamo applicare le stesse operazioni aritmetiche, con-
fronti logici e funzioni matematiche viste per i valori scalari. Le opera-

6
zioni che hanno come termini dei vettori vengono eseguite componente per
componente. Ad esempio,
> a<-1:5
> a
[1] 1 2 3 4 5
> b<-7:11
> b
[1] 7 8 9 10 11
> a+b
[1] 8 10 12 14 16
Quindi il primo elemento di a viene sommato al primo elemento di b, il
secondo di a al secondo di b e cosı̀ via. Analogamente,
> a*b
[1] 7 16 27 40 55
> log(b)
[1] 1.945910 2.079442 2.197225 2.302585 2.397895
> d<-rep(10,5)
> a+b+d
[1] 18 20 22 24 26
> a>b
[1] F F F F F
Anche nel caso in cui uno dei termini sia uno scalare, l’operazione viene
eseguita componente per componente. Ad esempio,
> a^2
[1] 1 4 9 16 25
> a*2+b
[1] 9 12 15 18 21
> a*(2+b)
[1] 9 20 33 48 65
> a<=3
[1] T T T F F
Alcune funzioni utili per la manipolazione di vettori sono:
> x<-26:3
> length(x) restituisce il numero di elementi di x
[1] 24
> max(x) restituisce il massimo di x
[1] 26
> min(x) restituisce il minimo di x

7
[1] 3
> sum(x) restituisce la somma degli elementi di x
[1] 348
> prod(x) restituisce il prodotto degli elementi di x
[1] 2.016457e+26
> sort(x) ordina gli elementi di x in ordine crescente
[1] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

1.6.3 Estrazione degli elementi da un vettore


Gli elementi di un vettore possono essere estratti tramite parentesi quadrate
[]. Ad esempio, con

> x<-seq(0,20,10)
> x
[1] 0 10 20
> x[1]
[1] 0

si ottiene il primo elemento di x, mentre con

> x[3]
[1] 20

si ottiene il terzo elemento di x. Esempi più complessi sono:

> x[1:2]
[1] 0 10

con cui vengono presi il primo ed il secondo elemento di x e

> x[c(1,3)]
[1] 0 20

con cui vengono presi il primo ed il terzo elemento di x.


Gli indici tra parentesi quadrate devono essere numeri interi. Sono am-
messi anche valori negativi; in questo caso, viene restituito il vettore, ottenuto
eliminando gli elementi che occupano le posizioni specificate. Con

> x<-seq(1,10,2)
> x
[1] 1 3 5 7 9
> x[c(-1,-4)]
[1] 3 5 9

8
si escludono dal vettore x gli elementi di posizione 1 e 4.
Sono possibili anche estrazioni di elementi tramite operazioni logiche. Ve-
diamo qualche esempio. Siano peso ed altezza due vettori che contengono,
rispettivamente, il peso (kg) e l’altezza (cm) di 5 individui:

> peso<-c(80,70,82,76,90)
> altezza<-c(170,168,176,181,180)

Per estrarre da peso solo i pesi maggiori di 80 kg, si esegue

> peso1<-peso[peso>80]
> peso1
[1] 82 90

Nell’estrazione viene mantenuto l’ordine del vettore originario peso. In modo


analogo, con

> altezza1<-altezza[altezza<=170]
> altezza1
[1] 170 168

vengono assegnati al vettore altezza1 gli elementi del vettore altezza che
sono minori od uguali a 170. Con

> peso2<-peso[altezza>170]
> peso2
[1] 82 76 90

vengono assegnati al vettore peso2 gli elementi di peso ai quali corrispondono


elementi del vettore altezza maggiori di 170, cioè i pesi degli individui che
hanno una altezza maggiore di 170 cm.

1.7 Creazione e manipolazione di matrici


R consente di creare anche matrici. Come per i vettori, le matrici possono
essere numeriche, di stringhe di caratteri o logiche. Il comando usato per la
creazione di matrici è matrix. Vediamone il funzionamento.

> a<-matrix(1:6,nrow=2)
> a
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6

9
L’opzione nrow ci dice quante righe deve avere la matrice risultante (il nume-
ro di colonne è ottenuto per differenza). Nell’esempio precedente, abbiamo
creato una matrice a di due righe (e conseguentemente 3 colonne) in cui
abbiamo disposto i numeri da 1 a 6. Senza ulteriori specificazioni, nella di-
sposizione dei valori si procede per colonna. Se si vuole procedere per riga,
è necessario usare l’opzione byrow=TRUE. Ad esempio, con
> b<-matrix(1:6,nrow=2,byrow=TRUE)
> b
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
si ottiene una matrice b di due righe e tre colonne, ma procedendo per riga.
Altri esempi sono:
> x<-3:8
> matrix(x,ncol=2)
[,1] [,2]
[1,] 3 6
[2,] 4 7
[3,] 5 8
> matrix(x,ncol=2,byrow=TRUE)
[,1] [,2]
[1,] 3 4
[2,] 5 6
[3,] 7 8
Nel primo caso, dal vettore x viene creata una matrice di due colonne pro-
cedendo per colonna; nel secondo caso, procedendo per riga.
Si possono creare anche matrici di stringhe di caratteri o logiche. Ad
esempio,
> x<-c("pippo","pluto","topolino","paperino")
> matrix(x,ncol=2)
[,1] [,2]
[1,] "pippo" "topolino"
[2,] "pluto" "paperino"
> matrix(c(3>=2,3<=5,2==2,1<0),nrow=2)
[,1] [,2]
[1,] TRUE TRUE
[2,] TRUE FALSE
Come accade per i vettori, anche le matrici non possono essere di tipo misto,
ad esempio numerico e di caratteri.
Per conoscere le dimensioni di una matrice, si usa la funzione dim:

10
> dim(a)
[1] 2 3

Il primo elemento rappresenta il numero di righe ed il secondo il numero di


colonne della matrice a.
È possibile creare matrici attraverso la concatenazione di vettori. Ciò
avviene con le funzione rbind e cbind che eseguono concatenazioni di vettori,
per riga e per colonna, rispettivamente. Ad esempio, con

> a<-rbind(peso,altezza)
> a
[,1] [,2] [,3] [,4] [,5]
peso 80 70 82 76 90
altezza 170 168 176 181 180

abbiamo ottenuto la matrice a concatenando, per riga, i vettori peso e


altezza. Mentre, con

> b<-cbind(peso,altezza)
> b
peso altezza
[1,] 80 170
[2,] 70 168
[3,] 82 176
[4,] 76 181
[5,] 90 180

otteniamo la matrice b concatenando, per colonna, i vettori peso e altezza.


Per estrarre un elemento da una matrice, bisogna specificarne le coordi-
nate (riga e colonna) tramite parentesi quadre []. Ad esempio,

> b[2,2]
[1] 168

restituisce l’elemento di b di coordinate 2,2;

> b[5,1]
[1] 90

restituisce l’elemento di b di coordinate 5,1. Se non si specifica una delle due


coordinate, si ottiene un’intera riga/colonna. Ad esempio,

> a[1,]
[1] 80 70 82 76 90

restituisce la prima riga di a

11
> a[,2]
peso altezza
70 168

restituisce la seconda colonna di a.


Possono essere estratti anche sottoinsiemi di righe e colonne. Ad esempio,

> b[1:3,2]
[1] 170 168 176

prende i primi tre elementi della seconda colonna di b,

> a[1,c(1,4,5)]
[1] 80 76 90

estrae dalla prima riga di a il primo, il quarto e il quinto elemento. Esempi


di estrazioni più complessi sono:

> b[b[,2]>175,]
peso altezza
[1,] 82 176
[2,] 76 181
[3,] 90 180

prende le righe di b che hanno un valore nella seconda colonna maggiore di


175 (in sostanza, peso e altezza degli individui più alti di 175 cm);

> b[b[,1]>80,]
peso altezza
[1,] 82 176
[2,] 90 180

prende le righe di b che hanno un valore sulla prima colonna maggiore di 80


(ossia, peso e altezza degli individui che pesano più di 80 kg).
Come accade per i vettori, anche per le matrici le operazioni aritmetiche e
di confronto vengono eseguite elemento per elemento. Vediamo degli esempi.

> a<-matrix(0:5,nrow=2)
> b<-matrix(seq(0,10,2),nrow=2)
> a
[,1] [,2] [,3]
[1,] 0 2 4
[2,] 1 3 5

12
> b
[,1] [,2] [,3]
[1,] 0 4 8
[2,] 2 6 10
> a+b
[,1] [,2] [,3]
[1,] 0 6 12
[2,] 3 9 15
> a*b
[,1] [,2] [,3]
[1,] 0 8 32
[2,] 2 18 50
> a==5
[,1] [,2] [,3]
[1,] FALSE FALSE FALSE
[2,] FALSE FALSE TRUE

Per eseguire la moltiplicazione matriciale, si usa l’operatore %*%, accertandosi


prima che il numero delle colonne della prima matrice sia uguale al numero
delle righe della seconda matrice:
> a
[,1] [,2] [,3]
[1,] 0 2 4
[2,] 1 3 5
> b<-matrix(seq(0,10,2),nrow=3)
> b
[,1] [,2]
[1,] 0 6
[2,] 2 8
[3,] 4 10
> d<-a%*%b
> d
[,1] [,2]
[1,] 20 56
[2,] 26 80
Per calcolare l’inversa di una matrice quadrata non singolare si usa la funzione
solve:
> solve(d)
[,1] [,2]
[1,] 0.5555556 -0.3888889
[2,] -0.1805556 0.1388889

13
Per calcolare la trasposta di una matrice si usa la funzione t:
> t(d)
[,1] [,2]
[1,] 20 26
[2,] 56 80

1.8 I data frame


Oltre agli scalari, i vettori e le matrici, una ulteriore struttura di dati che
viene messa a disposizione da R sono i data frame. Come osservato prece-
dentemente, tutti gli elementi di una matrice devono essere dello stesso tipo.
I data frame sono matrici le cui colonne possono essere di tipo diverso. È
allora possibile combinare in un data frame colonne numeriche e colonne di
stringhe di caratteri o logiche. Per questo motivo i data frame si prestano a
rappresentare le matrici di dati generate da indagini statistiche. Le righe del
data frame rappresentano tipicamente le unità statistiche, mentre le colonne
rappresentano le variabili rilevate che possono essere sia qualitative (in que-
sto caso abbiamo una colonna di stringhe di caratteri o di valori logici) che
quantitative (in questo caso abbiamo una colonna numerica).
La funzione data.frame è usata per creare un data frame a partire da
vettori o matrici. Riprendiamo l’esempio sul peso e l’altezza dei 5 individui
e supponiamo, inoltre, di aver rilevato per ciascuno di essi se è fumatore
oppure no. Creiamo un vettore di stringhe che contenga questa ulteriore
informazione:
> fumatore=c("Si","Si","No","No","Si")
Costruiamo ora il data frame indagine in cui combiniamo le informazioni su
peso, altezza e fumo di ciascuno dei 5 individui:
> indagine=data.frame(peso,altezza,fumatore)
> indagine
peso altezza fumatore
1 80 170 Si
2 70 168 Si
3 82 176 No
4 76 181 No
5 90 180 Si
Ciascuna riga di indagine corrisponde ad un individuo, ossia ad una unità
statistica, mentre ciascuna colonna corrisponde ad una variabile rilevata
(matrice dei dati).
L’accesso agli elementi di un data frame avviene in modo del tutto analogo
a quanto visto per le matrici. Ad esempio,

14
> indagine[,2]
[1] 170 168 176 181 180
> indagine[3,]
peso altezza fumatore
3 82 176 No
> indagine[indagine[,3]=="Si",]
peso altezza fumatore
1 80 170 Si
2 70 168 Si
5 90 180 Si
L’ultimo comando restituisce le righe relative ai soli fumatori.
Molti dei comandi e delle operazioni che si eseguono su matrici, possono
essere eseguite anche su data frame. Naturalmente, se la funzione o l’opera-
zione richiede un argomento numerico, essa potrà essere applicata solo alle
colonne numeriche del data frame. Ad esempio,
> dim(indagine)
[1] 5 3
> sum(indagine[,2])
[1] 875

1.9 Lettura e scrittura di un file


Il modo più semplice di importare un file di testo in R è tramite la funzione
read.table. Essa produce come risultato un data frame ed è pertanto adatta
a leggere matrici di dati con colonne sia dello stesso tipo che di tipo diverso.
Vediamo un esempio.
Il file di testo UScereal.txt, che supponiamo trovarsi nella directory
mywork di C:, rappresenta una matrice di dati con 65 righe e 9 colonne,
contenente alcune informazioni sul contenuto nutrizionale e sulla strategia di
marketing associati ad alcuni prodotti di cereali americani. Ciascuna riga
rappresenta un prodotto di cereali, mentre le colonne descrivono, nell’ordine,
le variabili:
prod Nome del prodotto
mfr Iniziali della marca: G=General Mills, K=Kelloggs, N=Nabisco,
P=Post, Q=Quaker Oats, R=Ralston Purina.
calories Numero di calorie per porzione
protein Proteine (grammi) per porzione
fat Grassi (grammi) per porzione
fibre Fibre (grammi) per porzione
sugars Zuccheri (grammi) per porzione

15
shelf Numerazione dello scaffale in cui sono state disposte
(1, 2, o 3, contando dal basso)
vitamins Presenza di vitamine e minerali (none=nessuna,
enriched=arricchito, o 100%= fabbisogno giornaliero)

Le prime due colonne e la nona sono quindi di stringhe di caratteri; le restanti


sono numeriche. Leggiamo il file nel data frame cereali:

> cereali=read.table("C:/mywork/UScereal.txt",header=TRUE)
> dim(cereali)
[1] 65 9

L’opzione header=TRUE di read.table permette di leggere la prima riga del


file come nome delle colonne del data frame. Vediamo una parte del contenuto
del data frame cereali:

> cereali[1:3,]
prod mfr calories protein fat fibre sugars
1 100% Bran N 212.1 12.1 3 30.3 18.2
2 All-Bran K 212.1 12.1 3 27.3 15.2
3 All-Bran with Extra Fiber K 100.0 8.0 0 28.0 0.0

shelf vitamins
1 3 enriched
2 3 enriched
3 3 enriched

Per la scrittura di un vettore, di una matrice oppure di un data frame su


un file di testo, si utilizza la funzione write.table. Ad esempio, supponiamo
di voler salvare nel file Kelloggs.txt della directory mywork di C: i dati del
data frame cereali riferiti ai soli prodotti della marca Kelloggs. Possiamo
procedere nel modo seguente.

> attach(cereali)
> protein[1:3]
[1] 12.1 12.1 8.0

Attraverso il comando attach(cereali) possiamo richiamare le colonne del


data frame cereali direttamente tramite il loro nome.

> kelloggs=cereali[mfr=="K",]
> write.table(kelloggs,"C:/mywork/Kelloggs.txt", col.names=TRUE,
+ row.names=FALSE, quote=FALSE)

16
Tramite l’opzione col.names=TRUE richiediamo che nel file di testo vengano
riportati i nomi delle colonne; tramite l’opzione row.names=FALSE si specifica
che il file di uscita non deve riportare i nomi delle righe (nel nostro esempio
non presenti); in fine, tramite l’opzione quote=FALSE si precisa che nel file
di uscita le stringhe di caratteri non devono essere racchiuse tra virgolette.
Per maggiori dettagli si veda l’Help di write.table. Si noti che è possibile
andare a capo durante la scrittura di un’istruzione; R inserisce nella nuova
riga il simbolo + solo per indicare la continuazione del comando.

1.10 Esercizi
Esercizio 1
Si costruisca un vettore x di elementi 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5,
5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5 e 10. Per x si calcolino la lunghezza, la
somma degli elementi, il prodotto degli elementi.
Esercizio 2
Per il vettore x dell’Esercizio 1 si calcolino la media e la varianza
mediante l’uso delle funzioni length e sum.
Esercizio 3
Dai vettori

> x<-c(3,5,9,1,2,10,12,24,6),
> y<-c(0.15,0,0.32,0.51,0.18,0.22,0.6,0.98,0.12)
> z<-c(123,415,981,643,1080,89,46,75,910)

si costruisca una matrice mat che ha come colonne i tre vettori. A


partire da mat si costruisca una sottomatrice mat1 selezionando solo le
righe che hanno valore di z maggiore di 900.
Esercizio 4
Dal vettore

> x<-c(20,3,26,14,22,14,5,24,28,21,17,29,24,1,25,26,27,7,11,25,
+ 20,25,9,16,20,7,19,27,30,2)

si crei una matrice mat di 3 colonne, procedendo per riga. Si costruisca


poi una sottomatrice mat1 selezionando le prime otto righe di mat. Per
mat1 si calcolino media e varianza degli elementi della prima colonna
ai quali corrispondono elementi della seconda colonna maggiori di 10.
Esercizio 5
Si costruisca un data frame y con la seguente struttura

17
> y
a b
1 2 I
2 3 II
3 4 III

Esercizio 6
Dal data frame cereali si costruisca il data frame general.mills
contenente le informazioni riferite solo alla marca General Mills. Si
calcoli, quindi, media e varianza del contenuto calorico per i prodotti
della General Mills e la percentuale di prodotti della stessa marca con
contenuto vitaminico arricchito.

18
Capitolo 2

Statistica descrittiva

2.1 Introduzione
In questo capitolo vedremo come condurre un’analisi descrittiva dei dati
mediante tabelle di frequenza, indici sintetici e strumenti grafici, usando i
comandi disponibili in R.

2.2 Tabelle di frequenza


Si consideri il file di testo Studenti.txt relativo ad un campione di 65
studenti della Facoltà di Scienze Politiche dell’Università di Bologna che
hanno sostenuto l’esame di statistica nel 1989. Le colonne rappresentano,
nell’ordine, le variabili

IND Indirizzo di studi


SESSO
ANASC Anno di nascita
SCUOLA Scuola di provenienza
MAT Voto conseguito alla maturita’
STAT Voto conseguito all’esame di stastica (31 per lode)
ECON Voto conseguito all’esame di economia
DIR Voto conseguito all’esame di diritto

Importiamo la matrice di dati in R, supponendo che il file Studenti.txt si


trovi nella directory mywork di C:.

> studenti=read.table("C:/mywork/Studenti.txt",header=TRUE)
> dim(studenti)
[1] 65 8

19
> studenti
IND SESSO ANASC SCUOLA MAT STAT ECON DIR
1 Amm. F 1963 ITC 58 30 30 31
2 Eco. M 1964 ITC 50 23 24 26
3 Soc. F 1964 Scien. 51 26 27 30
4 Amm. F 1963 ITC 48 23 24 27
....
63 Soc. F 1968 ITC 60 18 25 25
64 Amm. M 1969 ITC 42 25 19 25
65 Amm. F 1967 ITA 46 20 19 27
La principale funzione per la costruzione di tabelle di frequenza è table.
Vediamone il funzionamento, costruendo la tabella delle frequenze assolute
per la variabile IND (indirizzo di studi).
> attach(studenti)
> table(IND)
IND
Altro Amm. Eco. Soc.
1 27 19 18
> sum(table(IND))
[1] 65
Il risultato di table è un vettore i cui elementi sono le frequenze assolute delle
varie modalità (si noti che ad ogni frequenza viene associato il nome della
modalità corrispondente). Se vogliamo la tabella delle frequenze relative:
> n=length(IND)
> tab.freq.rel.IND=table(IND)/n
> tab.freq.rel.IND
IND
Altro Amm. Eco. Soc.
0.01538462 0.41538462 0.29230769 0.27692308
> sum(tab.freq.rel.IND)
[1] 1
Costruiamo la tabella di frequenza anche per la variabile ANASC (anno di
nascita):
> tab.freq.ANASC=table(ANASC)
> tab.freq.ANASC
ANASC
1949 1957 1960 1962 1963 1964 1965 1966 1967 1968 1969 1970
1 1 1 4 3 6 7 9 9 22 1 1
> tab.freq.rel.ANASC=tab.freq.ANASC/n

20
> tab.freq.rel.ANASC
ANASC
1949 1957 1960 1962 1963 1964
0.01538462 0.01538462 0.01538462 0.06153846 0.04615385 0.09230769
1965 1966 1967 1968 1969 1970
0.10769231 0.13846154 0.13846154 0.33846154 0.01538462 0.01538462

Dalla tabella delle frequenze possiamo ricavare la tabella delle frequenze cu-
mulate tramite la funzione cumsum. Tale funzione crea un vettore di dimen-
sione pari a quello in entrata i cui elementi rappresentano le somme cumulate
parziali.

> tab.freqcum.ANASC=cumsum(tab.freq.ANASC)
> tab.freqcum.ANASC
1949 1957 1960 1962 1963 1964 1965 1966 1967 1968 1969 1970
1 2 3 7 10 16 23 32 41 63 64 65
> tab.freqcum.rel.ANASC=cumsum(tab.freq.rel.ANASC)
> tab.freqcum.rel.ANASC
1949 1957 1960 1962 1963 1964
0.01538462 0.03076923 0.04615385 0.10769231 0.15384615 0.24615385
1965 1966 1967 1968 1969 1970
0.35384615 0.49230769 0.63076923 0.96923077 0.98461538 1.00000000

2.3 Indici di posizione e variabilità


Consideriamo la variabile STAT (voto all’esame di statistica) e proviamo a cal-
colare media, mediana, varianza e scarto interquartilico per questa variabile,
usando le funzioni di R sinora introdotte.

> media.STAT=sum(STAT)/n
> media.STAT
[1] 24.33846

Per la mediana, sappiamo che questa occupa la posizione (65+1)/2=33 nel


vettore ordinato delle osservazioni. Pertanto,

> STAT.ord=sort(STAT)
> mediana.STAT=STAT.ord[33]
> mediana.STAT
[1] 25

Per la varianza, ricordiamo che questa è la media degli scarti al quadrato

21
> varianza.STAT=sum((STAT-media.STAT)^2)/n
> varianza.STAT
[1] 18.96237
ma è calcolabile anche come differenza tra momento secondo e momento
primo al quadrato, ossia
> varianza2.STAT=sum(STAT^2)/n-media.STAT^2
> varianza2.STAT
[1] 18.96237
Se vogliamo lo scarto quadratico medio, basterà prendere
> sqrt(varianza.STAT)
[1] 4.35458
Per il calcolo dello scarto interquartilico abbiamo bisogno del primo e del
terzo quartile, ossia dei quantili 0.25 e 0.75. A questo fine costruiamo le
frequenze relative cumulate di STAT
> tab.freqcum.rel.STAT=cumsum(table(STAT)/n)
> tab.freqcum.rel.STAT
18 19 20 21 22 23 24
0.1692308 0.2153846 0.2923077 0.3076923 0.3230769 0.3692308 0.4769231
25 26 27 28 29 30 31
0.5846154 0.6769231 0.7384615 0.7846154 0.8000000 0.9230769 1.0000000
da cui vediamo che il primo quartile è 20 e il terzo quartile è 28. Lo scarto
interquartilico è 28-20=8.
Dopo tutto questo lavoro, che è stato utile per ripassare alcune proprietà
degli indici sintetici, vediamo quali sono le vere potenzialità di R per il calcolo
di tali misure.
Le principali funzioni di R per il calcolo di indici di posizione e variabilità
sono
• min calcola il valore minimo del vettore;

• max calcola il valore massimo del vettore;

• range fornisce i valori del minimo e del massimo, ossia gli estremi del
campo di variazione;

• mean calcola la media;

• median calcola la mediana;

• var calcola la varianza (ma fate attenzione al risultato prodotto);

22
• quantile calcola i quantili di qualsiasi ordine;

• summary fornisce una tabella che riassume maggior parte dei valori
sopra esposti.

Vediamo alcuni esempi

> min(STAT)
[1] 18
> max(STAT)
[1] 31
> range(STAT)
[1] 18 31
> mean(STAT)
[1] 24.33846
> median(STAT)
[1] 25
> var(STAT)
[1] 19.25865
> varianza.STAT
[1] 18.96237

Stranamente, var(STAT) e varianza.STAT non coincidono. Il motivo di


questa discrepanza è che la funzione var calcola la varianza campionaria
corretta, ossia la varianza ottenuta dividendo per la numerosità campionaria
meno 1. Facciamo una verifica:

> sum((STAT-mean(STAT))^2)/(n-1)
[1] 19.25865
> quantile(STAT,0.25)
25%
20
> quantile(STAT,0.75)
75%
28
> quantile(STAT,c(0.25,0.75))
25% 75%
20 28
> quantile(STAT,c(0.05,0.95))
5% 95%
18 31
> summary(STAT)
Min. 1st Qu. Median Mean 3rd Qu. Max.
18.00 20.00 25.00 24.34 28.00 31.00

23
2.4 Grafici
2.4.1 Grafici per variabili qualitative
I principali grafici per variabili qualitative sono:

• diagrammi a torta, prodotti dalla funzione pie

• diagrammi a rettangoli separati, prodotti dalla funzione barplot.

Consideriamo nuovamente il data frame studenti. La variabile IND è qua-


litativa e può essere rappresentata graficamente con gli strumenti appena
elencati.
L’Help di R per la funzione pie precisa che l’argomento della funzione
deve essere un vettore i cui elementi sono le aree dei settori circolari. Come
sappiamo, le aree dei settori circolari sono proporzionali alle frequenze asso-
lute. Dobbiamo pertanto costruire la tabella delle frequenze della variabile
IND che sarà data in input alla funzione pie

> tabella.IND=table(IND)
> tabella.IND
IND
Altro Amm. Eco. Soc.
1 27 19 18
> pie(tabella.IND)
> pie(tabella.IND,labels=c("Altro","Amministrativo","Economico",
+ "Sociologico"))

Attraverso l’opzione labels di pie possiamo dare un nome ai vari settori


circolari (fate attenzione all’ordine che deve essere lo stesso della tabella di
frequenza). In assenza di una specificazione delle etichette, pie utilizza i
nomi estratti dalla tabella di frequenza.
Per la funzione barplot, l’argomento principale è il vettore delle altezze
dei rettangoli. Sappiamo che le altezze dei rettangoli del diagramma sono
date dalle frequenze (assolute o relative) della variabile, pertanto

> barplot(tab.freq.rel.IND)
> barplot(tab.freq.rel.IND, names.arg=c("Altro","Amministrativo",
+ "Economico","Sociologico"))

L’opzione names.arg ha lo stesso effetto di labels in pie. Poiché la tabella


delle frequenze riporta le modalità in ordine alfabetico, nel grafico a rettangoli
separati la modalità Altro compare prima delle altre. Essendo Altro definito
a partire dalle altre modalità, sarebbe preferibile che comparisse in coda. Il
problema può essere facilmente risolto come segue.

24
> tabella.IND.rel.riord= tabella.IND.rel[c(2:4,1)]
> tabella.IND.rel.riord
IND
Amm. Eco. Soc. Altro
0.41538462 0.29230769 0.27692308 0.01538462
> barplot(tabella.IND.rel, names.arg=c("Amministrativo",
+ "Economico","Sociologico","Altro"))

La funzione barplot può essere usata anche per fare dei confronti. (Ri-
cordate che i confronti tra distribuzioni devono essere fatti in termini di
frequenze relative!). Inventiamo alcune valori che supponiamo rappresentare
la distribuzione dell’indirizzo di studi per gli studenti della facoltà di Scienze
Politiche dell’Università di Padova.

> tabella.IND.PD=c(20,20,10,5)
> tabella.IND.PD.rel=tabella.IND.PD/sum(tabella.IND.PD)

Per fare un confronto tra distribuzioni barplot si aspetta come argomen-


to una matrice in cui ciascuna riga contiene le frequenze di ciascuna delle
distribuzioni che vogliamo confrontare.

> tabella.congiunta=rbind(tabella.IND.rel.riord,tabella.IND.PD.rel)
> barplot(tabella.congiunta,names.arg=c("Amministrativo",
+ "Economico","Sociologico","Altro"))
> barplot(tabella.congiunta,names.arg=c("Amministrativo",
+ "Economico","Sociologico","Altro"),beside=TRUE)

Con l’opzione beside=TRUE i rettangoli vengono affiancati, invece di essere


sovrapposti.

2.4.2 Grafici per variabili quantitative


Grafici per variabili discrete con “poche” modalità
Uno strumento grafico appropriato per rappresentare variabili discrete con
“poche” modalità è il diagramma a bastoncini. Tratteremo la costruzio-
ne di diagrammi a bastoncini nel paragrafo 2.4.3, dopo aver discusso il
funzionamento del comando plot.

Grafici per variabili continue o discrete con molte modalità


I principali strumenti grafici per variabili continue o discrete, ma con molte
modalità sono

25
• gli istogrammi, realizzabili con la funzione hist;

• i boxplot, realizzabili con la funzione boxplot.


Vediamo il funzionamento di queste funzioni lavorando con la variabile sugars
(contenuto di zuccheri) del data frame cereali introdotto nel paragrafo 1.9.
> attach(cereali)
> hist(sugars)
Si noti come, in assenza di ulteriori specificazioni, R esegua in modo auto-
matico una suddivisione in classi di uguale ampiezza e metta in ordinata le
frequenze assolute. Per richiedere a R di mettere in ordinata la densità di
frequenza relativa (rapporto tra frequenza relativa e ampiezza delle classi) è
necessario usare l’opzione freq=FALSE:
> hist(sugars,freq=FALSE)
Si noti, inoltre, che R dà automaticamente un nome agli assi e un titolo al
grafico. Si può intervenire su queste scelte di default tramite le opzioni xlab,
ylab e main:
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri")
Il grafico evidenzia una distribuzione bimodale, con una prima moda at-
torno a 3 grammi e una seconda moda attorno a 11 grammi. Questo ci
fa pensare che siano in commercio due tipologie di cereali: dietetici e non
dietetici, ossia prodotti per i quali si è puntato soprattutto sul contenuto
nutrizionale e prodotti per i quali si è puntato soprattutto sul gusto. Benché
R calcoli automaticamente la suddivisione in classi di uguale ampiezza, è
possibile per l’utente intervenire sul raggruppamento adottato per la costru-
zione del grafico tramite le opzioni nclass e breaks. Con nclass si specifica
il numero di classi, le quali rimangono però di uguale ampiezza. Ad esempio,
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri", nclass=2)
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri", nclass=5)
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri", nclass=10)
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri", nclass=20)
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri", nclass=30)

26
R non ci permette un controllo totale del numero di classi, come accade
per nclass=2. Si noti come il numero delle classi possa modificare com-
pletamente la forma del grafico. Ad esempio, con sole 3 classi (ottenute da
nclass=2) perdiamo tutti i dettagli della distribuzione, inclusa la bimodalità.
Abbiamo, in altre parole, sintetizzato troppo i nostri dati. Per contro, con
nclass=30 il grafico è troppo irregolare per permettere un’interpretazione
del fenomeno.
Per intervenire, non solo sul numero delle classi, ma anche sulla divisione
in classi, dobbiamo utilizzare l’opzione breaks, dando i punti di interruzione
degli intervalli.

> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",


+ main="Istogramma del contenuto di zuccheri",breaks=c(0,10,15,25))
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri", breaks=c(0,2,5,8,10,
+ 12,15,21))
> hist(sugars,freq=FALSE,xlab="zuccheri",ylab="densita’ di freq. rel.",
+ main="Istogramma del contenuto di zuccheri",breaks=seq(0,21,by=3))

Tipicamente la scelta di classi di differente ampiezza è legata a conoscenze


specifiche del fenomeno o al desiderio di evidenziare comportamenti peculiari.
Vediamo ora il funzionamento di boxplot.

> boxplot(sugars)

Notiamo una forte asimmetria negativa. Il boxplot non ci permette però di


evidenziare la bimodalità presente nei dati.
É opportuna una precisazione riguardo all’uso di boxplot. Senza ulteriori
specificazioni, boxplot estende i baffi sino all’osservazione immediatamente
più piccola di “estremi della scatola ±1.5× scarto interquartilico”. Rappre-
senta, inoltre, con un punto le osservazioni più estreme che cadono oltre i
baffi. Per sugars, i baffi cosı̀ costruiti raggiungono il minimo e il massimo
osservati e il grafico assume la forma a noi nota. Tuttavia, se prendiamo ad
esempio la variabile calories (numero di calorie per porzione)

> boxplot(calories)

otteniamo il boxplot “tipico” prodotto da R , che è anche quello generalmente


proposto dalla letteratura statistica. Per ottenere un boxplot i cui baffi si
estendono sino al minimo e al massimo valore osservati, dobbiamo utilizzare
l’opzione range=0:

> boxplot(calories,range=0)

27
Sappiamo dal corso di Statistica che i boxplot si prestano a confrontare
distribuzioni di frequenza. Supponiamo di voler confrontare tramite boxplot
la distribuzione del contenuto di zuccheri per le diverse marche di cereali.

> table(mfr)
mfr
G K N P Q R
22 21 3 9 5 5
> zuccheri.G=sugars[mfr=="G"]
> zuccheri.K=sugars[mfr=="K"]
> zuccheri.N=sugars[mfr=="N"]
> zuccheri.P=sugars[mfr=="P"]
> zuccheri.Q=sugars[mfr=="Q"]
> zuccheri.R=sugars[mfr=="R"]
> boxplot(zuccheri.G,zuccheri.K,zuccheri.N,zuccheri.P,zuccheri.Q,
+ zuccheri.R)
> boxplot(zuccheri.G,zuccheri.K,zuccheri.N,zuccheri.P,zuccheri.Q,
+ zuccheri.R, names=c("G.Mills","Kelloggs","Nabisco","Post",
+ "Quaker","Ralston"))

Con l’opzione names è possibile dare un nome a ciascuna scatola. Dal con-
fronto dei boxplot possiamo dedurre che mentre la General Mills, la Kelloggs
e la Nabisco tendono a coprire l’intera gamma di prodotti, da quelli meno
zuccherati a quelli più zuccherati, la Post e la Quaker Oats tendono a fo-
calizzarsi su prodotti ad alto contenuto di zuccheri e la Ralston Purina su
prodotti a basso contenuto di zuccheri.
I boxplot affiancati prodotti attraverso le precedenti istruzioni, possono
essere ottenuti con un unico comando se facciamo ricorso alla funzione split:

> boxplot(split(sugars,mfr))
> split(sugars,mfr)
$G
[1] 13.3 10.7 0.8 12.0 14.0 13.0 13.0 13.3 12.0 13.3 2.0 12.0
[13] 6.0 20.0 16.0 3.0 14.0 3.0 4.0 12.0 3.0 10.7

$K
[1] 15.2 0.0 14.0 2.0 12.0 14.0 3.0 13.0 14.7 8.8 17.9 12.0
[13] 19.4 13.4 10.4 3.0 16.0 12.0 3.0 20.0 3.0

$N
[1] 18.2 0.0 0.0

$P

28
[1] 7.5 14.9 16.0 17.0 5.7 12.0 12.1 8.3 20.9

$Q
[1] 16 11 9 0 12

$R
[1] 9.0 3.0 6.7 1.8 4.5
Tramite split(sugars,mfr) otteniamo una suddivisione delle osservazioni
sul contenuto di zuccheri in base alle modalità assunte da mfr (le diverse
marche). Il risultato può essere dato in input a boxplot per la costruzione
di boxplot affiancati.

2.4.3 Diagrammi di dispersione


Come sappiamo il diagramma di dispersione viene usato per rappresentare la
distribuzione congiunta di due variabili quantitative. La funzione di R per la
costruzione di diagrammi di dispersione è plot. Vediamone il funzionamento
disegnando il grafico di dispersione tra le variabili sugars e calories del data
frame cereali.
> attach(cereali)
> plot(sugars,calories)
> plot(sugars,calories,xlab="zuccheri", ylab="calorie")
La funzione plot richiede come argomenti, nell’ordine, il vettore delle osser-
vazioni sulla variabile che verrà messa in ascisse e il vettore di osservazioni
sulla variabile che verrà messa in ordinata. Le opzioni xlab e ylab con-
sentono di specificare un’etichetta per gli assi, come visto per la funzione
hist.
Come ci aspettavamo, esiste una relazione di segno positivo tra le variabili
contenuto di zuccheri e numero di calorie: al crescere di una variabile anche
l’altra tende a crescere. Ci sono però due punti che si discostano da que-
sto andamento generale. Cerchiamo di identificare a quali unità statistiche
corrispondono.
> identify(sugars,calories,n=2)
[1] 31 32
> cereali[c(31,32),]
prod mfr calories protein fat fibre sugars shelf
31 Grape-Nuts P 440.0 12.0 0.0 12.0 12.0 3
32 Great Grains Pecan P 363.6 9.1 9.1 9.1 12.1 3

vitamins

29
31 enriched
32 enriched

Sono entrambi prodotti della Post, con un numero di calorie piuttosto elevato,
ma con un livello medio del contenuto di zuccheri. Possiamo però notare che
l’unità 32 è caratterizzata da un elevato tasso di grassi, che potrebbe spiegare
l’alto numero di calorie. Tale spiegazione non regge per l’unità 31.

> plot(fat,calories,xlab="grassi", ylab="calorie")


> points(fat[c(31,32)],calories[c(31,32)],col="red")

La funzione points aggiunge punti ad un diagramma di dispersione pre-


esistente. La sua sintassi è simile a quella di plot. Con l’ultimo comando
abbiamo evidenziato con il colore rosso (opzione col="red") i punti associati
alle unità 31 e 32.
Esiste ovviamente una forte relazione di segno positivo tra contenuto di
grassi e numero di calorie, ma l’unità 31 presenta ancora valori anomali.
Poiché nessuna delle restanti componenti nutrizionali dovrebbe incidere si-
gnificativamente sull’apporto calorico, lo strano comportamento dell’unità
31 potrebbe essere imputato a qualche variabile non rilevata, ad esempio la
quantità di carboidrati.
Dopo aver preso dimestichezza con le funzioni plot e points per crea-
re diagrammi di dispersione, affrontiamo il problema della costruzione di
diagrammi a bastoncini per variabili discrete che abbiamo rimandato dal pa-
ragrafo 2.4.2. Vogliamo costruire un diagramma a bastoncini per la variabile
ANASC del data frame studenti. Possiamo procedere come segue.

> tabella.freq.rel.ANASC
ANASC
1949 1957 1960 1962 1963 1964
0.01538462 0.01538462 0.01538462 0.06153846 0.04615385 0.09230769
1965 1966 1967 1968 1969 1970
0.10769231 0.13846154 0.13846154 0.33846154 0.01538462 0.01538462
> plot(c(1949,1957,1960,1962:1970),tabella.freq.rel.ANASC,type="h",
+ xlab="anno di nascita", ylab="frequenze relative")
> points(c(1949,1957,1960,1962:1970),tabella.freq.rel.ANASC)

Con la precedente istruzione plot abbiamo messo in ascisse le modalità della


variabile ANASC e in ordinate le corrispondenti frequenze relative. Tramite
l’opzione type="h" di plot sul grafico vengono tracciate delle linee verti-
cali che congiungono i punti alle ascisse, creando il diagramma a bastonci-
ni desiderato. Tramite il comando points abbiamo poi aggiunto dei punti
all’estremità dei bastoncini.

30
2.5 Misure di dipendenza tra due variabili
quantitative
Avendo introdotto i diagrammi di dispersione, sembra ragionevole affrontare
ora il problema di valutare, tramite opportune misure, la dipendenza tra due
variabili quantitative. Come sappiamo dal corso di Statistica, le misure più
usate per la quantificazione della dipendenza tra due variabili quantitative
sono
• la covarianza, ossia la media del prodotto degli scarti delle due variabili
dalle rispettive medie
• la correlazione, pari alla covarianza diviso il prodotto degli scarti qua-
dratici medi delle due variabili
Calcoliamo la covarianza tra le variabili sugars e calories in modo da
associare una misura di dipendenza al grafico di dispersione ottenuto nel
paragrafo 2.4.3.
> cov.zuccheri.calorie=mean((sugars-mean(sugars))*
+ (calories-mean(calories)))
> cov.zuccheri.calorie
[1] 177.4767
Ricordiamo che la covarianza può essere anche calcolata come differenza tra
la media del prodotto e il prodotto delle medie. Seguiamo anche questo
procedimento.
> cov2.zuccheri.calorie=mean(sugars*calories)-mean(sugars)*
+ mean(calories)
> cov2.zuccheri.calorie
[1] 177.4767
Per la correlazione,
> corr.zuccheri.calorie=cov.zuccheri.calorie/
+ sqrt((mean(calories^2)-mean(calories)^2)*
+ (mean(sugars^2)-mean(sugars)^2))
> corr.zuccheri.calorie
[1] 0.4952234
Il valore ottenuto indica la presenza di un buon grado di dipendenza lineare
tra le due variabili.
Come visto per gli indici di posizione e variabilità, anche per covarianza
e correlazione non è necessario il calcolo “manuale”, come fatto nei passi
precedenti, perché è possibile avvalersi delle funzioni di R cov e cor per
ottenere direttamente le due misure.

31
> cov(sugars,calories)
[1] 180.2497

Attenzione! Il risultato non coincide con quanto precedentemente ottenuto.


Questa discrepanza è dovuta al fatto che cov calcola la covarianza nella
sua versione corretta, ossia come media del prodotto degli scarti, ma non
dividendo per la numerosità complessiva del campione, bensı̀ dividendo per
la numerosità -1. È in pratica la stessa discrepanza vista per la varianza.
Facciamo una verifica.

> cov(sugars,calories)*(length(sugars)-1)/length(sugars)
[1] 177.4767

Per la correlazione, si ha:

> cor(sugars,calories)
[1] 0.4952234

Si noti che il valore della correlazione è identico a quello da noi ottenuto.


Questo per effetto di una semplificazione dei termini al numeratore (ottenuto
tramite cov) e al denominatore (ottenuto tramite var).
Proviamo ora a verificare cosa accade alla correlazione tra sugars e
calories se eliminiamo le due unità anomale 31 e 32.

> cor(sugars[c(-31,-32)],calories[c(-31,-32)])
[1] 0.6651287

Aumenta nettamente.
Calcoliamo ora covarianza e correlazione anche per le due variabili fat e
calories

> cov(fat,calories)
[1] 60.68219
> cor(fat,calories)
[1] 0.5895244

Come si poteva intuire dall’analisi dei due diagrammi di dispersione, il legame


lineare tra fat e calories è più forte che tra sugars e calories. Proviamo
a verificare cosa accade alla correlazione tra fat e calories se eliminiamo
l’unità 31 che risultava anomala rispetto all’andamento generale delle due
variabili:

> cor(fat[-c(31)],calories[-c(31)])
[1] 0.8112045

Anche in questo caso abbiamo un netto aumento della correlazione.

32
2.6 Salvataggio dei grafici
I grafici prodotti in R possono essere stampati, semplicemente selezionando il
grafico e quindi scegliendo l’opzione Print... dal menu di File. In alternativa,
possono essere salvati su disco, selezionando il grafico e quindi scegliendo
l’opzione Save as dal menu di File. A questo punto, vengono offerti vari
formati, la cui scelta dipende dall’uso che si intende fare del grafico. Il
formato jpeg si presta per l’importazione in file Word (cosı̀ come il formato
metafile), mentre il formato pdf è consigliabile per la stampa.

2.7 Esercizi
È stato messo a disposizione degli studenti il file cars.txt. Esso rappresenta
un data set relativo a 93 automobili (righe) per le quali sono state rilevate 9
variabili (colonne) di seguito descritte:

Manufacturer: Industria produttrice


Model: Modello
Type: Tipo (Small=Piccola, Sporty=Sportiva, Compact=Familiare,
Midsize=Dimensione media, Large=Grande, Van=Monovolume)
Min.Price: Prezzo minimo (in migliaia di dollari) -
prezzo per la versione base
AirBags: Presenza o Assenza di Air Bags di serie (none=Nessuno,
driver only=Solo per il guidatore, driver & passenger=
sia per il guidatore che il passeggero)
EngineSize: Dimensione del motore (in litri)
Horsepower: Potenza (massima)
Passengers: Numero di passeggeri
Length: Lunghezza (in pollici)

Si importi il file in R nel data frame cars tramite la funzione read.table e


lo si renda direttamente accessibile tramite la funzione attach.

Esercizio 1
Si precisi la natura di ciascuna delle 9 variabili: ad esempio, Type è
una variabile qualitativa. Con l’esclusione della variabile Model, per
tutte le altre variabili qualitative si costruiscano: (a) la tabella delle
frequenze assolute; (b) la tabella delle frequenze relative. Per le va-
riabili quantitative discrete, oltre alle tabelle delle frequenze assolute
e delle frequenze relative, si costruisca anche la tabella delle frequenze
relative cumulate.

33
Esercizio 2
Con l’esclusione della variabile Model, si rappresenti graficamente la di-
stribuzione delle frequenze di ciascuna variabile tramite il diagramma
che si ritiene appropriato, tendendo conto della natura della variabile
stessa. Ad esempio, la variabile Type è qualitativa, pertanto si potrà
ricorrere sia ad un diagramma a torta che ad un diagramma a rettan-
goli separati. In base ai grafici ottenuti, si commentino le principali
caratteristiche delle distribuzioni delle variabili rilevate.

Esercizio 3
Per la variabile Horsepower si costruiscano diversi istogrammi, facendo
variare, rispetto alla scelta di default di R , il numero di classi median-
te l’opzione nclass e le classi stesse mediante l’opzione breaks. Si
commentino i risultati ottenuti.

Esercizio 4
Per ciascuna variabile quantitativa si calcolino: (a) la media, (b) la
mediana, (c) la varianza e lo scarto quadratico medio, (d) i quantili
0.05, 0.25, 0.75 e 0.95, (e) lo scarto interquartilico e (f) il campo di
variazione, tramite le funzioni di R trattate al paragrafo 2.3.

Esercizio 5
Si confrontino le distribuzioni della variabile Horsepower condiziona-
te alle modalità della variabile AirBags attraverso boxplot affiancati.
A questo fine si faccia ricorso alla funzione split. Si commentino i
risultati.

Esercizio 6
Si costruisca il diagramma di dispersione della variabile Horsepower
contro la variabile EngineSize. Si commenti la relazione tra le due
variabili evidenziata dal grafico e si identifichino le unità che paiono
discostarsi dall’andamento generale.

Esercizio 7
Si calcolino covarianza e correlazione tra Horsepower e EngineSize,
usando le funzioni cov e cor, sia includendo tutte le osservazioni sia
escludendo quei punti che sono risultati anomali in base al grafico
ottenuto all’Esercizio 6.

Esercizio 8
Si ripetano le operazioni richieste dagli esercizi 6 e 7 con le variabili
EngineSize e Length.

34
Capitolo 3

Probabilità

3.1 Distribuzioni di probabilità


In R sono implementate tutte le distribuzioni di probabilità notevoli che
conosciamo (e molte altre). Per ogni distribuzione di probabilità, R mette a
disposizione 4 funzioni:

• una funzione che inizia per d per il calcolo dalla funzione di densità
(per variabili casuali continue) o di probabilità (per variabili casuali
discrete)

• una funzione che inizia per p per il calcolo della funzione di ripartizione

• una funzione che inizia per q per il calcolo dei quantili

• una funzione che inizia per r per la simulazione di valori dalla distri-
buzione.

La tabella seguente riporta le funzioni disponibili per le variabili casuali a


noi note.

Distribuzione Parametri Densità/ Probab. Ripartizione Quantili Simulazione


Binomiale n, p dbinom(x,n,p) pbinom(x,n,p) qbinom(prob,n,p) rbinom(num,n,p)
Poisson lambda dpois(x,lambda) ppois(x,lambda) qpois(prob,lambda) rpois(num,lambda)
Uniforme cont. a, b dunif(x,a,b) punif(x,a,b) qunif(prob,a,b) runif(num,a,b)
Normale mu,sigma dnorm(x,mu,sigma) pnorm(x,mu,sigma) qnorm(prob,mu,sigma) rnorm(num,mu,sigma)
χ2 df dchisq(x,df) pchisq(x,df) qchisq(prob,df) rchisq(num,df)
t df dt(x,df) pt(x,df) qt(prob,df) rt(num,df)
F df1, df2 df(x,df1,df2) pf(x,df1,df2) qf(prob,df1,df2) rf(num,df1,df2)

Le funzioni per il calcolo della densità/probabilità e per il calcolo della funzio-


ne di ripartizione richiedono come primo argomento il vettore x dei punti su

35
cui le funzioni dovranno essere valutate. Le funzioni per il calcolo dei quan-
tili richiedono come primo argomento il vettore prob del’ordine dei quantili,
ossia le probabilità che devono essere lasciate alla sinistra dei quantili. Le
funzioni per la simulazione richiedo come primo argomento il numero num di
punti da simulare. Vediamo il funzionamento di alcune di queste funzioni.
Vogliamo calcolare la funzione di probabilità di una variabile casuale
Bin(n=10,p=0.3) e rappresentarla graficamente tramite un diagramma a ba-
stoncini.

> x=0:10
> prob.binom=dbinom(x,10,0.3)
> cbind(x,prob.binom)
x prob.binom
[1,] 0 0.0282475249
[2,] 1 0.1210608210
[3,] 2 0.2334744405
[4,] 3 0.2668279320
[5,] 4 0.2001209490
[6,] 5 0.1029193452
[7,] 6 0.0367569090
[8,] 7 0.0090016920
[9,] 8 0.0014467005
[10,] 9 0.0001377810
[11,] 10 0.0000059049
> plot(x,prob.binom,type="h")
> points(x,prob.binom)

Se vogliamo calcolare il valore della funzione di ripartizione della stessa


binomiale nel punto 2, ossia P (X ≤ 2),

> pbinom(2, 10,0.3)


[1] 0.3827828

Se vogliamo calcolare la funzione di ripartizione su tutti i valori che possono


essere assunti dalla binomiale considerata

> pbinom(x,10,0.3)
[1] 0.02824752 0.14930835 0.38278279 0.64961072 0.84973167 0.95265101
[7] 0.98940792 0.99840961 0.99985631 0.99999410 1.00000000

Se vogliamo calcolare i quantili 0.1 e 0.9 della stessa binomiale

> qbinom(c(0.1,0.9),10,0.3)
[1] 1 5

36
che possiamo verificare essere corretti guardando ai valori della funzione di
ripartizione.
Vediamo alcuni esempi con la variabile casuale normale. Ricostruiamo
per punti e rappresentiamo graficamente la funzione di densità della variabile
casuale N (0, 1).

> x=seq(-5,5,0.1)
> den.norm=dnorm(x,0,1)
> plot(x,den.norm,type="l")

Con l’opzione type="l" di plot i punti del diagramma di dispersione vengono


congiunti da linee, producendo, nel nostro caso, la curva della funzione di
densità desiderata. Sullo stesso grafico, tracciamo anche la densità di N (0, 22 )
e N (1, 1):

> den.norm2=dnorm(x,0,2)
> den.norm3=dnorm(x,1,1)
> lines(x,den.norm2,col="red")
> lines(x,den.norm3,col="green")

La funzione lines opera in modo analogo a points, ma aggiunge ad un


grafico preesistente la spezzata dei punti specificati.
Ricordiamo che per la normale i valori della funzione di ripartizione e i
quantili non possono essere ottenuti in modo esplicito. Eravamo abituati a
calcolarli usando le tavole della normale standardizzata; con R è sufficiente
il ricorso a semplici istruzioni. Vediamo qualche esempio. Supponiamo di
voler calcolare il valore della funzione di ripartizione delle variabili casuali
N (0, 1), N (0, 22 ) e N (1, 1) nel punto 1:

> pnorm(1,0,1)
[1] 0.8413447
> pnorm(1,0,2)
[1] 0.6914625
> pnorm(1,1,1)
[1] 0.5

Ricostruiamo e rappresentiamo graficamente la funzione di ripartizione di


N (2, 22 ):

> x=seq(-3,7,0.1)
> rip.norm=pnorm(x,2,2)
> plot(x,rip.norm,type="l")

Calcoliamo i quantili 0.05 e 0.95 di N (0, 1), di N (0, 22 ) e di N (1, 1):

37
> qnorm(c(0.05,0.95),0,1)
[1] -1.644854 1.644854 #per la simmetria attorno a 0
> qnorm(c(0.05,0.95),0,2)
[1] -3.289707 3.289707 #per la simmetria attorno a 0
> qnorm(c(0.05,0.95),1,1)
[1] -0.6448536 2.6448536
Come per la distribuzione normale, anche per le variabili casuali χ2 , t ed F
la funzione di ripartizione e i quantili non possono essere calcolati in modo
esplicito, ma questo non è un problema se lavoriamo con R . Vediamo alcuni
esempi di calcolo di quantili per le tre variabili casuali.
> qchisq(c(0.1,0.9),1)
[1] 0.01579077 2.70554345
> qchisq(c(0.1,0.9),10)
[1] 4.865182 15.987179
> qt(c(0.05,0.95),1)
[1] -6.313752 6.313752 #per la simmetria
> qt(c(0.025,0.95),1)
[1] -12.706205 6.313752
> qt(c(0.025,0.95),5)
[1] -2.570582 2.015048
> qt(c(0.025,0.95),10)
[1] -2.228139 1.812461
> qt(c(0.025,0.95),100)
[1] -1.983972 1.660234
> qf(c(0.025,0.975),2,1)
[1] 0.02596976 799.50000000
> qf(c(0.025,0.975),1,2)
[1] 0.001250782 38.506329114 #per l’inversione dei gradi di liberta’
> 1/799.50000000
[1] 0.001250782
> 1/0.02596976
[1] 38.50632
> qf(c(0.025,0.975),5,10)
[1] 0.1510767 4.2360857
In modo analogo, possiamo usare le funzioni pchisq, pt e pf per il calcolo
della funzione di ripartizione delle tre distribuzioni.

3.2 Simulazione
Sinora non abbiamo utilizzato le funzioni che iniziano con r. Come accen-
nato, queste funzioni hanno il ruolo di simulare dei valori dalla distribuzione

38
di probabilità corrispondente. In altre parole, queste funzioni sono in grado
di riprodurre o simulare il comportamento di un fenomeno che segue una
determinata distribuzione di probabilità. Vediamo alcuni esempi.
Simuliamo, nell’ordine, un campione di 10, 100 e 1000 valori da una distri-
buzione N (0, 1). Ricostruiamo quindi la funzione di densità dei valori simula-
ti tramite un istogramma e confrontiamo la forma dell’istogramma ottenuto
con la curva della funzione di densità della variabile casuale N (0, 1).

> campione10=rnorm(10,0,1)
> campione100=rnorm(100,0,1)
> campione1000=rnorm(1000,0,1)
> par(mfrow=c(2,2))
> hist(campione10,freq=FALSE)
> x=seq(-5,5,0.1)
> lines(x,dnorm(x,0,1))
> hist(campione100,freq=FALSE)
> lines(x,dnorm(x,0,1))
> hist(campione1000,freq=FALSE)
> lines(x,dnorm(x,0,1))

Il precedente comando mfrow=c(2,2) permette di suddividere la finestra


grafica in 2 × 2 grafici, disposti su 2 righe e 2 colonne. Per ritornare ad un
unico grafico si dia il comando par(mfrow=c(1,1)). Si nota dal confronto dei
tre grafici che, all’aumentare della numerosità, la distribuzione del campione
simulato si avvicina sempre di più a quella della variabile generatrice N (0, 1).

3.3 Legge dei grandi numeri e teorema del


limite centrale
La legge dei grandi numeri stabilisce che, se X1 , X2 , . . ., Xn sono n variabili
casuali i.i.d. di media m, allora la media delle n variabili casuali converge a
m per n → ∞:
n
1X
lim X̄n = lim Xi = m
n→∞ n→∞ n
i=1

In altre parole, la media campionaria di n variabili casuali approssima la


vera media m per n sufficientemente grande. Alla luce di questo risultato,
se simuliamo n valori da una distribuzione e ne calcoliamo la media, per n
sufficientemente grande, questa dovrebbe approssimare la vera media della
distribuzione. Facciamo una verifica, simulando una distribuzione χ2 con 3
gradi di libertà (si ricorda che la media di un χ2 con r gradi di libertà è r).

39
> mean(rchisq(10,3))
> mean(rchisq(100,3))
> mean(rchisq(1000,3))
> mean(rchisq(10000,3))

Si noti come aumentando la numerosità del campione simulato, la media


campionaria si avvicini sempre di più alla vera media pari a 3. Tuttavia, già
per n = 100 otteniamo in questo caso una buona approssimazione.
Il teorema del limite centrale afferma che, se X1 , X2 , . . ., Xn sono n
variabili casuali i.i.d. di media m e varianza v 2 , allora la somma delle n
variabili si distribuisce approssimativamente come una normale di media nm
e varianza nv 2 per n grande:
n
Xi ∼· N (nm, nv 2 )
X
Sn =
i=1

Un’immediata conseguenza del teorema del limite centrale è che una variabile
casuale Bin(n, p) “assomiglia”, per n sufficientemente grande, ad una variabi-
le casuale N (np, np(1 − p)). Verifichiamo questo risultato costruendo la fun-
zione di probabilità di una variabile casuale Bin(n, 0.3) per valori crescenti di
n e confrontandola con la densità di una variabile casuale N (n·0.3, n·0.3·0.7).

> par(mfrow=c(2,2))
> x=0:5
> plot(x,dbinom(x,5,0.3),type="h")
> xx=seq(0,5,0.1)
> lines(xx,dnorm(xx,5*0.3,sqrt(5*0.3*0.7)))
> x=0:10
> plot(x,dbinom(x,10,0.3),type="h")
> xx=seq(0,10,0.1)
> lines(xx,dnorm(xx,10*0.3,sqrt(10*0.3*0.7)))
> x=0:20
> plot(x,dbinom(x,20,0.3),type="h")
> xx=seq(0,20,0.1)
> lines(xx,dnorm(xx,20*0.3,sqrt(20*0.3*0.7)))
> x=0:50
> plot(x,dbinom(x,50,0.3),type="h")
> xx=seq(0,50,0.1)
> lines(xx,dnorm(xx,50*0.3,sqrt(50*0.3*0.7)))

Se l’approssimazione è piuttosto carente per n = 5 e n = 10, migliora


decisamente per n = 20 ed è quasi perfetta per n = 50.

40
3.4 Tecniche di campionamento
Due tecniche di base per il campionamento da popolazioni finite sono il cam-
pionamento casuale, con e senza ripetizione. Entrambi gli schemi sono as-
similabili ad n estrazioni da un urna costituita da N palline; in un caso le
estrazioni sono fatte con reinserimento, nell’altro senza reinserimento.
Supponiamo di aver numerato gli elementi della popolazione da 1 a N . I
due schemi di campionamento possono essere realizzati generando n nume-
ri casuali da 1 a N , in un caso, rendendo possibili le ripetizioni, nell’altro
senza ripetizioni, e inserendo nel campione le unità della popolazione la cui
numerazione corrisponde ai valori generati. Per la generazione di numeri ca-
suali interi usiamo la funzione sample. Vediamone il funzionamento con un
esempio. Desideriamo estrarre un campione casuale senza ripetizione di nu-
merosità 20 da una popolazione di 1000 unità che abbiamo preventivamente
numerato da 1 a 1000.
> x=sample(1:1000,size=10)
> x
[1] 769 701 905 991 792 122 941 227 176 413
> sort(x)
[1] 122 176 227 413 701 769 792 905 941 991
In base a questi risultati, dovremmo includere nel campione le unità numerate
con 122, 176, ecc.. Per realizzare un campionamento casuale con ripetizione
è necessario utilizzare l’opzione replace=TRUE di sample:
> x=sample(1:1000,size=10,replace=TRUE)
> x
[1] 707 99 915 207 791 99 410 625 701 146
> sort(x)
[1] 99 99 146 207 410 625 701 707 791 915
In questa particolare estrazione casuale, l’unità 99 entra due volte nel cam-
pione.
Un altro schema di campionamento piuttosto diffuso è il campionamento
sistematico. Supponiamo di voler costruire un campione di dimensione n
da una popolazione di N unità. Possiamo procedere in questo modo. Sia
k la parte intera del rapporto N/n. Si estrae un valore casuale tra 1 e k;
sia r tale valore; allora il campione sistematico è formato considerando le
unità che sono state numerate con r, r + k, r + 2k, . . . , r + (n − 1)k. Il
campionamento sistematico può essere considerato casuale se gli elementi
della popolazione sono stati numerati secondo un ordine casuale. Vediamo
un esempio. Vogliamo costruire un campione sistematico di numerosità 10
da una popolazione di 1000 elementi. Allora, k = 1000/10 = 100. Estraiamo
un numero casuale tra 1 e 100, usando sample

41
> sample(1:100,size=1)
[1] 53
Il campione sistematico sarà quindi costituito dalle unità numerate con 53,
153, 253, . . . 953.

3.5 Confronti con la distribuzione normale


Poiché molte tecniche di inferenza statistica sono basate sull’ipotesi di nor-
malità del fenomeno che ha generato le osservazioni, è importante avere uno
strumento che ci permetta di dire se per un certo un campione tale ipotesi è
ragionevole. Un tale strumento è rappresentato dal diagramma quantile con-
tro quantile o Q-Q plot. Senza entrare nei dettagli teorici della costruzione
dei Q-Q plot, l’idea di base è quella di confrontare i quantili empirici (ossia le
osservazioni stesse) con i quantili teorici ottenuti dalla distribuzione normale.
Il confronto viene fatto graficamente tramite un diagramma di dispersione i
cui punti hanno coordinate date dai quantili teorici (generalmente messi in
ascissa) e i quantili empirici (generalmente posti in ordinata). Se le osserva-
zioni provengono da una distribuzione normale, quantili empirici e quantili
teorici coincidono, almeno approssimativamente, ossia il grafico cosı̀ ottenuto
deve seguire tendenzialmente la retta bisettrice. Allontanamenti dalla retta
sono indicazione di un non perfetto adattamento della distribuzione normale
ai dati.
La funzione di R per la costruzione di Q–Q plot normali è qqnorm. Ve-
diamone il funzionamento tramite alcuni esempi. Simuliamo un campione di
numerosità 100 da una distribuzione N (1, 32 ) e costruiamo per le osservazioni
generate il Q–Q plot normale.
> campione.normale=rnorm(100,1,3)
> qqnorm(campione.normale)
> abline(0,1)
Il comando abline(0,1) traccia sul grafico una linea retta con intercetta 0
e coefficiente angolare 1, ossia la retta bisettrice. In generale, il comando
abline(a,b) traccia sul grafico una linea retta con intercetta a e coefficiente
angolare b.
Benché abbiamo la certezza che le osservazioni siano normali, essendo sta-
te simulate dalla distribuzione normale, osserviamo un netto allontanamento
dalla retta bisettrice. Perché questo accade? Il motivo di questo risultato
inatteso è che la funzione qqnorm fa un confronto con i quantili della normale
standard (di media 0 e varianza 1), senza tener conto del fatto che le os-
servazioni potrebbero provenire da una distribuzione normale ma con media
diversa da 0 e/o varianza diversa da 1. Per questa ragione, se le osservazioni

42
hanno media diversa da 0 e varianza diversa da 1, prima di usare la funzione
qqnorm è bene standardizzarle (per renderle di media 0 e varianza unitaria)
sottraendo la media e dividendo per lo scarto quadratico medio:

> campione.normale.stand=(campione.normale-mean(campione.normale))/
+ sqrt(var(campione.normale))
> mean(campione.normale.stand)
> var(campione.normale.stand)
> qqnorm(campione.normale.stand)
> abline(0,1)

Il grafico è decisamente migliorato. I punti tendono a disporsi lungo la ret-


ta bisettrice, seppure si osservano alcune discrepanze nelle code. Questo
fenomeno si verifica spesso e è la conseguenza del fatto che le osservazioni
sulle code tendono ad essere più variabili. Il problema dovrebbe ridursi se
lavoriamo con campioni più numerosi:

> campione.normale=rnorm(1000,1,3)
> campione.normale.stand=(campione.normale-mean(campione.normale))/
+ sqrt(var(campione.normale))
> qqnorm(campione.normale.stand)
> abline(0,1)

Vediamo ora un esempio con la distribuzione χ2 . Sappiamo che la distribu-


zione χ2 con pochi gradi di libertà ha una funzione di densità fortemente
asimmetrica a destra che non assomiglia molto a quella di una normale (è
approssimabile a quella della normale se i gradi di libertà sono elevati). Ci
aspettiamo, allora, che un campione di osservazioni provenienti dalla distri-
buzione χ2 con 2 gradi di libertà produca un Q–Q plot normale che si allon-
tana decisamente dalla retta. Verifichiamo questa affermazione, simulando
un campione di 1000 osservazioni da un χ22 e costruendo su di esso il Q–Q
plot normale. Sapendo che le osservazioni simulate dal χ22 non hanno media
0 e varianza unitaria, prima di usare la funzione qqnorm le standardizziamo.

> campione.chi2=rchisq(1000,2)
> hist(campione.chi2)
> campione.chi2.stand=(campione.chi2-mean(campione.chi2))/
+ sqrt(var(campione.chi2))
> qqnorm(campione.chi2.stand)
> abline(0,1)

L’allontanamento dalla retta bisettrice è evidente. In particolare, dal grafico


deduciamo che le osservazioni presentano una distribuzione con una coda
sinistra più corta rispetto a quella della normale e una coda destra più lunga,

43
in accordo con le caratteristiche a noi note della distribuzione χ2 . Da questo
Q–Q plot non abbiamo dubbi sull’irragionevolezza dell’ipotesi di normalità
per il campione considerato.
Concludiamo con una applicazione a dati reali, considerando la variabile
MAT (voto all’esame di maturità ) del data frame studenti. Tale variabile
è discreta, ma con molte modalità, pertanto l’ipotesi che la sua distribu-
zione possa essere approssimata con la distribuzione normale non è a priori
irragionevole (si pensi a come il teorema del limite centrale ci permette di
approssimare una distribuzione binomiale tramite la distribuzione normale,
purché n sia sufficientemente grande). Vogliamo verificare se la forma della
distribuzione delle osservazioni su MAT è compatibile con le caratteristiche
della variabile casuale normale.
> attach(studenti)
> hist(MAT)
> mean(MAT)
[1] 47.98462
> var(MAT)
[1] 45.32788
> MAT.stand=(MAT-mean(MAT))/sqrt(var(MAT))
> qqnorm(MAT.stand)
> abline(0,1)
Alcune osservazioni sono ripetute e questo spiega i punti che formano dei
tratti orizzontali, ma al di là di questo aspetto legato alla natura discreta
della variabile, complessivamente l’adattamento della distribuzione normale
ai dati pare soddisfacente. Per queste osservazioni è, quindi, ragionevole
assumere che il fenomeno che le ha generate si distribuisca normalmente
(con media diversa da 0 e varianza diversa da 1!).

3.6 Esercizi
Esercizio 1
Si ricostruisca per punti e si rappresenti graficamente la funzione di
densità della variabile casuale χ2 con 3 gradi di libertà. Sullo stesso
grafico, si traccino anche le funzioni di densità, ricostruite per punti,
delle variabili casuali χ25 e χ210 , usando linee di colore diverso. Che
cosa accade al crescere dei gradi di libertà? (Suggerimento: per ben
rappresentare le tre funzioni sullo stesso grafico, usate come vettore di
punti sui cui devono essere valutate le densità x=seq(0,20,0.1).)
Esercizio 2
Si ripetano le operazioni descritte nell’Esercizio 1 per le variabili casuali

44
t con 2, 4 e 10 gradi di libertà, rispettivamente, usando colori diversi
per le linee. Sullo stesso grafico si tracci anche la curva della funzione
di densità della normale standard N (0, 1). Che cosa accade al crescere
dei gradi di libertà? (Suggerimento: per ben rappresentare le 4 funzioni
sullo stesso grafico, usate come vettore di punti sui cui devono essere
valutate le densità x=seq(-5,5,0.1).)

Esercizio 3
Si ricostruisca per punti e si rappresenti graficamente la funzione di
ripartizione della variabile casuale F con gradi di libertà 5, 20.

Esercizio 4
Si calcolino i quantili 0.005, 0.025, 0.1, 0.9 , 0.95, 0.975, 0.99 per le
seguenti distribuzioni: N (0, 1), N (10, 52 ), χ27 , t14 , F3,2 . Coincidono con
quelli ottenuti dalla tavole?

Esercizio 5
Si simulino 4 campioni, rispettivamente, di numerosità 10, 50, 100 e
1000 da una distribuzione χ2 con 3 gradi di libertà. Si Suddivida la
finestra grafica in 4 sottofinestre tramite mfrow. Su ciascuna sottofine-
stra si disegni l’istogramma per ogni campione simulato e si tracci sullo
stesso grafico la curva della densità della variabile casuale χ23 , ricostruita
per punti. Che cosa si può dedurre dal confronto dei 4 grafici?

Esercizio 6
Si progetti un campionamento di numerosità 30 da una popolazione di
800 unità secondo le tecniche del campionamento casuale con e sen-
za ripetizione e del campionamento sistematico, usando la funzione
sample.

Esercizio 7
Si simuli un campione di 1000 osservazioni da una distribuzione t con
4 gradi di libertà. Attraverso la funzione qqnorm si confronti la distri-
buzione del campione con la distribuzione normale. Quali discrepanze
sono osservabili? Si ripeta, quindi, l’operazione con la distribuzione t
con 20 gradi di libertà. Che cosa cambia rispetto al caso con 4 gradi
di libertà?

Esercizio 8
Si consideri il data frame cereali. Per tutte le variabili per le qua-
li l’ipotesi di normalità non sia a priori irragionevole, ossia, per tutte
le variabili continue o discrete, ma con molte modalità, si confronti
la distribuzione delle osservazioni con la distribuzione normale tramite
un Q-Q plot normale. Per ogni Q-Q plot ottenuto, si commentino i

45
risultati, precisando se l’adattamento della normale ai dati è soddisfa-
cente e, in caso di allontanamenti dalla normalità, illustrando il tipo
di discrepanze osservate e tentando una spiegazione “fenomenica” delle
discrepanze stesse.

46
Capitolo 4

Statistica Inferenziale: stima


puntuale, stima intervallare e
verifica di ipotesi

4.1 Stima puntuale


Le conoscenze acquisite nei precedenti corsi di statistica sulla stima puntuale
sono piuttosto limitate. Per questo motivo, a tale aspetto dell’inferenza
statistica dedichiamo relativamente poco spazio.
Ricordiamo che
• uno stimatore non distorto per la media di popolazione è la media
campionaria

• uno stimatore non distorto per la varianza di popolazione è la varianza


campionaria corretta (ottenuta da R tramite la funzione var)

• uno stimatore non distorto per una percentuale/probabilità è la corri-


spondente frequenza relativa nel campione.
Vediamo alcuni esempi.
In R sono contenuti diversi data set. Molti di questi sono data set famosi
nella letteratura statistica, tra cui sleep, originariamente studiato da Stu-
dent (lo stesso della t) nel 1908 (si veda l’Help di R sotto la voce sleep).
Il data set sleep, che in R ha la struttura di un data frame, si riferisce al-
l’effetto, in termini di aumento delle ore di sonno, di due sonniferi, ciascuno
somministrato ad un gruppo di 10 soggetti. Per accedere al data frame, si
usi il comando data(sleep):
> data(sleep)
> help(sleep)

47
> sleep
extra group
1 0.7 1
2 -1.6 1
3 -0.2 1
...
19 4.6 2
20 3.4 2
Si vuole stimare la media e la varianza dell’aumento nel numero di ore di
sonno separatamente per i due sonniferi.
> attach(sleep)
> stima.media.sonnifero1=mean(extra[group=="1"])
> stima.media.sonnifero1
[1] 0.75
> stima.media.sonnifero2=mean(extra[group=="2"])
> stima.media.sonnifero2
[1] 2.33
> stima.varianza.sonnifero1=var(extra[group=="1"])
> stima.varianza.sonnifero1
[1] 3.200556
> stima.varianza.sonnifero2=var(extra[group=="2"])
> stima.varianza.sonnifero2
[1] 4.009
In base ai risultati ottenuti parrebbe che il secondo sonnifero sia più efficace
del primo, ma come sappiamo abbiamo bisogno di condurre un test di ipotesi
per poter verificare questa affermazione.
Si consideri il data frame cereali. Nell’ipotesi che il campione di 65 pro-
dotti di cereali sia rappresentativo della popolazione di cereali in commer-
cio, si vuole stimare la percentuale di prodotti in commercio con contenuto
vitaminico pari al fabbisogno giornaliero.
> attach(cereali)
> table(vitamins)
vitamins
100% enriched none
5 57 3
> stima.p=5/65
> stima.p
[1] 0.07692308
> length(vitamins[vitamins=="100%"])/65
[1] 0.07692308

48
4.2 Verifica di ipotesi e stima intervallare
Procederemo per passi, considerando i problemi “classici” di verifica di ipotesi
e stima intervallare.

4.2.1 Media di una popolazione normale


Si dispone di un campione di osservazioni x1 , x2 , . . . , xn , realizzazioni delle
variabili casuali X1 , X2 , . . . , Xn i.i.d. che seguono una distribuzione N (µ, σ 2 ).
Si è interessati a fare inferenza su µ, ossia a condurre verifiche di ipotesi e
costruire intervalli di confidenza per µ. Trattiamo separatamente il caso in
cui σ 2 sia nota e il caso σ 2 ignota.

Varianza di popolazione nota


Se σ 2 è nota, sia il test di ipotesi che l’intervallo di confidenza per µ sono
basati sulla distribuzione normale. In particolare, l’intervallo di confidenza
di livello 1 − α per µ è  s 
x̄ ± z1−α/2
σ2 
n
dove z1−α/2 è il quantile 1 − α/2 della normale standard, x̄ è la media
campionaria e n è la numerosità campionaria.
La statistica test per saggiare l’ipotesi H0 : µ = µ0 è
x̄ − µ0
zoss = q 2 ,
σ
n

dove il pedice oss di z sottolinea il fatto che si tratta del valore osservato
della statistica test. Rifiutiamo H0 al livello di significatività assegnato α
• se H1 : µ > µ0 , per zoss > z1−α , dove z1−α è il quantile 1 − α della
normale standard;

• se H1 : µ < µ0 , per zoss < −z1−α ;

• se H1 : µ 6= µ0 , per |zoss | > z1−α/2 .


Sappiamo però che la verifica di ipotesi “moderna” non viene condotta attra-
verso l’approccio rifiuto/accetto per un livello di significatività α assegnato,
come sopra descritto, ma attraverso il p–value, ossia attraverso una misura
di quanto è verosimile l’ipotesi nulla H0 alla luce delle osservazioni raccolte.
In particolare, più piccolo è il valore del p–value, più i dati ci stanno dicendo
che l’ipotesi H0 è inverosimile. Il p–value può comunque essere usato per
condurre un test di ipotesi “classico”: più precisamente,

49
• se p–value< α rifiutiamo H0 al livello di significatività α;

• se p–value> α accettiamo H0 al livello di significatività α;

Per il caso trattato, il p–value è

• se H1 : µ > µ0 , p–value=1 − Φ(zoss );

• se H1 : µ < µ0 , p–value=Φ(zoss );

• se H1 : µ 6= µ0 , p–value=2 (1 − Φ(|zoss |)).

dove Φ rappresenta la funzione di ripartizione della normale standard.


In R non troviamo funzioni per la stima intervallare o la verifica di ipotesi
su µ nel caso di varianza di popolazione nota (perché è una situazione che
raramente si incontra in pratica). Dobbiamo perciò costruire da soli le due
strumentazioni.
I dati di seguito riportati si riferiscono alla perdita di peso (in kg) di
20 soggetti che hanno seguito una dieta dimagrante per un periodo di due
settimane.

> dieta=c(6.0, 4.7, 3.8, 5.1, 2.5, 1.4, 2.8, 3.3, 5.5, 1.1,
+ 4.3, 5.3, 3.4, 5.8, 5.7, 4.9, 3.1, 2.5, 5.1, 1.8)

Supponiamo, inoltre, di sapere che la varianza di popolazione è 2 kg2 .


Poiché i promotori della dieta sostengono che questa permette di perdere
in media 5 kg in due settimane, vogliamo sottoporre a verifica questa ipotesi
e costruire un intervallo di confidenza per la perdita media di peso. Più
precisamente, indicata con µ la vera ed ignota perdita media di peso dopo due
settimane dovuta alla dieta, vogliamo costruire un intervallo di confidenza
per µ e verificare l’ipotesi H0 : µ = 5 kg.
L’intervallo di confidenza e la statistica test sopra descritti valgono se
la distribuzione da cui provengono le osservazioni è normale; pertanto, con
gli strumenti acquisiti nel capitolo precedente, verifichiamo se l’ipotesi di
normalità è ragionevole per le nostre osservazioni.

> media.dieta=mean(dieta)
> media.dieta
[1] 3.905 #piuttosto piccola rispetto ai 5 kg dei promotori
> var.dieta=var(dieta)
> var.dieta
[1] 2.386816 #accordo con la varianza di popolazione
> dieta.stand=(dieta-mean(dieta))/sqrt(var(dieta))
> qqnorm(dieta.stand)
> abline(0,1)

50
È presente qualche deviazione, ma non cosı̀ grave da farci ritenere irragio-
nevole l’ipotesi che le osservazioni provengano da una distribuzione normale.
Procediamo allora con la verifica di ipotesi e la stima intervallare per µ, nel
caso di popolazione normale con varianza nota. Iniziamo con l’intervallo di
confidenza:
> estremo.inf.ic=media.dieta-qnorm(0.975)*sqrt(2/20)
> estremo.sup.ic=media.dieta+qnorm(0.975)*sqrt(2/20)
> estremo.inf.ic.2=media.dieta-qnorm(0.95)*sqrt(2/20)
> estremo.sup.ic.2=media.dieta+qnorm(0.95)*sqrt(2/20)
> estremo.inf.ic
[1] 3.285205
> estremo.sup.ic
[1] 4.524795
> estremo.inf.ic.2
[1] 3.384852
> estremo.sup.ic.2
[1] 4.425148
Abbiamo usato due livelli di confidenza: per 1 − α = 0.95, abbiamo ottenuto
l’intervallo (3.29 kg, 4.52 kg); per 1 − α = 0.9, abbiamo ottenuto l’intervallo
(3.38 kg, 4.43 kg).
Per la relazione esistente tra intervalli di confidenza e verifica di ipotesi
con alternativa bilaterale, in base a questi risultati siamo subito in grado di
concludere che H0 : µ = 5 kg viene rifiutata sia al livello α = 0, 1 che al livello
α = 0, 05, a favore dell’ipotesi alternativa bilaterale H1 : µ 6= 5 kg. Tuttavia,
per il caso in esame, verosimilmente l’interesse è per un’ipotesi alternativa
unilaterale del tipo H1 : µ < 5 kg; in aggiunta, vogliamo seguire l’approccio
basato sul valore del p–value.
> statistica.test=(media.dieta-5)/sqrt(2/20)
> statistica.test
[1] -3.462694
> p.value=pnorm(statistica.test)
> p.value
[1] 0.0002673981
Il valore ottenuto è molto basso. L’indicazione dataci dal p–value è che l’i-
potesi nulla è inverosimile alla luce dei dati osservati, i quali invece danno
sostegno all’ipotesi alternativa H1 : µ < 5. Si noti che, seguendo un ap-
proccio “classico” alla verifica di ipotesi, rifiuteremmo H0 a favore di H1 per
qualunque valore ragionevole del livello di significatività α (α ∈ (0.01, 0.1)).
A titolo esemplificativo, calcoliamo il p–value anche per le ipotesi alter-
native H1 : µ > 5 e H1 : µ 6= 5:

51
> p.value=1-pnorm(statistica.test)
> p.value
[1] 0.9997326 #molto alto, evidenza empirica a favore di Ho
> p.value=2*(1-pnorm(abs(statistica.test)))
> p.value
[1] 0.0005347961 #molto basso, evidenza empirica a sfavore di Ho
Si noti come la “plausibilità” di H0 dipenda fortemente dall’alternativa con-
templata: nel caso H1 : µ > 5, l’ipotesi alternativa è ancor più inverosimile
di H0 , da cui il valore alto del p–value (si accetterebbe H0 e si rifiutereb-
be H1 per qualunque valore ragionevole del livello di significatività α), nel
caso H1 : µ 6= 5, che comprende anche l’intervallo µ < 5 kg, l’ipotesi H0
ritorna ad essere inverosimile tanto da essere rifiutata a qualunque livello di
significatività α ragionevole.

Varianza di popolazione ignota


Se σ 2 non è nota, sia il test di ipotesi che l’intervallo di confidenza per µ sono
basati sulla distribuzione t di Student. Per questo motivo, il test su µ con
σ 2 ignota viene chiamato test t.
L’intervallo di confidenza di livello 1 − α per µ è
 s 
x̄ ± tn−1;1−α/2
S 02 
n

dove S 02 è la varianza campionaria corretta e tn−1;1−α/2 è il quantile 1 − α/2


della distribuzione t con n − 1 gradi di libertà .
La statistica test per saggiare H0 : µ = µ0 è
x̄ − µ0
toss = q 02
S
n

Il p–value è definito in modo analogo al caso di varianza nota: basterà so-


stituire alla funzione di ripartizione della normale standard, la funzione di
ripartizione della variabile casuale t con n − 1 gradi di libertà e a zoss , toss .
In R la funzione t.test può essere usata sia per condurre verifiche di
ipotesi su µ sia per costruire intervalli di confidenza. Vediamone il funzio-
namento, usando il campione dieta, ma supponendo ora che la varianza di
popolazione, precedentemente posta pari a 2, non sia nota.
> t.test(dieta, alternative="less", mu=5, conf.level=0.95)

One Sample t-test

52
data: dieta
t = -3.1697, df = 19, p-value = 0.002523
alternative hypothesis: true mean is less than 5
95 percent confidence interval:
-Inf 4.502342
sample estimates:
mean of x
3.905

L’argomento principale di t.test è il vettore delle osservazioni campiona-


rie, nel nostro caso dieta. Le opzioni di t.test ci permetto di specificare
alcuni aspetti della verifica di ipotesi e dell’intervallo di confidenza. Con l’op-
zione alternative="less" specifichiamo un’ipotesi alternativa unilaterale a
sinistra H1 : µ < µ0 ; con l’opzione alternative="greater" l’alternativa è
unilaterale a destra H1 : µ > µ0 ; con l’opzione alternative="two.sided"
l’alternativa è bilaterale H1 : µ 6= µ0 . Con l’opzione mu specifichiamo il valore
di µ0 : con mu=5 poniamo µ0 = 5. Con l’opzione conf.level specifichiamo il
livello di confidenza dell’intervallo per µ: con conf.level=0.95 richiediamo
un intervallo di confidenza di livello 1 − α = 0.95.
Interpretiamo le componenti principali dell’output di t.test.

• t: è il valore della statistica test.

• df: sono i gradi di libertà del test (i gradi di libertà della distribuzione
t di riferimento).

• p-value: è il valore del p–value. Nel caso in esame, è un valore piutto-


sto basso che suggerisce che l’ipotesi nulla, rispetto all’ipotesi alterna-
tiva considerata, sia poco plausibile, tanto che ci porterebbe a rifiutare
H0 : µ = 5 kg a favore di H1 : µ < 5 kg per qualunque valore ragionevole
del livello di significatività α.

• 95 percent confidence interval: è l’intervallo di confidenza per il


livello specificato con l’opzione conf.level. Attenzione, avendo spe-
cificato un’ipotesi alternativa unilaterale a sinistra, l’intervallo di con-
fidenza prodotto da t.test è in realtà un estremo superiore di confi-
denza: un aspetto dell’inferenza statistica che non abbiamo preceden-
temente trattato. Per ottenere l’intervallo di confidenza a noi noto è ne-
cessario specificare una alternativa bilaterale tramite alternative="two.sided".

• sample estimates: è la stima di µ, ossia la media campionaria.

Vediamo cosa accade se specifichiamo un’ipotesi alternativa bilaterale H1 :


µ 6= 5 kg e richiediamo un livello dell’intervallo di confidenza pari a 0.99:

53
> t.test(dieta, alternative="two.sided", mu=5, conf.level=0.99)

One Sample t-test

data: dieta
t = -3.1697, df = 19, p-value = 0.005045
alternative hypothesis: true mean is not equal to 5
99 percent confidence interval:
2.916669 4.893331
sample estimates:
mean of x
3.905

In questo caso l’intervallo di confidenza di livello 0.99 ottenuto è quello a noi


noto. Il p–value ci indica che i dati non danno sostegno all’ipotesi nulla.
In fine, consideriamo l’ipotesi alternativa H1 : µ > 5 kg:

> t.test(dieta, alternative="greater", mu=5, conf.level=0.99)

One Sample t-test

data: dieta
t = -3.1697, df = 19, p-value = 0.9975
alternative hypothesis: true mean is greater than 5
99 percent confidence interval:
3.027717 Inf
sample estimates:
mean of x
3.905

Poiché l’alternativa considerata è unilaterale destra, l’intervallo di confidenza


prodotto è, in realtà, un estremo inferiore di confidenza. Il p–value è molto
alto, per cui concludiamo che i dati danno sostegno a H0 : µ = 5 kg rispetto
a H1 : µ > 5 kg.

4.2.2 Confronto tra le medie di due popolazioni nor-


mali
Siano x1 , x2 , . . . , xn1 un campione di n1 osservazioni generate dalle variabili
X1 , X2 , . . . , Xn1 i.i.d. N (µ1 , σ12 ) e y1 , y2 , . . . , yn2 un campione di n2 osser-
vazioni generate dalle variabili Y1 , Y2 , . . . , Yn2 i.i.d. N (µ2 , σ22 ). Gli obiettivi
sono costruire intervalli di confidenza per la differenza tra le due medie di
popolazione µ1 − µ2 e saggiare l’ipotesi H0 : µ1 = µ2 .

54
Considereremo nel seguito solo il caso in cui le due varianze di popolazione
σ12 e σ22 siano ignote e ipotizziamo, in aggiunta, che siano tra loro uguali
σ12 = σ22 = σ 2 . Con tali specificazioni, sia gli intervalli di confidenza che
la verifica di ipotesi per il confronto delle medie nelle due popolazioni sono
basate sulla distribuzione t. Per questo motivo, la verifica di ipotesi viene
chiamata test t a due campioni (cfr. test t ad un campione del paragrafo
4.2.1).
L’intervallo di confidenza di livello 1 − α per µ1 − µ2 è
s !
1 1

(x̄ − ȳ) ± tn1 +n2 −2;1−α/2 Sp2 +
n1 n2
dove
• x̄, ȳ sono le medie campionarie di x1 , x2 , . . . , xn1 e y1 , y2 , . . . , yn2 , rispet-
tivamente;

• tn1 +n2 −2;1−α/2 è il quantile 1 − α/2 della distribuzione t con n1 + n2 − 2


gradi di libertà;

• Sp2 è la varianza campionaria pooled:

(n1 − 1)S102 + (n2 − 1)S202


Sp2 =
n1 + n2 − 2
con S102 e S202 sono le varianza campionarie corrette di x1 , x2 , . . . , xn1 e
y1 , y2 , . . . , yn2 , rispettivamente.
La statistica test per saggiare l’ipotesi H0 : µ1 = µ2 è
x̄ − ȳ
toss = r  
1 1
Sp2 n1
+ n2

Il p–value è definito in modo analogo al caso del test su una singola media con
varianza nota: basterà sostituire alla funzione di ripartizione della normale
standard la funzione di ripartizione della distribuzione t con n1 + n2 − 2 gradi
di libertà e a zoss , toss .
La stessa funzione t.test usata per l’inferenza su una singola media,
può essere usata per il confronto tra le medie di due popolazioni normali.
Vediamone il funzionamento, lavorando con il data frame sleep.
Abbiamo osservato nel paragrafo 4.1 che il secondo sonnifero parrebbe
condurre ad un aumento medio del numero delle ore di sonno superiore ri-
spetto al primo sonnifero. Verifichiamo in modo formale questa affermazione.
Tuttavia, prima di procedere con intervalli di confidenza e test, è bene valu-
tare se le ipotesi alla base degli strumenti che utilizzeremo sono ragionevoli

55
per i campioni osservati. Si tratta, allora, di stabilire se le osservazioni su
ciascuna popolazione seguono una distribuzione normale e se l’assunto di
uguale varianza è plausibile.

> data(sleep)
> attach(sleep)
> boxplot(split(extra,group))
> sonnifero1.stand=(extra[group=="1"]-stima.media.sonnifero1)/
+ sqrt(stima.varianza.sonnifero1)
> qqnorm(sonnifero1.stand)
> abline(0,1)
> sonnifero2.stand=(extra[group=="2"]-stima.media.sonnifero2)/
+ sqrt(stima.varianza.sonnifero2)
> qqnorm(sonnifero2.stand)
> abline(0,1)

La scarsità di osservazioni per ciascuna popolazione rende difficile l’interpre-


tazione dei Q–Q plot, ma non parrebbero esserci delle grosse deviazioni dalla
distribuzione normale. Pertanto, l’ipotesi che i dati provengano da popola-
zioni normalmente distribuite non sembra irragionevole. Per quanto riguarda
l’ipotesi di uguale varianza, è possibile condurre un test formale per verifi-
care H0 : σ12 = σ22 , ma non seguiamo questa strada e ci limitiamo a fare un
confronto tra le due varianze campionarie:

> stima.varianza.sonnifero1
[1] 3.200556
> stima.varianza.sonnifero2
[1] 4.009

Le due varianze campionarie non sono molto differenti, se teniamo anche


conto della bassa numerosità campionaria; pertanto, anche l’ipotesi di ugua-
glianza delle varianze di popolazione pare accettabile alla luce dell’evidenza
campionaria. Procediamo allora con l’applicazione dei risultati sopra de-
scritti per il confronto di µ1 e µ2 . Iniziamo considerando l’ipotesi alternativa
bilaterale H1 : µ2 6= µ2

> t.test(extra[group=="1"],extra[group=="2"],alternative="two.sided",
+ conf.level=0.99,var.equal=TRUE)

Two Sample t-test

data: extra[group == "1"] and extra[group == "2"]


t = -1.8608, df = 18, p-value = 0.07919
alternative hypothesis: true difference in means is not equal to 0

56
99 percent confidence interval:
-4.024058 0.864058
sample estimates:
mean of x mean of y
0.75 2.33
La funzione t.test, quando impiegata per il confronto tra due medie, ri-
chiede come argomenti principali i vettori che contengono le osservazioni
campionarie sulle due popolazioni: nel caso in esame, extra[group=="1"] e
extra[group=="2"]. Le opzioni alternative e conf.level hanno lo stes-
so ruolo visto per il test t ad un campione. È necessario utilizzare l’opzione
var.equal=TRUE, con la quale si precisa che il test deve essere condotto sotto
l’ipotesi di uguaglianza tra le due varianze di popolazione, in quanto R è in
grado di condurre il test anche per varianze differenti (è la scelta di default),
ma questo test non verrà da noi trattato. L’output è simile a quello ottenuto
con il test t ad un campione. In particolare,
• t = -1.8608 è il valore osservato della statistica test.

• df = 18 sono i gradi di libertà della distribuzione t di riferimento (20-


2).

• p-value = 0.07919 è il p–value del test. È un valore ambiguo: l’ipo-


tesi nulla H0 : µ1 = µ2 verrebbe accettata, contro l’ipotesi alternativa
H1 : µ1 6= µ2 , al livello α = 0.05 (e a livelli più bassi), ma rifiutata
al livello α = 0.1 (e a livelli più alti). L’indicazione è che vi sia una
moderata evidenza empirica a sfavore di H0 .

• -4.024058 0.864058 è l’intervallo di confidenza per µ1 − µ2 al livello


99% (attenzione, l’ordine è lo stesso dei vettori dati come argomento
della funzione).
Consideriamo ora come ipotesi alternativa il caso in cui il secondo sonnifero
sia più efficace del primo, vale a dire H1 : µ1 < µ2 .
> t.test(extra[group=="1"],extra[group=="2"],alternative="less",
+ conf.level=0.99,var.equal=TRUE)

Two Sample t-test

data: extra[group == "1"] and extra[group == "2"]


t = -1.8608, df = 18, p-value = 0.03959
alternative hypothesis: true difference in means is less than 0
99 percent confidence interval:
-Inf 0.5872026

57
sample estimates:
mean of x mean of y
0.75 2.33
Il p–value del test è diminuito: ora H0 verrebbe rifiutata, a favore dell’ipotesi
alternativa unilaterale, anche per α = 0.05 (e per valori più alti di α), ma
continueremmo ad accettarla per α = 0.03 (e a livelli più bassi). Seppure
l’informazione campionaria sia più a sfavore di H0 rispetto al caso prece-
dente, l’evidenza non è cosı̀ netta. Questo potrebbe sembrare un risultato
sorprendente guardando alla grossa differenza tra le due medie campionarie,
ma è opportuno ricordare che il test di ipotesi tiene conto della variabilità
campionaria, che è in questo caso piuttosto elevata relativamente ai valori
delle medie.
Avendo specificato un’ipotesi alternativa unilaterale, il 99 percent confidence
interval è in realtà un estremo superiore e non l’intervallo di confidenza a
noi noto.

4.2.3 Analisi della varianza ad un fattore


Come noto, l’analisi della varianza ad un fattore è l’estensione al caso di più
di due popolazioni del test t a due campioni trattato al paragrafo precedente.
Si considera il caso generico di K popolazioni. Nella tabella seguente sono
riassunte le informazioni campionarie disponibili.

Camp. Osservazioni Provenienza


1 x11 x12 . . . x1j . . . x1n1 N (µ1 , σ12 )
2 x21 x22 . . . x2j . . . x2n2 N (µ2 , σ22 )
.. .. .. .. .. .. .. ..
. . . . . . . .
i xi1 xi2 . . . xij ... xini N (µi , σi2 )
.. .. .. .. .. .. .. ..
. . . . . . . .
2
K xK1 xK2 . . . xKj ... xKnK N (µK , σK )

Per ciascun campione, le osservazioni sono realizzazioni di altrettante varia-


bili casuali i.i.d. normali, ma con media che può cambiare da popolazione a
popolazione. L’obiettivo è verificare l’ipotesi nulla di uguaglianza delle me-
die, H0 : µ1 = µ2 = . . . = µK , contro l’ipotesi alternativa che almeno due
medie siano tra loro differenti, H1 : H̄0 . Le K varianze di popolazione sono
assunte ignote, ma tra loro uguali: σ12 = σ22 = . . . = σK
2
= σ 2 ignota.
La statistica test del precedente sistema di ipotesi si basa sulla scompo-
sizione della somma dei quadrati totale
ni
K X
(xij − x̄)2
X
SST =
i=1 j=1

58
dove x̄ è la media delle osservazioni di tutti i K campioni, nella somma dei
quadrati between e nella somma dei quadrati within:

SST = SSB + SSW

con
K
ni (x̄i − x̄)2
X
SSB =
i=1

dove x̄i (i = 1, . . . , K) è la media dell’i–esimo campione, e


ni
K X
(xij − x̄i )2 .
X
SSW =
i=1 j=1

Più precisamente, il valore osservato della statistica test è

SSB/(K − 1)
Foss =
SSW/( K
i=1 ni − K)
P

La statistica test si distribuisce, sotto H0 , come una variabile casuale F con


K −1 e K i=1 ni − K gradi di libertà. Si rifiuta H0 al livello di significatività
P

α se Foss > FK−1,PK ni −K;1−α (il quantile 1 − α della distribuzione F con i


i=1
gradi di libertà sopra specificati).
Il p–value del test è

p − value = Pr(FK−1,PK ni −K
> Foss )
i=1

La funzione di R per l’analisi della varianza è aov. Vediamone il funziona-


mento tramite un esempio.
I seguenti dati si riferiscono ad un esperimento effettuato per studiare la
resistenza allo strappo di diverse marche di impermeabili. Capi di cinque
diverse marche sono stati sottoposti alla stessa sollecitazione. La resistenza
allo strappo è stata misurata con il tempo (in minuti e frazioni decimali di
minuti) intercorso tra la sollecitazione e lo strappo.

Marca A: 2.34 2.46 2.83 2.04 2.69


Marca B: 2.64 3.00 3.19 3.83
Marca C: 2.61 2.07 2.80 2.58 2.98 2.30
Marca D: 1.32 1.62 1.92 0.88 1.50 1.30
Marca E: 0.41 0.83 0.58 0.32 1.62

Vogliamo verificare se le 5 marche hanno la stessa resistenza media. Inseriamo


i dati in R:

59
> resistenza=c(2.34, 2.46, 2.83, 2.04, 2.69, 2.64, 3.00, 3.19, 3.83,
+ 2.61, 2.07, 2.80, 2.58, 2.98, 2.30, 1.32, 1.62, 1.92, 0.88, 1.50,
+ 1.30, 0.41, 0.83, 0.58, 0.32, 1.62)
> Marca=c(rep("A",5),rep("B", 4), rep("C", 6), rep("D", 6), rep("E",5))
> resistenza
[1] 2.34 2.46 2.83 2.04 2.69 2.64 3.00 3.19 3.83 2.61 2.07 2.80 2.58
[14] 2.98 2.30 1.32 1.62 1.92 0.88 1.50 1.30 0.41 0.83 0.58 0.32 1.62
> Marca
[1] "A" "A" "A" "A" "A" "B" "B" "B" "B" "C" "C" "C" "C" "C" "C" "D"
[17] "D" "D" "D" "D" "D" "E" "E" "E" "E" "E"
> length(resistenza)
[1] 26
> length(Marca)
[1] 26

Per poter usare la funzione aov abbiamo bisogno di comunicare a R che


Marca, inserito come vettore di stringhe di caratteri, contiene le osservazioni
su una variabile qualitativa, o nella terminologia di R, su un fattore. Lo
possiamo fare tramite la funzione as.factor:

> Marca.fat=as.factor(Marca)
> Marca.fat
[1] A A A A A B B B B C C C C C C D D D D D D E E E E E
Levels: A B C D E

Attenzione, le colonne di stringhe di caratteri all’interno di un data frame


sono automaticamente trattate come osservazioni su variabili qualitative:

> dati.marche=data.frame(resistenza, Marca)


> dati.marche
resistenza Marca
1 2.34 A
2 2.46 A
...
25 0.32 E
26 1.62 E
> is.factor(dati.marche[,2])
[1] TRUE

Lavorando con il data frame dati.marche non ci sarebbe stato, pertanto, il


bisogno di creare la nuova variabile Marca.fat.
Prima di condurre l’analisi della varianza, verifichiamo attraverso una
semplice analisi esplorativa se le ipotesi su cui si basa il test, ossia normalità
e varianze costanti, sono ragionevoli per i dati in esame:

60
> boxplot(split(resistenza,Marca.fat))
> qqnorm((resistenza[Marca=="A"]-mean(resistenza[Marca=="A"]))/
+ sqrt(var(resistenza[Marca=="A"])))
> abline(0,1)
> qqnorm((resistenza[Marca=="B"]-mean(resistenza[Marca=="B"]))/
+ sqrt(var(resistenza[Marca=="B"])))
> abline(0,1)
> qqnorm((resistenza[Marca=="C"]-mean(resistenza[Marca=="C"]))/
+ sqrt(var(resistenza[Marca=="C"])))
> abline(0,1)
> qqnorm((resistenza[Marca=="D"]-mean(resistenza[Marca=="D"]))/
+ sqrt(var(resistenza[Marca=="D"])))
> abline(0,1)
> qqnorm((resistenza[Marca=="E"]-mean(resistenza[Marca=="E"]))/
+ sqrt(var(resistenza[Marca=="E"])))
> abline(0,1)
> var(resistenza[Marca=="A"])
[1] 0.09497
> var(resistenza[Marca=="B"])
[1] 0.2485667
> var(resistenza[Marca=="C"])
[1] 0.1089067
> var(resistenza[Marca=="D"])
[1] 0.1224667
> var(resistenza[Marca=="E"])
[1] 0.27317

Abbiamo pochissime osservazioni per gruppo e questo rende molto difficile


l’interpretazione dei grafici. Tuttavia, non abbiamo indicazioni di forti de-
viazioni dalla normalità e le stime delle varianze di popolazione non sono
cosı̀ eterogenee da porci grossi dubbi sulla validità dell’ipotesi di varianze
costanti. Procediamo, allora, con l’analisi della varianza.

> aov.marche=aov(resistenza~Marca.fat)
> summary(aov.marche)
Df Sum Sq Mean Sq F value Pr(>F)
Marca.fat 4 18.1681 4.5420 28.261 3.475e-08 ***
Residuals 21 3.3751 0.1607
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Gli argomenti di aov sono, nell’ordine, il vettore di osservazioni su tutti i


K gruppi e il vettore di osservazioni sul fattore che specifica l’appartenenza

61
ai gruppi. I due vettori devono essere separati dal simbolo ~. Nell’esem-
pio trattato, il risultato di aov è stato assegnato all’oggetto aov.marche.
Una sintesi del contenuto di aov.marche può essere ottenuta tramite la fun-
zione summary già incontrata nel secondo capitolo (tale funzione opera in
modi diversi a secondo del tipo di input). In particolare, la sintesi prodotta
comprende:

• Marca.fat – la prima riga fornisce informazioni sulla somma dei qua-


drati between;

• Residuals – la seconda riga fornisce informazioni sulla somma dei


quadrati within;

• Df – sono i gradi di libertà della distribuzione F di riferimento: K −


1=5-1=4 per la somma dei quadrati between, K i=1 ni − K= 26-5=21
P

per la somma dei quadrati within;

• Sum Sq – è la somma dei quadrati: 18.1681 per la between e 3.3751


per la within;

• Mean Sq – è il rapporto tra somma dei quadrati e i gradi di libertà:


4.5420 è il numeratore di Foss , 0.1607 è il denominatore di Foss ;

• F value – è il valore di Foss ;

• Pr(>F) – è il p–value del test: è un valore molto basso, che ci porte-


rebbe a rifiutare H0 a qualunque livello di significatività α ragionevole;
l’indicazione è che H0 sia altamente inverosimile e che vi siano delle
differenze significative tra le resistenze medie delle 5 marche.

Consideriamo un secondo esempio. I dati sono tratti da Freund e Wilson


(1997), pag. 220, e riguardano il raccolto di quattro varietà di riso ciascuna
assegnata in modo casuale a 4 dei 16 appezzamenti in cui è stata suddivisa
la fattoria:

Varieta’ 1: 934 1041 1028 935


Varieta’ 2: 880 963 924 946
Varieta’ 3: 987 951 976 840
Varieta’ 4: 992 1143 1140 1191

Vogliamo verificare l’uguaglianza dei raccolti medi associati alle 4 varietà.


Inseriamo i dati in R usando un data frame:

> raccolto=c(934, 1041, 1028, 935, 880, 963, 924, 946,


+ 987, 951, 976, 840, 992, 1143, 1140, 1191)
> varieta=c(rep("1",4),rep("2",4),rep("3",4),rep("4",4))

62
> varieta
[1] "1" "1" "1" "1" "2" "2" "2" "2" "3" "3" "3" "3" "4" "4" "4" "4"
> fw=data.frame(raccolto,varieta)
> attach(fw)
> varieta
[1] "1" "1" "1" "1" "2" "2" "2" "2" "3" "3" "3" "3" "4" "4" "4" "4"
> rm(varieta)
> varieta
[1] 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
Levels: 1 2 3 4
> rm(raccolto)
> raccolto
[1] 934 1041 1028 935 880 963 924 946 987 951 976 840 992
[14] 1143 1140 1191

Si noti come i vettori creati “prevalgano” sul contenuto del data frame sino
alla loro eliminazione. Si lascia allo studente la verifica empirica delle ipotesi
alla base dell’analisi della varianza e il confronto tra le 4 distribuzioni tramite
boxplot (attenzione alla scarsità di dati!).

> fw.aov=aov(raccolto~varieta)
> summary(fw.aov)
Df Sum Sq Mean Sq F value Pr(>F)
varieta 3 89931 29977 7.2124 0.005034 **
Residuals 12 49876 4156
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Si paragonino i risultati ottenuti con la tabella di pag. 224 di Freund e


Wilson. Il valore di Foss (rapporto tra Mean Sq di varieta e Mean Sq di
Residuals) è 7.2124. Se confrontiamo questo valore con la distribuzione
F di riferimento con 3, 12 gradi di libertà, otteniamo un p–value pari a
0.005034, che indica che vi sono differenze significative tra i raccolti medi
delle 4 varietà .

4.2.4 Test di indipendenza nelle tabelle a doppia en-


trata
Sia dato un campione di ampiezza n sul quale sono osservate due variabili
X e Y che assumono rispettivamente le modalità (x1 , . . . , xr ) e (y1 , . . . , ys ).
Sia nij il numero di unità del campione che presentano la modalità xi della
prima variabile e la modalità yj della seconda variabile, con i = 1, . . . , r e
j = 1, . . . , s. Siano ni· = sj=1 nij , n·j = ri=1 nij e n = ri=1 ni· = sj=1 n·j .
P P P P

63
I dati sono in genere presentati tramite una tabella, detta tabella a doppia
entrata, di dimensione (r × s), in cui la quantità nella i-esima riga e j-esima
colonna è nij .
Per verificare l’ipotesi nulla H0 di indipendenza stocastica delle due varia-
bili in alternativa a H1 , che invece ipotizza la dipendenza delle due variabili,
si può usare l’indice χ2 , dato da
r X
s
(nij − n∗ij )2
χ2 =
X
,
i=1 j=1 n∗ij

dove n∗ij , per i = 1, . . . , r e j = 1, . . . , s, è la frequenza teorica sotto l’ipotesi


di indipendenza, espressa da n∗ij = (ni· n·j )/n. Sotto H0 la distribuzione
approssimata di χ2 è la distribuzione chi-quadrato con (r − 1)(s − 1) gradi
di libertà. Si rifiuta H0 al livello di significatività α se l’indice χ2 risulta
superiore del quantile 1−α della distribuzione chi–quadrato con (r −1)(s−1)
gradi di libertà, χ2(r−1)(s−1);1−α . Il p–value del test è

p − value = Pr(χ2(r−1)(s−1) > χ2 )

Attenzione, i risultati distributivi sopra riportati possono essere considerati


una buona approssimazione per n∗ij ≥ 5.
In R è disponibile la funzione chisq.test che esegue il test χ2 su una
tabella a doppia entrata.
Vediamone il funzionamento tramite un esempio. In un’indagine sono sta-
ti classificati 1725 bambini di una scuola secondo l’intelligenza e l’apparente
livello economico della famiglia. Una classificazione riassuntiva è:
Tardo Intelligente Molto capace
Molto ben vestito 81 322 233
Ben vestito 141 457 153
Poveramente vestito 127 163 48
Si vuole verificare l’indipendenza tra le due variabili.
La funzione chisq.test richiede come argomento principale la tabella a
doppia entrata delle frequenze assolute congiunte, sotto forma di una matrice.
> mat=matrix(c(81, 322, 233, 141 ,457, 153,127 ,163 ,48),ncol=3,
+ byrow=TRUE)
> mat
[,1] [,2] [,3]
[1,] 81 322 233
[2,] 141 457 153
[3,] 127 163 48
> chisq.test(mat,correct=FALSE)

64
Pearson’s Chi-squared test

data: mat
X-squared = 134.6854, df = 4, p-value < 2.2e-16

L’opzione correct=FALSE è necessaria, perché di default R applica una


correzione per continuità al test che non è stata da noi trattata.
L’output ottenuto è
(1) X-squared: il valore dell’indice χ2 ;
(2) df: gradi di libertà della distribuzione approssimata dell’indice sotto H0
((3-1)(3-1)=4);
(3) p-value: il p–value del test. Dal valore ottenuto per il p–value, notia-
mo che i dati avvalorano l’ipotesi di dipendenza tra l’intelligenza e il livello
economico della famiglia.
Vediamo un secondo esempio. Il file assicurazione.txt, messo a dispo-
sizione degli studenti, contiene informazioni riguardanti 1235 clienti di una
compagnia di assicurazione, classificati in base alla loro età (classi di età:
< 25, 25-30, 30-35, >35) e allo stato di rischio (Sı̀, se hanno causato almeno
un incidente nell’ultimo anno, No, altrimenti). Si vuole valutare se tra l’età
e lo stato di rischio vi sia una forma di dipendenza.

> assicurazione=read.table("c:/mywork/assicurazione.txt",
+ header=TRUE)
> dim(assicurazione)
[1] 1235 2
> assicurazione
Eta Incidente
1 30-35 Si
2 25-29 Si
3 25-29 Si
...
1234 >35 No
1235 25-29 No
> attach(assicurazione)
> table(Eta)
Eta
<25 >35 25-29 30-35
113 503 238 381
> table(Incidente)
Incidente
No Si
1110 125

65
Poiché i dati sono in forma grezza, la funzione table, introdotta nel capitolo
2 per la costruzione di una tabella di frequenza univariata, viene ora usata per
ottenere la tabella a doppia entrata che verrà data come input a chisq.test:

> table(Eta,Incidente)
Incidente
Eta No Si
<25 80 33
>35 477 26
25-29 210 28
30-35 343 38
> chisq.test(table(Eta,Incidente),correct=FALSE)

Pearson’s Chi-squared test

data: table(Eta, Incidente)


X-squared = 59.5077, df = 3, p-value = 7.489e-13

Dal p–value concludiamo che l’evidenza empirica dà sostegno all’ipotesi di


una forma di associazione tra le due variabili e quindi che lo stato di rischio
di un soggetto dipende dalla sua età.

4.3 Esercizi
Esercizio 1
Si consideri il data frame studenti. Assumendo che il campione di
65 studenti sia rappresentativo dell’intera popolazione di studenti della
Facoltà di Scienze Politiche, si verifichi l’ipotesi nulla che il voto medio
alla maturità degli studenti di Scienze Politiche sia pari a 50, conside-
rando tutte e 3 le possibili ipotesi alternative. Si commentino i risultati
ottenuti. Si costruisca, inoltre, l’intervallo di confidenza di livello 99%
per lo stesso voto medio.

Esercizio 2
Si acceda al data frame cars. Considerando il campione di 93 modelli
rappresentativo della popolazione di modelli di automobili in commer-
cio, si verifichi l’ipotesi nulla che la lunghezza media dei modelli di
automobili in commercio sia pari a 180 pollici, contro tutte e 3 le pos-
sibili ipotesi alternative. Si commentino i risultati ottenuti. Si costrui-
sca, inoltre, un intervallo di confidenza di livello 95% per la lunghezza
media.

66
Esercizio 3
Si consideri il data frame assicurazione introdotto al paragrafo 4.2.4.
Senza tener conto dell’età e utilizzando noti risultati, si costruisca un
intervallo di confidenza di livello 95% per la percentuale di assicurati
che causano almeno un incidente in un anno.

Esercizio 4
Si considerino i dati sulle marche di impermeabili del paragrafo 4.2.3. È
possibile dire che le marche A, B, C sono più resistenti, in media, delle
marche D,E? A questo fine si creino due vettori per le osservazioni sui
due gruppi di marche. Si costruisca, inoltre, un intervallo di confidenza
di livello 90% per la differenza tra le due medie.

Esercizio 5
I seguenti dati riguardano i tempi di caricamento (in secondi) di due
diverse pagine web per una connessione via modem. Il numero di
osservazioni disponibili per le due pagine sono, rispettivamente, 20 e
25.

pagina 1: 2.3, 3.4, 3.2, 2.2, 0.9, 3.4, 2.4, 1.9,


1.5, 2.5, 3.0, 2.8, 0.6, 2.5, 0.6, 1.8,
0.4, 2.6, 0.5, 1.3
pagina 2: 3.3, 2.2, 2.4, 1.6, 4.0, 2.7, 2.8, 4.9,
4.9, 3.9, 2.3, 2.5, 3.7, 2.1, 2.0, 2.7,
3.7, 4.5, 1.8, 1.9, 4.6, 3.9, 3.4, 3.1,
2.6

È possibile dire, ad un livello di significatività pari al 5%, che i tempi


medi di caricamento delle due pagine sono uguali, contro l’alternativa
che la seconda pagina abbia tempi di caricamento mediamente più lun-
ghi? Si ottenga, inoltre, un intervallo di confidenza di livello 95% per
la differenza tra i due tempi medi di caricamento.

Esercizio 6
Si consideri il data frame studenti. Escludendo dall’analisi l’indirizzo
di studi Altro, esiste una differenza significativa tra i voti medi alla
maturità degli studenti che scelgono i restanti indirizzi di studi?

Esercizio 7
In R è incluso il data frame InsectSprays che riguarda il numero di
insetti osservati in unità agricole sperimentali trattate con 6 diversi tipi
di insetticida. Le due colonne del data frame riportano rispettivamente

67
count: numero di insetti
spray: tipo di insetticida (tra A,B,C,D,E e F)

Si verifichi se esiste una differenza significativa nell’efficacia dei 6 inset-


ticidi.

Esercizio 8
È stato messo a disposizione degli studenti il file gelati.txt. Esso
riguarda la preferenza di gusto di gelato di un campione di 40 individui,
classificati per sesso. Le colonne del file sono:

gusto: gusto preferito


sesso

Esiste una dipendenza tra le due variabili considerate?

Esercizio 9
Un’indagine su un campione di 100 imprese ha prodotto i seguenti
risultati relativi alla redditività e alla quota di mercato:

Quota di mercato
Redditività <15% 15–30% >30%
Bassa 18 7 8
Media 13 11 8
Alta 8 12 15

I dati evidenziano un’associazione tra quota di mercato e redditività?

68
Capitolo 5

Statistica Inferenziale: il
modello di regressione lineare

5.1 Introduzione
5.1.1 Definizione di un modello di regressione
Un modello di regressione lineare può essere descritto, in generale, nel modo
che segue. Si considerano una variabile risposta Y ed una o più variabili
esplicative X1 , . . . , Xm . La variabile Y è rappresentabile tramite la relazione
Y = β0 + β1 X1 + . . . + βm Xm + ε, (5.1)
in cui β0 ha il ruolo di intercetta (lo si può pensare come ad un coefficiente
associato ad una variabile esplicativa identicamente uguale a 1), β1 , . . . , βm
sono i parametri che individuano la relazione tra Y e le variabili esplicative
ed ε è la variabile dell’errore casuale, che rappresenta la parte di variabilità
di Y non riducibile alla dipendenza da X1 , . . . , Xm .
Avendo a disposizione un insieme di n osservazioni, ciascuna delle qua-
li è prodotta dal modello (5.1), obiettivo è fare inferenza sui parametri
β0 , . . . , βm . Utilizzando la notazione matriciale, si può scrivere
y = Xβ + ε,
dove y = (y1 , . . . , yn )T è il vettore contenente le n osservazioni sulla variabile
risposta, X = [xij ] è la matrice di regressione (o delle condizioni sperimentali)
di dimensione n × (m + 1) contenente i valori delle variabili esplicative (gli
elementi della prima colonna di X sono pari a 1), ε = (ε1 , . . . , εn )T è il vettore
contenente le n componenti della variabile di errore e β = (β0 , . . . , βm )T è il
vettore dei parametri di regressione. Si assume che
εi ∼ N (0, σ 2 ), i = 1, . . . , n, indipendenti.

69
5.1.2 Stima e verifica di ipotesi per un modello di re-
gressione
Lo stimatore di β con il metodo dei minimi quadrati è

β̂ = (X T X)−1 X T y = CX T y,

con C = (X T X)−1 , ed è possibile dimostrare che

β̂ ∼ N (β, σ 2 C),

da cui si deduce che β̂ è uno stimatore corretto di β.


Se si è interessati anche alla stima di σ 2 , si può considerare
Pn 2
2 i=1 ri
S = (5.2)
n−m−1
dove ri è il residuo associato all’i–esima osservazione, ossia lo scarto tra
il valore effettivamente osservato per Y e il valore stimato dal modello di
regressione: ri = yi − ŷi , con ŷi = β̂0 + β̂1 xi1 + . . . + β̂m xim . Questo stimatore
è corretto per σ 2 .
È utile ricordare la scomposizione
n n n
yi2 − nȳ 2 ) = ( ŷi2 − nȳ 2 ) + ri2 ,
X X X
(
i=1 i=1 i=1
Pn
della somma dei quadrati totale SST = ( i=1 yi2 − nȳ 2 ) in somma dei
quadrati di regressione SSR = ( ni=1 ŷi2 − nȳ 2 ) e somma dei quadrati re-
P

sidua SSE = ni=1 ri2 . Lo studio di queste componenti è fondamentale


P

nell’ambito dei modelli lineari, in quanto il confronto tra SSR e SST è


un’indicatore della bontà di adattamento del modello di regressione ai da-
ti. In particolare, un indicatore normalizzato (con valori in [0, 1]) della
bontà di adattamento è il coefficiente di determinazione lineare del modello
R2 = SSR/SST = 1 − SSE/SST . Quanto più R2 è prossimo a 1, tanto più
il modello è soddisfacente in quanto i punti osservati yi sono vicini a quelli
stimati ŷi . Infatti, se R2 = 1 deve essere SSE = 0 e ciò significa che, per
ogni i, yi = ŷi .
Per verificare l’ipotesi nulla della significatività complessiva del modello,
ossia H0 : β1 = . . . = βm = 0, contro H1 : H̄0 (almeno un coefficiente è
diverso da 0), può essere utilizzata la statistica test
SSR/m
F = (5.3)
SSE/(n − m − 1)
che, sotto H0 , segue una distribuzione F con m, n − m − 1 gradi di libertà.
Posto con Foss il valore osservato della statistica test, si rifiuta H0 al livello

70
di significatività α se Foss > F1−α;m,n−m−1 , ossia Foss è maggiore del quantile
1 − α della distribuzione F con i gradi di libertà sopra specificati. Il p–value
del test è Pr(Fm,n−m−1 > Foss ).
Per verificare l’ipotesi nulla di significatività di un singolo parametro,
ossia H0 : βj = 0 (j = 1, . . . , m) può essere utilizzata la statistica test

β̂j
t= q (5.4)
cjj S 2

dove cjj è il j–esimo elemento sulla diagonale di C. Sotto H0 , t si distribuisce


come una variabile casuale t di Student con n − m − 1 gradi di libertà. Se
l’ipotesi alternativa specifica H1 : βj 6= 0, si rifiuta H0 al livello di significa-
tività α se il il valore osservato della statistica test toss è in valore assoluto
maggiore del quantile 1 − α/2 della distribuzione t con n − m − 1 gradi di
libertà: |toss | > tn−m−1;1−α/2 . Per lo stesso sistema di ipotesi il p–value è
2Pr(tn−m−1 > |toss |).

5.1.3 Analisi dei residui


Oltre alle verifiche di ipotesi descritte sommariamente nel precedente pa-
ragrafo, è necessario completare lo studio dell’adattamento del modello di
regressione ai dati mediante un’analisi dei residui. A questo fine, si può
ricorrere ad alcuni semplici strumenti grafici, quali

1. grafico dei residui, ri , rispetto ai valori stimati dal modello, ŷi . Tale
grafico è utile per verificare se le ipotesi sui termini di errore εi (varianza
costante e indipendenza) sono corrette.

2. grafico dei residui ri rispetto alle variabili esplicative presenti nel mo-
dello. Tale grafico è utile per individuare scorrette specificazioni della
dipendenza dalle variabili esplicative (come, ad esempio, dipendenze
non lineari);

3. Q-Q plot normale dei residui ri per verificare la validità dell’ipotesi di


normalità sui termini di errore εi .

Se il modello è soddisfacente, i diagrammi 1. e 2. non evidenziano alcun


andamento sistematico, mentre il diagramma 3. segue un andamento linea-
re. Ogni scostamento da tale situazione indica la necessità di migliorare il
modello, attraverso, ad esempio, trasformazioni della variabile risposta e/o
delle variabili esplicative. I diagrammi 1. e 2. permettono inoltre di indivi-
duare eventuali residui particolarmente elevati, in valore assoluto, associati
ad osservazioni che non vengono ben colte dal modello.

71
5.2 Inferenza su un modello di regressione
lineare in R
La funzione di R per la stima di un modello di regressione lineare multipla
è lm. La sua sintassi generale è

lm(formula)

in cui formula specifica l’espressione del modello di regressione ed è esprimi-


bile nella forma

variabile risposta ~ elenco delle variabili esplicative separate da +

Il risultato di lm è un oggetto composto da numerosi elementi che riassumono


la stima del modello ed a cui si può accedere tramite il simbolo $. I principali
sono:
1. coef: stime dei coefficienti di regressione, β̂;
2. residuals: residui del modello, ri ;
3. fitted: valori stimati dal modello di regressione, ŷi .
Sono disponibili anche numerose funzioni che permettono di utilizzare le in-
formazioni del risultato di lm, tra le quali
1. summary: sintesi convenzionale dei risultati di una analisi di regressione;
2. predict: valori previsti per nuovi dati.

Per il loro utilizzo si vedano gli esempi che seguono.

5.3 Esempi di regressione lineare semplice in


R
Iniziamo la discussione dei modelli di regressione lineare in R prendendo in
esame il caso della regressione lineare semplice, ossia di un’unica variabile
esplicativa.

5.3.1 Esempio 1: l’occupazione


Il file occupazione.txt, messo a disposizione degli studenti, contiene un in-
sieme di dati macroeconomici relativi al numero di persone occupate (Employed)
e al prodotto interno lordo, deflazionato ai valori del 1954, (RealGNP) rilevati
negli Stati Uniti negli anni 1947–1962 (Year). Questo data set fa parte di
un più ampio insieme di dati originariamente analizzato da J. W. Longley
(1967). Siamo interessati a spiegare l’andamento del numero di occupati in
funzione del PIL. Importiamo il file in R:

72
> occupazione=read.table("c:occupazione.txt",header=TRUE)
> attach(occupazione)
> occupazione
Year Employed RealGNP
1 1947 60.323 282.276
2 1948 61.122 293.137
3 1949 60.171 292.578
4 1950 61.187 317.988
5 1951 63.221 341.970
6 1952 63.639 353.720
7 1953 64.989 369.076
8 1954 63.761 363.112
9 1955 66.019 392.756
10 1956 67.857 400.746
11 1957 68.169 408.458
12 1958 66.513 401.215
13 1959 68.655 428.689
14 1960 69.564 440.106
15 1961 69.331 447.859
16 1962 70.551 474.674

Iniziamo lo studio con un’analisi descrittiva dei dati che ci permetterà di


individuare eventuali valori anomali e valutare se un modello di regressione
lineare è una scelta ragionevole per rappresentare le variazioni di Employed
in funzione di RealGNP.

> summary(RealGNP)
Min. 1st Qu. Median Mean 3rd Qu. Max.
282.3 336.0 380.9 375.5 413.5 474.7
> summary(Employed)
Min. 1st Qu. Median Mean 3rd Qu. Max.
60.17 62.71 65.50 65.32 68.29 70.55
> boxplot(RealGNP)
> boxplot(Employed)
> plot(RealGNP,Employed)

I dati non sembrano presentare valori inusuali. Dal diagramma di dispersione


si nota una forte, anche se non perfetta, relazione di tipo lineare tra le due
variabili, confermata anche dall’alto valore del coefficiente di correlazione:

> cor(RealGNP,Employed)
[1] 0.986509

73
In base ai risultati ottenuti, un modello di regressione lineare semplice della
forma
Employed = β0 + β1 RealGNP + ε,
sembra adeguato a rappresentare la dipendenza di Employed da RealGNP.
Procediamo, allora, con la stima della retta di regressione.
> reg.occupazione=lm(Employed~RealGNP)
> summary(reg.occupazione)

Call:
lm(formula = Employed ~ RealGNP)

Residuals:
Min 1Q Median 3Q Max
-0.8272 -0.3340 -0.1798 0.4612 1.0587

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 43.264226 0.989313 43.73 2.25e-16 ***
RealGNP 0.058726 0.002605 22.55 2.10e-12 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.5951 on 14 degrees of freedom


Multiple R-Squared: 0.9732, Adjusted R-squared: 0.9713
F-statistic: 508.4 on 1 and 14 DF, p-value: 2.105e-12
Interpretiamo l’output della funzione summary applicata al risultato di lm.
• Residuals: sintesi dei residui ri del modello stimato.

• Coefficients: risultati inferenziali relativi ai coefficienti della regres-


sione β0 e β1 . In particolare, la colonna Estimate riporta i valori stima-
ti dei due parametri, β̂0 e β̂1 ; la colonna Std. Error l’errore standard
(scarto quadratico medio stimato) delle stime (il denominatore della
statistica test (5.4)); la colonna t value il valore osservato della sta-
tistica test (5.4)), la colonna Pr(>|t|) il p–value del test che pone a
confronto H0 : βj = 0 contro H1 : βj 6= 0.

• Residual standard error: è S, la radice quadrata di (5.2).

• Multiple R-Squared: è il valore di R2 (Ajusted R-squared è un ag-


giustamento del valore di R2 per tener conto del numero di parametri
del modello; non verrà considerato all’interno di questo corso).

74
• F-statistic: è il valore osservato della statistica test (5.3) con i gradi
di libertà della distribuzione F di riferimento e il p–value associato al
test.

Guardano ai risultati ottenuti, il modello stimato è

Employed
d = 43.264226 + 0.058726 × RealGNP

Possiamo, inoltre, osservare che la variabile RealGNP ha un effetto non trascu-


rabile sulla variabile Employed (dal p–value del test che verifica H0 : β1 = 0
contro H1 : β1 6= 0 deduciamo che β1 è significativamente diverso da 0).
Anche l’intercetta del modello risulta significativamente diversa da 0. Si ri-
corda che è comunque buona pratica mantenere l’intercetta in un modello
di regressione, anche se questa è non significativa, in quanto eliminandola,
si perderebbero alcune proprietà (ad esempio, i residui ri non avrebbero più
media nulla). L’elevato valore ottenuto per il coefficiente di determinazio-
ne lineare R2 esprime la buona capacità esplicativa del modello selezionato.
Si ricorda che per una regressione lineare semplice l’R2 è il coefficiente di
correlazione lineare tra le due variabili elevato al quadrato:

> (cor(RealGNP,Employed))^2
[1] 0.9732

Nel caso di una regressione lineare semplice la statistica test (5.3) è il quadra-
to della statistica test (5.4) riferita al coefficiente di regressione β1 (22.552 =
508.5 e i due p–value sono uguali). Pertanto i due test portano alle mede-
sime conclusioni riguardo all’effetto della variabile esplicativa sulla variabile
dipendente.
Procediamo ora a valutare l’adeguatezza del modello di regressione per i
dati in esame attraverso l’analisi dei residui, iniziando con il diagramma di
dispersione dei residui rispetto ai valori stimati:

> plot(reg.occupazione$fitted, reg.occupazione$residuals,


+ xlab="valori stimati", ylab="residui")

Con il comando reg.occupazione$fitted si ottiene il vettore dei valo-


ri stimati ŷi della regressione reg.occupazione. Analogamente, tramite
reg.occupazione$residuals si ottiene il vettore dei residui ri = yi − ŷi .
Dal grafico non si identificano andamenti sistematici che ci fanno dubitare
delle ipotesi sui termini di errore εi . Non sembrano neppure essere presen-
ti residui particolarmente elevati, in valore assoluto. Consideriamo anche il
grafico dei residui rispetto alla variabile esplicativa:

> plot(RealGNP, reg.occupazione$residuals,xlab="PIL", ylab="residui")

75
È opportuno precisare che nella regressione lineare semplice, il diagramma di
dispersione dei residui rispetto alla variabile esplicativa non aggiunge molto
rispetto al diagramma di dispersione dei residui rispetto ai valori stimati,
essendo questi ultimi una semlice trasformazione lineare della variabile espli-
cativa. Tuttavia, acquistiamo da subito l’abitudine di costruire questo tipo di
grafico che nella regressione multipla, trattata nel paragrafo 5.4, è fondamen-
tale. Entrambi i grafici non presentano sistematicità, per cui pare ragionevole
assumere una dipendenza lineare di Employed da RealGNP. Completiamo l’a-
nalisi dei residui con un Q-Q plot normale. A questo riguardo, ricordiamo
che per costruzione i residui ri hanno media nulla
> mean(reg.occupazione$residuals)
[1] -3.903128e-18
ma non hanno, in generale, varianza unitaria
> var(reg.occupazione$residuals)
[1] 0.3305502
pertanto, nel costruire il Q-Q plot normale, standardizziamo i residui divi-
dendo per il loro scarto quadratico medio:
> qqnorm(reg.occupazione$residuals/sqrt(var(reg.occupazione$residuals)))
> abline(0,1)
Il Q-Q plot mostra qualche deviazione dalla retta di riferimento, tuttavia
data la bassa numerosità delle osservazioni è difficile stabilire se queste de-
viazioni sono l’effetto di una reale non normalità dei residui o se sono dovute
a variabilità nei dati. In base ai risultati ottenuti possiamo considerare soddi-
sfacente l’adattamento del modello di regressione ai dati. A completamento,
tracciamo sul diagramma di dispersione di Employed rispetto a RealGNP la
retta di regressione stimata.
> plot(RealGNP,Employed)
> reg.occupazione$coef
(Intercept) RealGNP
43.26422581 0.05872557
Il comando reg.occupazione$coef fornisce le stime dei due coefficienti di
regressione. Pertanto, con
> abline(reg.occupazione$coef)
aggiungiamo la retta di regressione stimata al grafico di dispersione preesi-
stente.
Utilizziamo la retta stimata per prevedere il numero di occupati in funzio-
ne di futuri valori del PIL. A questo fine impieghiamo la funzione predict:

76
> predict(reg.occupazione, data.frame(RealGNP=500),
+ interval="prediction",level=0.95)
fit lwr upr
[1,] 72.62701 71.13889 74.11514

Il primo argomento di predict deve essere il risultato di lm. Il secondo


argomento è un data frame in cui si specifica il valore della/e variabile/i
esplicativa/e in corrispondenza del quale si vuole ottenere una previsione per
la variabile risposta (i nomi delle colonne del data frame devono coincidere
con quelli delle variabili esplicative). Con l’opzione interval="prediction"
si richiede ad R di produrre anche l’intervallo di previsione. Per l’inter-
vallo di confidenza sulla media condizionata è necessario usare l’opzione
interval="confidence":

> predict(reg.occupazione, data.frame(RealGNP=500),


+ interval="confidence",level=0.95)
fit lwr upr
[1,] 72.62701 71.86194 73.39209

Con l’opzione level si precisa il livello di previsione o di confidenza dell’in-


tervallo. Leggendo i risultati ottenuti, il valore previsto per il numero di
occupati in corrispondenza di un PIL pari a 500 è 72.62701 con intervallo
di previsione di livello 95% pari a (71.13889, 74.11514) e intervallo di confi-
denza dello stesso livello pari a (71.86194, 73.39209). È possibile richiedere
previsioni per diversi valori della variabile esplicativa:

> prev.occupazione=predict(reg.occupazione,
+ data.frame(RealGNP=seq(475,500,5)), interval="prediction",level=0.95)
> prev.occupazione
fit lwr upr
1 71.15887 69.73066 72.58709
2 71.45250 70.01319 72.89182
3 71.74613 70.29526 73.19699
4 72.03976 70.57690 73.50261
5 72.33338 70.85810 73.80867
6 72.62701 71.13889 74.11514

Aggiungiamo i valori previsti al grafico di dispersione di Employed e RealGNP:

> min(RealGNP)
[1] 282.276
> min(Employed)
[1] 60.171
> plot(RealGNP,Employed,xlim=c(282,500),ylim=c(60,74.2))

77
> points(seq(475,500,5), prev.occupazione[,1],pch=2)
> lines(seq(475,500,5), prev.occupazione[,2])
> lines(seq(475,500,5), prev.occupazione[,3])
> abline(reg.occupazione$coef)
Con l’opzione xlim= di plot si specifica il campo di variazione delle ascisse;
analogamente ylim= specifica il campo di variazione delle ordinate. Entram-
be devono essere seguite da un vettore che contiene, nell’ordine, il valore
minimo e il valore massimo del campo di variazione. L’opzione pch=2 con-
sente di rappresentare i punti nel diagramma con un simbolo diverso da quello
di default. Numeri diversi corrispondono a simboli diversi; il simbolo di de-
fault (il punto) è ottenibile con pch=1. Per maggiori dettagli si veda l’Help
di R alla voce par.
Nel condurre previsioni per dati futuri, è importante ricordare che è, in
generale, pericoloso cercare di prevedere valori della variabile dipendente cor-
rispondenti a valori delle esplicative molto distanti dal campo di osservazione.

5.3.2 Esempio 2: le cucitrici e l’effetto dei punti in-


fluenti
Il file cucitrici.txt si riferisce al numero (numero) e al punteggio medio
(punteggio) dei capi completati in una data giornata da 12 cucitrici im-
piegate in una fabbrica di capi di abbigliamento in cui ad ogni capo viene
assegnato un punteggio in base alla sua qualità. La paga di ciascuna cuci-
trice dipende in parte dal numero di capi completati. Si vuole studiare la
dipendenza del punteggio medio dal numero di capi prodotti.
Importiamo i dati in R:
> cucitrici=read.table("c:cucitrici.txt",header=TRUE)
> cucitrici
cucitrice numero punteggio
1 1 14 7.2
2 2 13 7.3
3 3 17 6.9
4 4 16 7.3
5 5 17 7.5
6 6 18 7.6
7 7 19 6.8
8 8 32 3.7
9 9 18 6.5
10 10 15 7.9
11 11 15 6.8
12 12 19 7.1

78
> attach(cucitrici)

Iniziamo con un’analisi descrittiva dei dati.

> summary(numero)
Min. 1st Qu. Median Mean 3rd Qu. Max.
13.00 15.00 17.00 17.75 18.25 32.00
> summary(punteggio)
Min. 1st Qu. Median Mean 3rd Qu. Max.
3.700 6.800 7.150 6.883 7.350 7.900
> boxplot(numero)
> boxplot(punteggio)
> plot(numero,punteggio)

È evidente la presenza di un valore anomalo, sia rispetto alla variabile espli-


cativa che rispetto alla variabile dipendente,

> identify(numero,punteggio,n=1)
[1] 8

corrispondente all’ottava cucitrice. Dal diagramma di dispersione parreb-


be esserci una relazione lineare di segno negativo tra le due variabili, come
confermato dal coefficiente di correlazione:

> cor(numero,punteggio)
[1] -0.9013145

Tuttavia, sorge il sospetto che l’indicazione di una dipendenza lineare negati-


va tra punteggio e numero possa essere l’effetto proprio del punto anomalo.
In effetti, se eliminiamo dall’analisi l’ottava cucitrice

> plot(numero[-8],punteggio[-8])
> cor(numero[-8],punteggio[-8])
[1] -0.3116176

assistiamo ad un indebolimento del grado di dipendenza.


Non essendo note le cause dell’anomalia rilevata, conviene condurre l’a-
nalisi del modello di regressione lineare semplice

punteggio = β0 + β1 numero + ε

sia includendo che escludendo l’ottava cucitrice, in modo da poter valutare


la sensibilità dei risultati al dato anomalo.

79
> reg.cucitrici1=lm(punteggio~numero)
> summary(reg.cucitrici1)

Call:
lm(formula = punteggio ~ numero)

Residuals:
Min 1Q Median 3Q Max
-0.62914 -0.37320 -0.03143 0.46552 0.76629

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 10.40626 0.55366 18.80 3.94e-09 ***
numero -0.19847 0.03016 -6.58 6.23e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4885 on 10 degrees of freedom


Multiple R-Squared: 0.8124, Adjusted R-squared: 0.7936
F-statistic: 43.3 on 1 and 10 DF, p-value: 6.233e-05
Il parametro β1 associato alla variabile esplicativa numero risulta signifi-
cativamente diverso da 0; pertanto, numero ha un valore esplicativo non
trascurabile per la variabile punteggio. Proseguiamo con l’analisi dei residui.
> plot(reg.cucitrici1$fitted,reg.cucitrici1$residuals)
> identify(reg.cucitrici1$fitted,reg.cucitrici1$residuals,n=1)
[1] 8
> plot(numero,reg.cucitrici1$residuals)
> identify(numero,reg.cucitrici1$residuals,n=1)
[1] 8
> qqnorm(reg.cucitrici1$residuals/sqrt(var(reg.cucitrici1$residuals)))
> abline(0,1)
Non si osserva dai diagrammi di dispersione dei residui rispetto ai valori sti-
mati e alla variabile esplicativa la presenza di residui particolarmente elevati,
in valore assoluto, ma è evidente la presenza di un punto che si discosta dagli
altri per avere un valore inusuale sia della variabile esplicativa che della ri-
sposta stimata. Il Q-Q plot normale presenta alcune deviazioni dalla retta di
riferimento, ma non preoccupanti, se si considera anche la bassa numerosità
campionaria.
> plot(numero,punteggio)
> abline(reg.cucitrici1$coef)

80
Dal grafico della retta di regressione stimata sul diagramma di dispersione di
numero e punteggio si nota come il modello di regressione cerchi di cogliere il
punto anomalo. Ripetiamo le stesse operazioni, eliminando l’ottava cucitrice.

> punteggio2=punteggio[-8]
> numero2=numero[-8]
> reg.cucitrici2=lm(punteggio2~numero2)
> summary(reg.cucitrici2)

Call:
lm(formula = punteggio2 ~ numero2)

Residuals:
Min 1Q Median 3Q Max
-0.57545 -0.22545 -0.09018 0.23013 0.63571

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 8.20848 1.05994 7.744 2.87e-05 ***
numero2 -0.06295 0.06398 -0.984 0.351
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4083 on 9 degrees of freedom


Multiple R-Squared: 0.09711, Adjusted R-squared: -0.003216
F-statistic: 0.9679 on 1 and 9 DF, p-value: 0.3509

Tolta l’ottava cucitrice, l’effetto di numero non risulta più significativo. Inol-
tre, l’R2 ha subito una forte riduzione.

> plot(reg.cucitrici2$fitted,reg.cucitrici2$residuals)
> plot(numero2,reg.cucitrici2$residuals)
> qqnorm(reg.cucitrici2$residuals/sqrt(var(reg.cucitrici2$residuals)))
> abline(0,1)
> plot(numero,punteggio)
> abline(reg.cucitrici1$coef)
> abline(reg.cucitrici2$coef)

Non notiamo nei primi due grafici andamenti sistematici ed è migliorato il Q-


Q plot normale. Complessivamente l’osservazione sull’ottava cucitrice ha un
forte effetto sulla stima del modello, tanto da trasformare la variabile espli-
cativa da significativa a non significativa. Un punto con tali caratteristiche è
chiamato punto influente. Tipicamente, un punto influente è caratterizzato

81
da valori inusuali sia per la variabile esplicativa che per la variabile dipen-
dente. Esso determina uno spostamento del modello di regressione verso il
punto stesso, tanto che in molti casi (come nel presente) può non presentare
un residuo particolarmente elevato.
La scelta di quale insieme di risultati utilizzare (reg.cucitrici1 o reg.cucitrici2?)
è spesso problematica e condizionata alla disponibilità di informazioni ag-
giuntive. Ad esempio, se sospettiamo che l’osservazione influente sia il risul-
tato di un errore di misurazione o di circostanze straordinarie, sarebbe più
opportuno fare affidamento sui risultati ottenuti escludendo il punto stesso.
Se, per contro, riteniamo il punto un’osservazione genuina prodotta sotto
condizioni normali, sarebbe pericoloso non tenerne conto.
Per misurare la discrepanza tra i due modelli, prevediamo il valore di
punteggio per il numero di capi dell’ottava cucitrice, sulla base dei risultati
ottenuti senza il punto influente:

> numero[8]
[1] 32
> predict(reg.cucitrici2,data.frame(numero2=32),
+ interval="prediction", level=0.95)
fit lwr upr
[1,] 6.194196 3.746142 8.642251
> punteggio[8]
[1] 3.7

5.3.3 Esempio 3: le miglia aeree e le trasformazioni


Le osservazioni contenute nel file airmiles.txt rappresentano le miglia per-
corse dai passeggeri delle linee aeree commerciali americane negli anni 1937–
1955.

> miglia.aeree=read.table("c:airmiles.txt",header=TRUE)
> miglia.aeree
miglia anno
1 412 1937
2 480 1938
...
18 16769 1954
19 19819 1955
> attach(miglia.aeree)

Si è interessati a spiegare le variazioni temporali del traffico aereo, ossia ad


individuare un modello che ci permetta di esprimere miglia in funzione di
anno.

82
> summary(miglia)
Min. 1st Qu. Median Mean 3rd Qu. Max.
412 1402 5948 6307 9285 19820
> boxplot(miglia)
> plot(anno,miglia)
Il diagramma di dispersione mette in rilievo una evidente deviazione dall’i-
potesi di linearità. Tuttavia, stimare il modello lineare

miglia = β0 + β1 anno + ε

può essere un utile esercizio, soprattutto al fine di imparare a trattare op-


portunamente situazioni di questo tipo.
> reg.miglia=lm(miglia~anno)
> summary(reg.miglia)

Call:
lm(formula = miglia ~ anno)

Residuals:
Min 1Q Median 3Q Max
-2556.1 -1808.2 -359.4 1414.1 4506.5

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.941e+06 1.731e+05 -11.21 2.82e-09 ***
anno 1.001e+03 8.894e+01 11.25 2.68e-09 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2123 on 17 degrees of freedom


Multiple R-Squared: 0.8816, Adjusted R-squared: 0.8746
F-statistic: 126.6 on 1 and 17 DF, p-value: 2.685e-09
> plot(reg.miglia$fitted,reg.miglia$residuals)
> plot(anno,reg.miglia$residuals)
> qqnorm(reg.miglia$residuals/sqrt(var(reg.miglia$residuals)))
> abline(0,1)
> plot(anno,miglia)
> abline(reg.miglia$coef)
È importante notare come, senza un’analisi dei residui, saremmo indotti a ri-
tenere soddisfacente il modello di regressione stimato: la variabile esplicativa
risulta significativa e l’R2 è piuttosto elevato. Tuttavia, i grafici dei residui

83
contro i valori stimati e l’anno presentano un andamento sistematico che è
sintomo di una violazione delle ipotesi alla base del modello di regressione e
della incapacità del modello stesso di cogliere a pieno le variazioni di miglia
in funzione di anno. In particolare, il modello stimato non coglie la curvatura
nelle osservazioni. Anche il Q-Q plot normale mostra delle deviazioni sulla
coda sinistra.
Ritorniamo al diagramma di dispersione delle due variabili.

> par(mfrow=c(1,2))
> plot(anno,miglia)

Osserviamo un andamento tendenzialmente esponenziale delle miglia ae-


ree nel tempo. Pertanto, una trasformata logaritmica di miglia dovrebbe
riportarci ad una relazione almeno approssimativamente lineare:

> plot(anno,log(miglia))

Possiamo allora pensare di stimare il modello di regressione lineare con la


variabile risposta trasformata

log(miglia) = β0 + β1 anno + ε (5.5)

> log.miglia=log(miglia)
> reg.miglia2=lm(log.miglia~anno)
> summary(reg.miglia2)

Call:
lm(formula = log.miglia ~ anno)

Residuals:
Min 1Q Median 3Q Max
-0.26002 -0.12180 -0.04432 0.09232 0.52197

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -4.139e+02 1.635e+01 -25.32 6.17e-15 ***
anno 2.169e-01 8.401e-03 25.82 4.46e-15 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2006 on 17 degrees of freedom


Multiple R-Squared: 0.9751, Adjusted R-squared: 0.9737
F-statistic: 666.4 on 1 and 17 DF, p-value: 4.458e-15

84
Si osservi come i risultati inferenziali siano complessivamente migliorati: sia
la significatività di anno che l’R2 sono aumentati. Tuttavia, questi valori non
sono sufficienti a garantire la bontà di adattamento ai dati del nuovo modello
di regressione. Procediamo, pertanto, all’analisi dei residui.
> par(mfrow=c(1,2))
> plot(reg.miglia$fitted,reg.miglia$residuals)
> plot(reg.miglia2$fitted,reg.miglia2$residuals)
> plot(anno,reg.miglia$residuals)
> plot(anno,reg.miglia2$residuals)
Dal confronto dei residui prima e dopo la trasformazione della variabile di-
pendente, possiamo concludere che il ricorso alla trasformata logaritmica di
miglia ha ridotto gli andamenti sistematici, ma permangono degli schemi
di variazione che sono indice di un non perfetto adattamento ai dati. In
particolare, osserviamo una forma parabolica nei nuovi residui che potrebbe
indicare la necessità di includere una potenza della variabile anno nel modello
di regressione. Ritorneremo su questo punto nel paragrafo 5.4, quando verrà
trattata la regressione multipla. Inoltre, cogliamo la presenza di due residui
relativamente elevati. Verifichiamo a quali osservazioni corrispondono.
> identify(anno,reg.miglia2$residuals,n=2)
[1] 10 11
> miglia.aeree[c(10,11),]
miglia anno
10 5948 1946
11 6109 1947
> par(mfrow=c(1,1))
> plot(anno,miglia)
I due residui elevati corrispondono ai due punti che nel diagramma di disper-
sione di miglia su anno si discostano dall’andamento fondo.
> par(mfrow=c(1,2))
> qqnorm(reg.miglia$residuals/sqrt(var(reg.miglia$residuals)))
> abline(0,1)
> qqnorm(reg.miglia2$residuals/sqrt(var(reg.miglia2$residuals)))
> abline(0,1)
Alcune deviazioni dalla retta di riferimento sono ancora osservabili nel Q-Q
plot normale.
> plot(anno,miglia)
> abline(reg.miglia$coef)
> plot(anno,log(miglia))
> abline(reg.miglia2$coef)

85
Per poter rappresentare i risultati del nuovo modello di regressione sulla scala
originaria dobbiamo ricorrere alla trasformata esponenziale:
> par(mfrow=c(1,1))
> plot(anno,miglia)
> abline(reg.miglia$coef)
> lines(anno,exp(reg.miglia2$fitted))
Complessivamente, possiamo dire che l’uso della trasformata logaritmica ha
migliorato l’adattamento del modello di regressione ai dati ma alcune discre-
panze sono ancora presenti che potrebbero richidere ulteriori manipolazioni
(cfr. paragrafo 5.4.2).
Per fare delle previsioni su valori futuri delle miglia aeree sulla base del
nuovo modello di regressione, dobbiamo nuovamente ricorrere alla trasforma-
ta esponenziale.
> prev=predict(reg.miglia2,data.frame(anno=c(1956:1960)),
+ interval="prediction", level=0.95)
fit lwr upr
1 10.33762 9.868664 10.80658
2 10.55450 10.078560 11.03044
3 10.77138 10.287907 11.25485
4 10.98826 10.496729 11.47979
5 11.20514 10.705053 11.70522
> prev.miglia=exp(prev)
> prev.miglia
fit lwr upr
1 30872.53 19315.51 49344.43
2 38349.64 23826.65 61724.79
3 47637.66 29375.22 77253.77
4 59175.17 36196.92 96740.29
5 73506.99 44580.57 121202.52
Particolare cautela è richiesta nella previsione in modelli log–lineari come
quello utilizzato in questo paragrafo. Essi infatti assumono un andamento
esponenziale che per molti fenomeni diventa irragionevole nel lungo periodo.
A titolo esemplificativo, sono disponibili per le miglia aeree le osservazioni
degli anni 1956–1960:
> effettive=c(22362, 25340, 25343, 29269, 30514)
Confrontiamole graficamente con le nostre previsioni.
> plot(anno, miglia,xlim=c(1937,1960),ylim=c(0,73507))
> lines(c(anno,1956:1960),c(exp(reg.miglia2$fitted),prev.miglia[,1]))
> points(1956:1960,effettive,col="red")

86
5.4 Esempi di regressione lineare multipla in
R
Tratteremo in questo paragrafo alcuni esempi di regressione lineare multipla,
ossia modelli in cui la variabile dipendente è espressa come funzione lineare
di più di una variabile esplicativa.

5.4.1 Esempio 1: la teoria di Modigliani


La teoria sviluppata da Franco Modigliani sul risparmio asserisce che il tasso
di risparmio (i risparmi personali aggregati sul reddito utilizzabile) è spie-
gato dal reddito pro-capite utilizzabile, dal tasso di variazione annuale del
reddito pro-capite utilizzabile e da due variabili demografiche: la percentuale
di popolazione di età inferiore a 15 anni e la percentuale di popolazione di
età superiore a 75 anni. In R è disponibile il data frame LifeCycleSavings
che per 50 diverse nazioni riporta le 5 variabili

sr tasso di risparmio
pop15 % di popolazione sotto i 15 anni
pop75 % di popolazione sopra i 75 anni
dpi reddito pro-capite utillizzabile (a valori reali)
ddpi tasso di crescita di dpi

I valori presentati per le 5 variabili sono il risultato di una media fatta sugli
anni 1960–1970. Siamo interessati ad utilizzare questo insieme di dati per ve-
rificare la teoria di Modigliani, usando la variabile sr come variabile risposta
espressa in funzione delle restanti 4 variabili esplicative.

> data(LifeCycleSavings)
> attach(LifeCycleSavings)
> LifeCycleSavings
sr pop15 pop75 dpi ddpi
Australia 11.43 29.35 2.87 2329.68 2.87
Austria 12.07 23.32 4.41 1507.99 3.93
Belgium 13.17 23.80 4.43 2108.47 3.82
.... .......
Libya 8.89 43.69 2.07 123.58 16.71
Malaysia 4.71 47.20 0.66 242.69 5.08

Si lascia allo studente l’analisi descrittiva di ogni singola variabile.

> pairs(LifeCycleSavings)

87
Con il comando pairs(LifeCycleSavings) otteniamo una matrice di dia-
grammi di dispersione. Ogni colonna e ogni riga della matrice è associata ad
una variabile del data frame. Ad esempio, la prima riga mostra i diagrammi
di dispersione della variabile sr rispetto alle restanti variabili del data frame;
la prima colonna contiene i diagrammi di dispersione di ciasuna delle varia-
bili del data frame, esclusa sr, rispetto a sr (è in sostanza la versione riflessa
della prima riga). Tramite questo grafico, siamo in grado di capire quali
sono le relazioni bivariate tra tutte le variabili coinvolte; non solo la dipen-
denza della variabile risposta dalle variabili esplicative, ma anche le relazioni
esistenti tra le variabili esplicative stesse. Possiamo cosı̀ notare una leggera
dipendenza di segno negativo di sr da pop15 e una dipendenza più marcata
di segno positivo di sr da ddpi, mentre non si osserva alcuna particolare
forma di relazione tra sr e pop75 o dpi. È opportuno sottolineare che queste
relazioni bivariate sono spurie, ossia non tengono conto dell’effetto congiunto
di tutte le variabili. Notiamo inoltre una forte dipendenza di segno negativo
tra pop15 e le variabili pop75 e dpi, e una relazione di segno positivo tra
pop75 e dpi.
Partiamo da un modello di regressione multipla che include tutte e 4 le
variabili esplicative:

sr = β0 + β1 pop15 + β2 pop75 + β3 dpi + β4 ddpi + ε

Come precisato al paragrafo 5.2, per stimare un modello di regressione


multipla tramite la funzione lm dobbiamo far seguire alla variabile risposta
il simbolo ~ e l’elenco delle variabili esplicative separate da +:

> mod=lm(sr~pop15+pop75+dpi+ddpi)
> summary(mod)

Call:
lm(formula = sr ~ pop15 + pop75 + dpi + ddpi)

Residuals:
Min 1Q Median 3Q Max
-8.2422 -2.6857 -0.2488 2.4280 9.7509

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 28.5660865 7.3545161 3.884 0.000334 ***
pop15 -0.4611931 0.1446422 -3.189 0.002603 **
pop75 -1.6914977 1.0835989 -1.561 0.125530
dpi -0.0003369 0.0009311 -0.362 0.719173
ddpi 0.4096949 0.1961971 2.088 0.042471 *

88
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.803 on 45 degrees of freedom


Multiple R-Squared: 0.3385, Adjusted R-squared: 0.2797
F-statistic: 5.756 on 4 and 45 DF, p-value: 0.0007904

Guardando ai risultati inferenziali sui singoli coefficienti di regressione, no-


tiamo che solo la variabile pop15 ha un coefficiente significativamente diverso
da 0. Per ddpi vi è solo una moderata indicazione contro l’ipotesi H0 : β4 = 0
(l’ipotesi verrebbe rifiutata al livello 5%, ma accettata, per esempio, al livello
3% e a livelli inferiori). Gli altri coefficienti (con eccezione dell’intercetta)
non risultano significativamente diversi da 0. L’R2 è piuttosto basso, indican-
do che il modello nel suo complesso non ha una grande capacità esplicativa
rispetto alla variabile risposta. Nell’esempio considerato, la statistica F ve-
rifica l’ipotesi nulla H0 : β1 = . . . = β4 = 0, contro l’ipotesi alternativa che
almeno un parametro sia diverso da 0. Dal p–value siamo indotti a rifiutare
H0 , verosimilmente per effetto della significatività dei parametri β1 e β4 .
Proseguiamo con un’analisi dei residui che ci permetterà di valutare se
il modello si adatta bene ai dati e, eventualmente, di individuarne i punti
deboli.

> par(mfrow=c(3,2))
> plot(mod$fitted,mod$residuals)
> plot(pop15,mod$residuals)
> plot(pop75,mod$residuals)
> plot(dpi,mod$residuals)
> plot(ddpi,mod$residuals)

Si nota una leggera tendenza della varianza dei residui ad aumentare con
pop15, per il resto, non si osservano preoccupanti andamenti sistematici.
Rileviamo dal grafico dei residui e ddpi un valore anomalo rispetto a que-
st’ultima variabile; verifichiamone la presenza nel diagramma di dispersione
di sr su ddpi:

> plot(ddpi,sr)

È effettivamente un valore inusuale per ddpi, tuttavia, non essendo associato


ad un valore anomalo per la variabile risposta, difficilmente si tratta di un
punto influente. Concludiamo l’analisi dei residui con un Q-Q plot normale:

> par(mfrow=c(1,1))
> qqnorm(mod$residuals/sqrt(var(mod$residuals)))
> abline(0,1)

89
I punti seguono perfettamente la retta di riferimento, pertanto sembra ade-
guata l’ipotesi di normalità dei termini di errore εi . Complessivamente, l’ana-
lisi dei residui non ha evidenziato grosse deviazioni dall’ipotesi del modello,
il quale può essere ritenuto soddisfacente.
Possiamo ora interpretare i risultati inferenziali alla luce della teoria di
Modigliani. Delle 4 variabili che Modigliani propone come determinanti del
tasso di risparmio, solo due (di cui una marginalmente) risultano significative.
Inoltre, l’R2 del modello è piuttosto basso. Questo ci fa pensare che, oltre a
quelli considerati in questa analisi, vi siano altri i fattori che possono incidere
sul tasso di risparmio.
Poiché 2 delle 4 variabili esplicative considerate non risultato associate ad
un parametro significativamente diverso da 0, possiamo pensare di sempli-
ficare il modello senza perdere in capacità esplicativa rispetto alla variabile
risposta. Seguiamo una procedura all’indietro (backward selection) eliminan-
do la variabile che risulta meno significativa in base al corrispondente p–value,
ossia la variabile dpi :

> mod2=lm(sr~pop15+pop75+ddpi)
> summary(mod2)

Call:
lm(formula = sr ~ pop15 + pop75 + ddpi)

Residuals:
Min 1Q Median 3Q Max
-8.2539 -2.6159 -0.3913 2.3344 9.7070

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 28.1247 7.1838 3.915 0.000297 ***
pop15 -0.4518 0.1409 -3.206 0.002452 **
pop75 -1.8354 0.9984 -1.838 0.072473 .
ddpi 0.4278 0.1879 2.277 0.027478 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.767 on 46 degrees of freedom


Multiple R-Squared: 0.3365, Adjusted R-squared: 0.2933
F-statistic: 7.778 on 3 and 46 DF, p-value: 0.0002646

La prima cosa che notiamo è che è migliorata la significatività di tutte le


variabili rimaste. Ad esempio, per pop75 siamo passati da un p–value pari
a 0.13 ad un p–value pari a 0.07. Questa variabile che prima risultava non

90
significativa, ora risulta, seppure marginalmente, significativa: rifiuteremmo
l’ipotesi di nullità del parametro ad essa associato al livello 10%, ma l’ac-
cetteremmo al livello 5%. La spiegazione di questo cambiamento può essere
ritrovata nella relazione identificata all’inizio dell’analisi tra dpi e le variabili
pop75 e pop15. Spesso, quando tra variabili esplicative esiste una relazione,
l’eliminazione di una delle variabili ha effetti sulle stime del modello.
L’R2 di mod2 è diminuito rispetto a mod. Vale in generale che l’elimina-
zione di una o più variabili porti a una riduzione dell’R2 . Tuttavia, se le
variabili eliminate sono non significative, anche la riduzione dell’R2 è “non
significativa”.
Non sembra opportuno procedere con un ulteriore semplificazione del mo-
dello, dato che tutte le variabili incluse hanno un ruolo nello spiegare sr. Pos-
siamo allora rivedere le nostre conclusioni riguardo alla teoria di Modigliani.
Delle 4 variabili proposte dall’economista 3 risultano rilevanti nel determi-
nare il tasso di risparmio. Tuttavia, l’R2 del modello selezionato è piuttosto
basso e permane il dubbio che altre variabili non considerate influenzino il
fenomeno del risparmio.
Concludiamo l’esempio, trattando il problema della previsione. Supponia-
mo, ad esempio, di essere interessati a prevedere il tasso di risparmio sr corri-
spondente a (pop15=33, pop75=2, ddpi=3) e (pop15=37, pop75=2, ddpi=3),
in base al modello di regressione multipla stimato mod2. A questo fine, si uti-
lizza ancora la funzione predict, ma nel data frame delle nuove osservazioni
dovremmo precisare i valori di tutte le variabili esplicative del modello:
> predict(mod2,data.frame(pop15=c(33,37),pop75=c(2,2),ddpi=c(3,3)),
+ interval="prediction",level=0.95)
fit lwr upr
1 10.828684 3.077458 18.57991
2 9.021574 1.355349 16.68780

5.4.2 Esempio 2: le miglia aree e le trasformazioni


(continua)
Riprendiamo il data frame miglia.aeree e il modello di regressione con
variabile risposta trasformata (5.5). Avevamo rilevato un andamento pa-
rabolico nel grafico dei residui rispetto alla variabile esplicativa anno, che
può essere interpretato come un suggerimento ad includere la variabile anno
attraverso una forma quadratica. In altre parole, possiamo pensare ad un
modello di regressione del tipo

log(miglia) = β0 + β1 anno + β2 anno2 + ε

Procediamo con la stima di questo nuovo modello.

91
> reg.miglia3=lm(log.miglia~anno + I(anno^2))

Quando includiamo una trasformazione di una variabile all’interno della for-


mula del modello, possiamo procedere in due modi: il primo è definire la
variabile trasformata prima di utilizzare lm per poi richiamarla all’interno
della formula (come fatto, ad esempio, per log.miglia); il secondo procedi-
mento è di inserire la trasformazione direttamente all’interno della formula,
ma in questo caso la trasformazione deve essere inclusa tramite I(), come
fatto nel precedente esempio.

> summary(reg.miglia3)

Call:
lm(formula = log.miglia ~ anno + I(anno^2))

Residuals:
Min 1Q Median 3Q Max
-0.225215 -0.098130 -0.005284 0.045813 0.370831

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.949e+04 4.737e+03 -4.115 0.000810 ***
anno 1.982e+01 4.868e+00 4.072 0.000886 ***
I(anno^2) -5.038e-03 1.251e-03 -4.028 0.000973 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1457 on 16 degrees of freedom


Multiple R-Squared: 0.9876, Adjusted R-squared: 0.9861
F-statistic: 639.7 on 2 and 16 DF, p-value: 5.416e-16

La variabile anno al quadrato ha un coefficiente che risulta fortemente signifi-


cativo. Inoltre, rispetto al modello (5.5), l’R2 è aumentato. Verifichiamo ora
se questa modifica ha effetti benefici anche sul comportamento dei residui.

> par(mfrow=c(2,2))
> plot(reg.miglia3$fitted, reg.miglia3$residuals)
> plot(anno, reg.miglia3$residuals)
> plot(anno^2, reg.miglia3$residuals)
> qqnorm(reg.miglia3$residuals/sqrt(var(reg.miglia3$residuals)))
> abline(0,1)

Non si notano sistematicità nei grafici dei residui rispetto ai valori stimati
e alle variabili esplicative. Anche il Q-Q plot normale è migliorato rispetto

92
al modello (5.5). Complessivamente, possiamo ritenere il nuovo modello di
regressione soddisfacente.
Tracciamo il grafico della curva di regressione stimata sul diagramma di
dispersione di miglia rispetto a anno:

> par(mfrow=c(1,1))
> plot(anno,miglia)
> lines(anno,exp(reg.miglia2$fitted))
> lines(anno,exp(reg.miglia3$fitted),col="red",lty=2)

L’opzione lty=2 consente di tracciare delle linee tratteggiate sul diagramma


preesistente; valori diversi da 2 producono diversi tipi di linea.
Per la previsione di valori futuri, dobbiamo ricordare

1. che per ritornare alla scala originaria dobbiamo utilizzare la trasformata


esponenziale;

2. che è necessario prestare particolare cautela nelle previsioni di lungo


termine, in parte per l’utilizzo della forma esponenziale e in parte per
l’uso del quadrato di anno, che se opportuni nel campo di variazione
osservato potrebbero portare ad estrapolazioni inverosimili.

> prev2=predict(reg.miglia3,data.frame(anno=c(1956:1960)),
+ interval="prediction", level=0.95)
> prev2
fit lwr upr
1 9.984959 9.595617 10.37430
2 10.096038 9.673105 10.51897
3 10.197041 9.732421 10.66166
4 10.287969 9.773647 10.80229
5 10.368820 9.797029 10.94061

Si noti che nello specificare i valori futuri per la variabile esplicativa è suf-
ficiente precisare i nuovi punti per anno: R si preoccuperà di calcolare la
potenza di anno necessaria per la previsione. Facciamo un confronto con
le precedenti previsioni e con i valori effettivamente osservati per gli anni
1956–1960:

> prev.miglia2=exp(prev2)
> prev.miglia2
fit lwr upr
1 21697.64 14700.21 32025.91
2 24246.75 15884.59 37011.04
3 26823.71 16855.30 42687.53

93
4 29377.04 17564.71 49133.19
5 31850.86 17980.25 56421.76
> prev.miglia
fit lwr upr
1 30872.53 19315.51 49344.43
2 38349.64 23826.65 61724.79
3 47637.66 29375.22 77253.77
4 59175.17 36196.92 96740.29
5 73506.99 44580.57 121202.52
> effettive
[1] 22362 25340 25343 29269 30514
Anche in termini previsivi il nuovo modello si comporta meglio di (5.5).

5.4.3 Esempio 3: i crash test e la regressione polinomia-


le
Uno dei vantaggi di R è quello di mettere a disposizione varie librerie, scritte
da diversi autori, che implementano particolari insiemi di procedure statisti-
che (molte delle quali a noi ignote!). Tra le varie librerie, troviamo anche
MASS, i cui autori sono W. Venables e B. Ripley. Per accedere al contenuto
di MASS si dia il comando
> library(MASS)
In MASS è compreso il data frame mcycle che riporta 133 osservazioni relative
all’accelerazione della testa in funzione del tempo dopo l’impatto in incidenti
simulati di motocicletta utilizzati per testare la resistenza di caschi di prote-
zione. Le variabili sono:
times: tempo in millesecondi dopo l’impatto
accel: accelerazione della testa in g.
Accediamo al data frame in questione:
> data(mcycle)
> attach(mcycle)
Iniziamo lo studio della dipendenza dell’accelerazione dal tempo tramite un
diagramma di dispersione:
> plot(times,accel,xlab="Tempo",ylab="Accelerazione")
È evidente che esiste un legame tra le due variabili, ma anche che questo
legame non ha forma lineare. Cerchiamo una soluzione ricorrendo ad una
regressione polinomiale, ossia ad un modello di regressione multipla del tipo
accel = β0 + β1 times + β2 times2 + . . . + timesm + ε. (5.6)

94
Il problema è la scelta del grado m del polinomio più appropriato.
Una prima precisazione riguardo a modelli di regressione polinomiale è
che spesso l’uso di potenze relativamente elevate della variabile esplicativa
conduce a problemi di stabilità delle stime. Un modo per superare questo
ostacolo è di lavorare con una versione standardizzata della variabile espli-
cativa, ad esempio sottraendo alla variabile stessa la sua media. Questa è la
strada che seguiremo in questo esempio, definendo la nuova variabile

> times.st=times-mean(times)

Un modo per scegliere il grado del polinomio (non è l’unico, né necessa-
riamente il migliore) è stimare inizialmente un polinomio di grado elevato,
più alto di quello che verosimilmente sarà appropriato per i dati in esame, e
procedere ad una eliminazione all’indietro, sfruttando la funzione anova di
R. Per il data frame mcycle, il diagramma di dispersione suggerisce che per
cogliere l’andamento dei dati sarà necessario un polinomio di grado piuttosto
elevato. Partiamo allora da un modello con polinomio di grado 15.

> pol15=lm(accel~times.st+I(times.st^2)+I(times.st^3)+I(times.st^4)+
+ I(times.st^5)+ I(times.st^6)+I(times.st^7)+I(times.st^8)+I(times.st^9)+
+ I(times.st^10)+I(times.st^11)+I(times.st^12)+I(times.st^13)+
+ I(times.st^14)+I(times.st^15))
> anova(pol15)
Analysis of Variance Table

Response: accel
Df Sum Sq Mean Sq F value Pr(>F)
times.st 1 27079 27079 51.6676 6.659e-11 ***
I(times.st^2) 1 17221 17221 32.8575 7.870e-08 ***
I(times.st^3) 1 57499 57499 109.7107 < 2.2e-16 ***
I(times.st^4) 1 45 45 0.0866 0.7690391
I(times.st^5) 1 60417 60417 115.2781 < 2.2e-16 ***
I(times.st^6) 1 7040 7040 13.4331 0.0003730 ***
I(times.st^7) 1 23592 23592 45.0142 7.345e-10 ***
I(times.st^8) 1 26590 26590 50.7347 9.268e-11 ***
I(times.st^9) 1 1016 1016 1.9391 0.1664100
I(times.st^10) 1 20027 20027 38.2132 9.556e-09 ***
I(times.st^11) 1 588 588 1.1211 0.2918630
I(times.st^12) 1 5415 5415 10.3317 0.0016902 **
I(times.st^13) 1 218 218 0.4156 0.5203935
I(times.st^14) 1 34 34 0.0639 0.8008214
I(times.st^15) 1 123 123 0.2340 0.6294789
Residuals 117 61319 524

95
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

La funzione anova conduce un’analisi sequenziale della significatività delle


variabili incluse nel modello, rispettando l’ordine con cui le variabili sono
state inserite. L’output di anova viene interpretato nel modo seguente. La
prima riga, relativa a times.st, riproduce i risultato del test che verifica la
significatività del parametro associato a times.st quando la variabile viene
aggiunta al modello con la sola intercetta. La statistica utilizzata a questo
fine è il quadrato della statistica test t definita da (5.4). La seconda riga,
relativa a I(times.st^2) riproduce lo stesso test di significatività, ma con
riferimento alla variabile I(times.st^2), quando questa viene aggiunta al
modello che include intercetta e variabile times.st. Analogo ragionamento
per le successive righe. Guardando i valori del p–value notiamo che le po-
tenze dalla tredicesima alla quindicesima non sono significative. (Si lascia
allo studente verificare che aggiungendo termini di grado più elevato questi
risultano non significativi.) Potremmo, allora, pensare di scegliere per m il
valore 12. Esploriamo il modello risultante.

> pol12=lm(accel~times.st+I(times.st^2)+I(times.st^3)+I(times.st^4)+
+ I(times.st^5)+ I(times.st^6)+I(times.st^7)+I(times.st^8)+I(times.st^9)+
+ I(times.st^10)+I(times.st^11)+I(times.st^12))
> summary(pol12)

Call:
lm(formula = accel ~ times.st + I(times.st^2) + I(times.st^3) +
I(times.st^4) + I(times.st^5) + I(times.st^6) + I(times.st^7) +
I(times.st^8) + I(times.st^9) + I(times.st^10) + I(times.st^11) +
I(times.st^12))

Residuals:
Min 1Q Median 3Q Max
-75.781 -12.284 1.046 11.995 50.613

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -6.536e+01 4.743e+00 -13.782 < 2e-16 ***
times.st 2.398e+01 1.659e+00 14.457 < 2e-16 ***
I(times.st^2) 1.044e+00 2.455e-01 4.254 4.19e-05 ***
I(times.st^3) -4.078e-01 4.248e-02 -9.601 < 2e-16 ***
I(times.st^4) -4.255e-03 3.382e-03 -1.258 0.210865
I(times.st^5) 2.598e-03 3.845e-04 6.756 5.40e-10 ***
I(times.st^6) -6.008e-06 1.660e-05 -0.362 0.718033

96
I(times.st^7) -7.787e-06 1.575e-06 -4.944 2.52e-06 ***
I(times.st^8) 7.794e-08 3.369e-08 2.314 0.022393 *
I(times.st^9) 1.111e-08 2.981e-09 3.728 0.000295 ***
I(times.st^10) -1.745e-10 4.141e-11 -4.215 4.86e-05 ***
I(times.st^11) -6.110e-12 2.117e-12 -2.886 0.004625 **
I(times.st^12) 1.239e-13 3.817e-14 3.245 0.001520 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 22.67 on 120 degrees of freedom


Multiple R-Squared: 0.7998, Adjusted R-squared: 0.7798
F-statistic: 39.96 on 12 and 120 DF, p-value: < 2.2e-16

Non tutte le potenze hanno coefficienti che risultano significativi, tuttavia la


preferenza è in generale di utilizzare un polinomio completo, anche se questo
implica mantenere alcune variabili che sono poco significative. Il valore di
R2 suggerisce che complessivamente la regressione polinomiale spiega un’alta
percentuale della variabilità di accel. Conduciamo un’analisi dei residui.

> plot(pol12$fitted,pol12$residuals)
> plot(times.st,pol12$residuals)
> plot(times.st^2,pol12$residuals)
> plot(times.st^3,pol12$residuals)
> plot(times.st^4,pol12$residuals)
> qqnorm(pol12$residuals/sqrt(var(pol12$residuals)))
> abline(0,1)

La variabilità dei residui sembra dipendere dal valore delle variabili espli-
cative. Questa è una violazione delle ipotesi del modello che ci fà dubitare
della sua bontà. Il Q-Q plot normale mostra alcune deviazioni, ma nulla di
particolarmente preoccupante.

> plot(times, accel)


> lines(times,pol12$fitted)

È chiaro il motivo della dipendenza della varianza dei residui dalla variabile
esplicativa: per valori relativamente bassi del tempo le osservazioni seguono
da vicino il polinomio, ma la loro variabilità attorno alla curva stimata cre-
sce a tempi di impatto più elevati. In conclusione, il modello sembra cogliere
alcuni andamenti di fondo delle osservazioni, ma presenta delle carenze che
non sono colmabili con il ricorso a polinomi di grado più elevato. Soluzioni
a questo problema potrebbero essere trovate in trasformazioni della varia-
bile dipendente o nel ricorso a strumenti statistici diversi dalla regressione
polinomiale, ma non verrano qui considerate.

97
Come precisato nel paragrafo 5.4.2 è bene essere cauti nelle previsio-
ni basate su una regressione polinomiale, perché gli andamenti al di fuori
del campo di osservazione potrebbero differire da quelli colti dal modello.
Prevediamo il valore dell’accelerazione corrispondente a times=20:30:
> prev=predict(pol12,data.frame(times.st=20:30-mean(times)),
+ interval="prediction",level=0.95)
> prev
fit lwr upr
1 -116.950714 -162.97370 -70.9277294
2 -122.029313 -168.17997 -75.8786519
3 -119.190976 -165.39070 -72.9912530
4 -108.655402 -154.80079 -62.5100145
5 -91.526718 -137.54130 -45.5121333
6 -69.618335 -115.50011 -23.7365565
7 -45.198260 -91.02735 0.6308305
8 -20.691938 -66.58819 25.2043179
9 1.618239 -44.43782 47.6742938
10 19.859817 -26.37341 66.0930394
11 32.772603 -13.57995 79.1251518
> points(20:30, prev[,1],col="red")
Nella previsione, abbiamo standardizzato i “nuovi” valori della variabile
esplicativa, sottraendo la media di times.

5.5 Esercizi
Esercizio 1
Si consideri il data frame cereali introdotto al paragrafo 1.9 e analiz-
zato parzialmente nel Capitolo 2. Si studi l’andamento della variabile
calories (quantità di calorie per porzione) in funzione della variabile
fat (quantità di grassi per porzione) attraverso un opportuno model-
lo di regressione. A questo fine, si presti attenzione alla osservazione
corrispondente all’unità 31, già valutata anomala al Capitolo 2. Infine,
in base al modello stimato si prevedano i valori di calories corrispon-
denti a valori di fat tra 1 e 8 con un passo pari a 0.2. Si tracci sul
diagramma di dispersione dei dati i valori previsti e i corrispondenti
intervalli di previsione al livello 99%.
Esercizio 2
Nella libreria MASS di Venables e Ripley è incluso il data frame mammals
che fornisce per 62 specie di mammiferi i pesi medi del cervello in gram-
mi (colonna brain) e del corpo in chilogrammi (colonna body). Si vuole

98
spiegare le dipendenza del peso medio del cervello dal peso medio del
corpo. A questo fine, si acceda al data frame, come descritto al para-
grafo 5.4.3 e si costruiscano il diagramma di dispersione della variabile
brain sulla variabile body e il diagramma di dispersione della variabile
brain trasformata attraverso il logaritmo rispetto alla variabile body
anch’essa trasformata attraverso il logaritmo. Alla luce dei due grafici
ottenuti, quale modello di regressione di brain su body vi sembra più
appropriato? Si stimi e si valuti l’adeguatezza del modello proposto.

Esercizio 3
Nella libreria MASS di Venables e Ripley è incluso il data frame wtloss.
Esso riporta il peso in chilogrammi (colonna Weight) di un paziente
obeso rilevato in corrispondenza di 52 istanti temporali (colonna Days)
durante 8 mesi di un programma di riabilitazione. È di interesse stu-
diare l’andamento temporale del peso, ossia la dipendenza di Weight
da Days. A questo fine, si acceda al data frame e si analizzi il model-
lo di regressione lineare semplice della variabile Weight rispetto alla
variabile Days. Quale modifiche al precedente modello di regressione
vengono suggerite dall’analisi dei residui? Si proponga e si studi un
modello di regressione alternativo alla retta precedentemente stimata.
(Suggerimento: si consideri la possibilità di ricorrere ad una regressio-
ne polinomiale.) In base al nuovo modello si preveda il peso che si
sarebbe raggiunto al termine del trattamento qualora il programma di
riabilitazione fosse stato prolungato sino al giorno 256.

Esercizio 4
È stato messo a disposizione degli studenti il file fuel.txt che per
48 stati americani, specificati dalla prima colonna, riporta le seguenti
quantità:

TAX: tasse sul carburante per motori in centesimi di dollari


per gallone nell’anno 1972
INC: reddito pro-capite in dollari nell’anno 1972
ROAD: lunghezza in miglia delle strade principali nell’anno 1971
DLIC: frazione della popolazione con patente di guida nell’anno
1971
FUEL: consumo pro-capite di carburante per motori in galloni
nell’anno 1972

Si vuole studiare la dipendenza del consumo di carburante (FUEL) dal-


le restanti variabili, con particolare attenzione all’effetto del livello di
tassazione (TAX). Si importi il file in R e si conduca un’analisi descrit-
tiva delle variabili sia univariata che bivariata (per l’analisi bivariata

99
ci si avvalga anche della funzione pairs introdotta al paragrafo 5.4.1).
Partendo dal modello di regressione multipla che include tutte e 4 le
variabili esplicative, tramite una procedura all’indietro, si selezioni le
variabili con un effetto significativo su FUEL. Per il modello finale si
conduca un’analisi della bontà di adattamento ai dati e di verifica delle
ipotesi della regressione. Si preveda, inoltre, il valore di FUEL corri-
spondente a livelli di tassazione pari a 4.5 e 10.5, mentre le restanti
variabili esplicative sono fissate ai rispettivi valori medi.

100
Indice

1 Introduzione a R 1
1.1 Che cos’è R . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Iniziare e chiudere una sessione di R . . . . . . . . . . . . . . 1
1.3 Un pò di aritmetica, matematica e logica... . . . . . . . . . . . 2
1.4 Assegnazioni di valori . . . . . . . . . . . . . . . . . . . . . . . 3
1.5 Salvataggio dei dati . . . . . . . . . . . . . . . . . . . . . . . . 4
1.6 I vettori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.6.1 Creazione di un vettore . . . . . . . . . . . . . . . . . . 5
1.6.2 Manipolazione dei vettori . . . . . . . . . . . . . . . . 6
1.6.3 Estrazione degli elementi da un vettore . . . . . . . . . 8
1.7 Creazione e manipolazione di matrici . . . . . . . . . . . . . . 9
1.8 I data frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.9 Lettura e scrittura di un file . . . . . . . . . . . . . . . . . . . 15
1.10 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2 Statistica descrittiva 19
2.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 Tabelle di frequenza . . . . . . . . . . . . . . . . . . . . . . . 19
2.3 Indici di posizione e variabilità . . . . . . . . . . . . . . . . . 21
2.4 Grafici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.4.1 Grafici per variabili qualitative . . . . . . . . . . . . . 24
2.4.2 Grafici per variabili quantitative . . . . . . . . . . . . . 25
2.4.3 Diagrammi di dispersione . . . . . . . . . . . . . . . . 29
2.5 Misure di dipendenza tra due variabili quantitative . . . . . . 31
2.6 Salvataggio dei grafici . . . . . . . . . . . . . . . . . . . . . . . 33
2.7 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3 Probabilità 35
3.1 Distribuzioni di probabilità . . . . . . . . . . . . . . . . . . . 35
3.2 Simulazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.3 Legge dei grandi numeri e teorema del limite centrale . . . . . 39
3.4 Tecniche di campionamento . . . . . . . . . . . . . . . . . . . 41

101
3.5 Confronti con la distribuzione normale . . . . . . . . . . . . . 42
3.6 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

4 Statistica Inferenziale: stima puntuale, stima intervallare e


verifica di ipotesi 47
4.1 Stima puntuale . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.2 Verifica di ipotesi e stima intervallare . . . . . . . . . . . . . . 49
4.2.1 Media di una popolazione normale . . . . . . . . . . . 49
4.2.2 Confronto tra le medie di due popolazioni normali . . . 54
4.2.3 Analisi della varianza ad un fattore . . . . . . . . . . . 58
4.2.4 Test di indipendenza nelle tabelle a doppia entrata . . 63
4.3 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

5 Statistica Inferenziale: il modello di regressione lineare 69


5.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.1.1 Definizione di un modello di regressione . . . . . . . . . 69
5.1.2 Stima e verifica di ipotesi per un modello di regressione 70
5.1.3 Analisi dei residui . . . . . . . . . . . . . . . . . . . . . 71
5.2 Inferenza su un modello di regressione lineare in R . . . . . . 72
5.3 Esempi di regressione lineare semplice in R . . . . . . . . . . 72
5.3.1 Esempio 1: l’occupazione . . . . . . . . . . . . . . . . . 72
5.3.2 Esempio 2: le cucitrici e l’effetto dei punti influenti . . 78
5.3.3 Esempio 3: le miglia aeree e le trasformazioni . . . . . 82
5.4 Esempi di regressione lineare multipla in R . . . . . . . . . . 87
5.4.1 Esempio 1: la teoria di Modigliani . . . . . . . . . . . . 87
5.4.2 Esempio 2: le miglia aree e le trasformazioni (continua) 91
5.4.3 Esempio 3: i crash test e la regressione polinomiale . . 94
5.5 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

102

Potrebbero piacerti anche