Esercitazioni di programmazione in R del corso di "Laboratorio di

Transcript

Esercitazioni di programmazione in R del corso di "Laboratorio di
Laurea Magistrale in Biologia Sperimentale ed Applicata
Esercitazioni di programmazione in R del corso di
"Laboratorio di Statistica"
Davide Guido
Sara Sacco
Riccardo Beltrami
Unità di Statistica Medica e Genomica
Dipartimento di Scienze del Sistema Nervoso e del Comportamento
(Department of Brain and Behavioural Sciences)
Università degli Studi di Pavia
1
Autori:
Davide Guido
Laboratorio di Statistica Multivariata
Unità di Statistica Medica e Genomica
Dipartimento di Scienze del Sistema Nervoso e del Comportamento
Università degli Studi di Pavia
e–mail: [email protected]
Sara Sacco
Laboratorio di Epidemiologia Clinica e Programmazione Sanitaria
Unità di Statistica Medica e Genomica
Dipartimento di Scienze del Sistema Nervoso e del Comportamento
Università degli Studi di Pavia
e–mail: [email protected]
Riccardo Beltrami
Laboratorio di Statistica Genetica ed Epidemiologia Genetica
Unità di Statistica Medica e Genomica
Dipartimento di Scienze del Sistema Nervoso e del Comportamento
Università degli Studi di Pavia
e–mail: [email protected]
Software utilizzati:
- Microsoft Office Excel 2010 in ambiente Windows 7
- R (versione 2.15.2)
Sono gradite segnalazioni di eventuali refusi.
2
Indice
1.
Cenni di analisi dei dati con Excel - Esercizi (per non soffrire Pag.
troppo!)
1.1
1.2
Il Foglio Elettronico Excel
L’inserimento dei dati
“
“
6
7
1.2.1
1.2.2
1.2.3
Inserimento di numeri e testo
Riempimento automatico
Esempio pratico
“
“
“
7
7
8
1.3
Le formule
“
10
1.3.1
1.3.2
1.3.3
1.3.4
1.3.5
1.3.6
1.3.7
Inserire una formula in una cella
Formula semplice
Arrotondamento decimale
Separatore decimale e separatore delle migliaia
Copia / Incolla speciale… Valori
Formula complessa
Formula con costante bloccata
“
“
“
“
“
“
“
10
10
12
13
14
16
18
1.4
La formattazione
“
20
1.4.1
1.4.2
Formattare la larghezza delle colonne
Eliminare una colonna intera
“
“
20
21
1.5
L’ordinamento e il filtro dei dati
“
22
1.5.1
1.5.2
Ordinamento delle colonne dati
Selezione (filtro) di alcuni dati
“
“
22
23
1.6
Le funzioni
“
27
1.6.1
1.6.2
1.6.3
Premessa
Inserire una funzione
Copiare una funzione
“
“
“
27
28
29
1.7
Lo strumento “Analisi dati”
“
31
1.7.1
1.7.2
Installazione
Calcolo di misure di sintesi
“
“
31
33
1.8
1.9
Il grafico scatter plot e la linea di tendenza con R2
La distribuzione di frequenza
“
“
35
40
1.9.1
1.9.2
Tabella pivot
Grafico pivot
“
“
40
43
1.10
Il salvataggio per l’importazione in R
“
47
1.10.1
1.10.2
Formato .csv
Formato .txt
“
“
47
48
2.
Utili nozioni di programmazione in R
Pag.
49
2.1
2.2
2.3
2.4
2.5
Cos’è R e come utilizzarlo
Come installare R e le funzioni di aiuto
Gestione dei pacchetti
Nomi e assegnazioni in R
Operazioni elementari
“
“
“
“
“
49
50
52
53
54
2.5.1
2.5.2
Operatori aritmetici e relazionali
Alcune funzioni notevoli
“
“
54
54
Esercizi
“
55
Vettori in R
Alcune funzioni statistiche
“
“
56
58
3
2.6
2.7
6
“
“
Pag.
“
58
59
60
62
I comandi header, colnames(), $ e attach()
Cenni di riordino dei dati
“
“
64
65
Come creare nuove funzioni in R
Elementi di analisi esplorativa e nozioni elementari sulla gestione dei grafici
La ricodifica di variabili in R
“
“
“
67
69
81
Esercitazione 1
Esercizi di “Elementi di programmazione in R e statistica descrittiva
“
86
2.8
2.9
2.10
2.11
Il ciclo for
Matrici in R
I data.frame in R
Procedure di importazione ed esportazione dei dati
2.11.1
2.11.2
2.12
2.13
2.14
3.
Principi di inferenza statistica
3.1
3.2
3.3
3.4
3.5
Distribuzioni di campionamento (teoriche) e variabili casuali
Alcune variabili casuali notevoli
Stime e stimatori
Gli elementi e la filosofia dei test di significatività
Test di significatività parametrici e intervalli di confidenza
“
“
“
“
“
101
103
106
109
110
3.5.1
3.5.2
3.5.3
Sulla media di una variabile casuale normale con 2 noto (Test Z a un campione)
Sulla media di una variabile casuale normale con 2 ignoto (Test T a un campione)
Sulla differenza tra medie di due variabili casuali normali con 2 noti e uguali (Test Z per
due campioni indipendenti)
Sulla differenza tra medie di due variabili casuali normali con 2 ignoti ma uguali (Test T
per due campioni indipendenti)
Sulla differenza tra medie di due variabili casuali normali con 2 ignoti e diversi (Test T per
due campioni indipendenti)
Sulla differenza tra medie di due variabili casuali normali con 2 ignoti ma uguali (Test T
per due campioni appaiati)
Sul rapporto di varianze di due variabili casuali normali (Test F per due campioni
indipendenti)
“
“
110
122
“
122
“
123
“
123
“
124
“
125
3.6
Test di significatività da modello probabilistico non Normale
“
125
3.6.1
3.6.2
3.6.3
3.6.4
Su una proporzione (Test Z su proporzione)
Sulla differenza di due proporzioni (Test Z su differenza di proporzioni)
Test di indipendenza
Sull’uguaglianza di due variabili casuali (Test U di Mann-Whitney) attraverso le mediane
(X0.5)
Sulla normalità di una distribuzione (Test di Shapiro-Wilk)
“
“
“
125
126
128
“
“
129
130
Esercitazione 2
Test di significatività e intervalli di confidenza
“
131
Esercitazione 3
Analisi della varianza (ANOVA), regressione lineare e correlazione
“
146
3.5.4
3.5.5
3.5.6
3.5.7
3.6.5
Pag. 101
4
5
1. Cenni di analisi dei dati con Excel - Esercizi
(per non soffrire troppo!)
1.1 Il Foglio Elettronico Excel
Un foglio elettronico, o foglio di calcolo, è costituito da una tabella in cui è possibile inserire testo,
numeri e formule.
Per aprire il foglio elettronico Excel, cliccare su:
Pulsante Start  Tutti i programmi  Microsoft Office  Microsoft Excel 2010
A questo punto, sullo schermo si aprirà il foglio elettronico Excel: esso viene presentato in una
nuova cartella (Cartel1) con all’interno tre fogli di lavoro.
Barra di accesso rapido
Barra multifunzione
Barra della formula
Cella
Casella del nome
Colonna
Riga
Pulsanti di scorrimento
Fogli di lavoro
Come si vede, il foglio elettronico Excel è una griglia di rettangoli (celle), in cui le colonne sono
denominate con lettere alfabetiche maiuscole (A, B, C, etc.) e le righe sono indicate da numeri arabi
(1, 2, 3, etc.): ogni cella risulta quindi univocamente identificata dall’incrocio tra la lettera della
colonna e il numero della riga corrispondenti (p.es. cella B1, cella C10, etc.).
6
1.2. L’inserimento dei dati
1.2.1 Inserimento di numeri e testo
Per digitare i dati (numeri o testo) all'interno di una cella, bisogna procedere nel seguente modo:
1) posizionare il puntatore del mouse sulla cella in cui si vogliono inserire i dati,
2) cliccare con il tasto sinistro del mouse: in questo modo la cella viene evidenziata con un bordo
nero per indicare che è attiva, cioè pronta per l’inserimento dei dati,
3) digitare sulla tastiera i numeri o il testo che si intendono inserire nella cella,
4) premere INVIO: in questo modo, il dato digitato viene inserito nella cella desiderata e la cella
sottostante diventa automaticamente attiva.
1.2.2 Riempimento automatico
Quando una cella è attiva, in corrispondenza del suo angolo inferiore destro compare un piccolo
quadratino nero: posizionandovi sopra il puntatore del mouse, il quadratino assume la forma di
piccola croce nera.
Tenendo premuto il tasto sinistro del mouse sopra la croce nera e trascinando il mouse, è possibile
duplicare il contenuto della cella (p.es. una parola), incrementare una serie riconosciuta (p.es. i mesi
dell’anno) o duplicare la formula contenuta.
E’ possibile incrementare anche una serie numerica: in questo caso bisogna scrivere i primi due
numeri della serie, selezionare le celle (dal centro delle celle) ed infine trascinare il quadratino di
riempimento.
7
1.2.3 Esempio pratico
In un campione di 15 soggetti, sono stati raccolti i dati relativi alle seguenti variabili:
- Sesso (variabile qualitativa, con due possibili modalità: maschio oppure femmina),
- Colesterolemia Totale (variabile quantitativa continua, con modalità espresse in milligrammi
per decilitro -mg/dl-),
- Colesterolemia HDL (variabile quantitativa continua, con modalità espresse in mg/dl).
I dati rilevati su ogni soggetto sono i seguenti (vedi File “Campione”):
Soggetti
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sesso
Colesterolemia Totale (mg/dl)
Colesterolemia HDL (mg/dl)
femmina
femmina
femmina
femmina
femmina
femmina
femmina
maschio
maschio
maschio
femmina
femmina
maschio
femmina
femmina
166
184
151
236
169
202
177
215
174
214
151
204
166
182
224
79
56
58
60
67
50
71
72
37
57
48
68
59
66
62
Per inserire questi dati in un foglio elettronico Excel procediamo nel seguente modo:
1)
2)
3)
4)
lasciamo vuota la colonna A: ci servirà in seguito,
posizioniamo il puntatore del mouse sulla cella B1,
clicchiamo con il tasto sinistro del mouse,
stabiliamo un nome (label o etichetta) per la prima delle tre variabili raccolte, cioè la variabile
Sesso, e lo digitiamo (label scelta: sesso),
5) premiamo INVIO,
6) ripetiamo l’intera procedura (punti 2, 3, 4 e 5) per le variabili Colesterolemia Totale (label
scelta: coltot) e Colesterolemia HDL (label scelta: hdl), inserendo le rispettive labels nelle
celle C1 e D1,
7) posizioniamo il puntatore del mouse sulla cella B2,
8) clicchiamo con il tasto sinistro del mouse,
9) digitiamo la modalità (femmina, codifica: f) che la variabile Sesso assume nel primo soggetto
del campione (per i maschi usiamo la codifica m),
10) premiamo INVIO,
11) ripetiamo le operazioni indicate ai punti 9 e 10, fino ad inserire nella colonna B le modalità
assunte dalla variabile Sesso in tutti i 15 soggetti del campione (ogni riga corrisponderà ad un
soggetto),
12) ripetiamo l’intera procedura (punti 7, 8, 9, 10 e 11) per le variabili Colesterolemia Totale e
Colesterolemia HDL, inserendo le rispettive modalità nella colonna C (a partire dalla C2) e
nella colonna D (a partire dalla cella D2),
8
13) a questo punto, ci spostiamo nella colonna A e qui creiamo una nuova variabile (la variabile
Identificativo, con label ID) che assume i valori numerici da 1 a 15 e serve ad identificare in
maniera univoca ognuno dei 15 soggetti componenti il campione:
a. posizioniamo il puntatore del mouse sulla cella A1,
b. clicchiamo con il tasto sinistro del mouse,
c. digitiamo la label ID,
d. premiamo INVIO,
e. posizioniamo il puntatore del mouse sulla cella A2,
f. clicchiamo con il tasto sinistro del mouse,
g. digitiamo la cifra 1,
h. premiamo INVIO,
i. digitiamo la cifra 2,
j. premiamo INVIO,
k. posizioniamo il puntatore del mouse sulla cella A2,
l. premiamo il tasto sinistro del mouse e, senza rilasciarlo, trasciniamo il mouse verso il basso
fino a selezionare le celle A2 e A3 che vengono così evidenziate in azzurro,
m. rilasciamo il tasto sinistro del mouse,
n. posizioniamo il puntatore del mouse sopra il quadratino nero presente in corrispondenza
dell’angolo inferiore destro della cella A3: il quadratino assume così la forma di piccola
croce nera,
o. premiamo il tasto sinistro del mouse e, senza rilasciarlo, trasciniamo il mouse verso il basso:
in questo modo compare un bordo nero ombreggiato che si espande ad evidenziare le celle
sottostanti,
p. continuiamo a trascinare il mouse verso il basso finché il bordo nero ombreggiato evidenzia
tutte le celle della colonna A da A2 a A16 compresa,
q. rilasciamo il tasto sinistro del mouse e vedremo comparire la serie numerica 1-15 nelle celle
da A2 a A16,
r. clicchiamo con il tasto sinistro del mouse su una cella qualunque del foglio elettronico per
far scomparire la selezione.
Ecco che a questo punto tutti i nostri dati risultano inseriti su quattro colonne del foglio elettronico:
ciascuna colonna corrisponde a una variabile (da sinistra verso destra: Identificativo, Sesso,
Colesterolemia Totale e Colesterolemia HDL) e ciascuna riga corrisponde a un soggetto del
campione (dall’alto verso il basso da 1 a 15).
9
1.3 Le formule
1.3.1 Inserire una formula in una cella
Una formula è un insieme di operazioni su numeri, funzioni e contenuti numerici di celle e fornisce
in uscita un valore numerico.
Le funzioni più importanti sono senza dubbio gli operatori aritmetici (+ - * /) di somma (addizione),
differenza (sottrazione), prodotto (moltiplicazione) e quoziente (divisione) che permettono di
costruire formule per tutte le esigenze.
Una formula comincia sempre con il simbolo = (uguale) e può contenere costanti, riferimenti di
celle e di intervalli, funzioni. Ad esempio =A1*A3 è una formula che moltiplica il contenuto della
cella A1 per il contenuto della cella A3.
E’ possibile inserire anche formule più articolate: ad esempio =A1*A3/B4 è una formula che
moltiplica il contenuto della cella A1 per il contenuto della cella A3 e divide il tutto per il contenuto
della cella B4.
L’inserimento manuale di una formula avviene nel seguente modo:
1) selezionare la cella in cui si desidera immettere la formula,
2) digitare = (segno di uguale MAIUSC. + 0),
3) immettere il nome della prima cella (o selezionarla col click del mouse),
4) inserire l’operatore aritmetico (+ addizione; - sottrazione; * moltiplicazione; / divisione),
5) immettere il nome della seconda cella (o selezionarla col click del mouse),
6) premere INVIO.
1.3.2 Formula semplice
L’Indice di rischio cardiovascolare è un numero puro o adimensionale, cioè senza unità di misura
(valori normali: < 5 per i maschi e < 4,5 per le femmine), che risulta dal rapporto tra il valore di
Colesterolemia Totale e il valore di Colesterolemia HDL di ciascun soggetto:
Calcoliamo l’Indice di rischio cardiovascolare per ciascuno dei 15 soggetti di cui abbiamo inserito i
dati nell’esempio pratico 1.2.3:
1) posizioniamo il puntatore del mouse sulla cella E1,
2) clicchiamo con il tasto sinistro del mouse,
3) digitiamo coltot/hdl (è la label scelta per la nuova variabile Indice di rischio cardiovascolare,
variabile quantitativa continua con modalità adimensionali),
4) premiamo INVIO,
5) digitiamo il segno = (il segno comparirà ovviamente nella cella E2),
6) posizioniamo il puntatore del mouse sulla cella C2,
7) clicchiamo con il tasto sinistro del mouse (in questo modo la cella C2 assumerà un bordo blu e,
nella cella E2, dopo il segno = comparirà la scritta C2 nello stesso colore),
8) digitiamo il segno / (la scritta appare sempre nella cella E2),
10
9) posizioniamo il puntatore del mouse sulla cella D2,
10) clicchiamo con il tasto sinistro del mouse (in questo modo la cella D2 assumerà un bordo verde
e, nella cella E2, dopo il segno = comparirà la scritta D2 nello stesso colore),
11) premiamo INVIO: nella cella E2 compare il numero 2,101266,
12) posizioniamo il puntatore del mouse sulla cella E2 e clicchiamo con il tasto sinistro,
13) clicchiamo con il tasto destro del mouse,
14) con il tasto sinistro del mouse selezioniamo Copia,
15) posizioniamo il puntatore del mouse sulla cella E3,
16) premiamo il tasto sinistro del mouse e, senza rilasciarlo, trasciniamo il mouse verso il basso fino
a selezionare tutte le celle da E3 e E16, che vengono così evidenziate in azzurro,
17) rilasciamo il tasto sinistro del mouse,
18) posizioniamo il puntatore del mouse all’interno dell’area selezionata,
19) clicchiamo con il tasto destro del mouse,
20) con il tasto sinistro del mouse selezioniamo Opzioni Incolla… Incolla (N): nella colonna E
compaiono tutti i valori dell’Indice di rischio cardiovascolare calcolato per ciascun soggetto (le
cifre decimali seguono il numero intero dopo la virgola),
21) clicchiamo con il tasto sinistro del mouse su una cella qualunque del foglio elettronico per far
scomparire la selezione.
11
1.3.3 Arrotondamento decimale
Se vogliamo arrotondare i valori dell’Indice di rischio cardiovascolare alla seconda cifra
decimale, procediamo così:
1) posizioniamo il puntatore del mouse sulla cella E2,
2) premiamo il tasto sinistro del mouse e, senza rilasciarlo, trasciniamo il mouse verso il basso fino
a selezionare tutte le celle da E2 e E16, che vengono così evidenziate in azzurro,
3) rilasciamo il tasto sinistro del mouse,
4) posizioniamo il puntatore del mouse all’interno dell’area selezionata,
5) clicchiamo con il tasto destro del mouse,
6) con il tasto sinistro del mouse selezioniamo Formato celle...,
7) si apre una finestra di dialogo: con il tasto sinistro del mouse selezioniamo Numero, agendo sui
tasti freccia all’interno della finestra indichiamo quante Posizioni decimali vogliamo
considerare (nel nostro caso: 2) e infine selezioniamo OK,
8) tutti i valori dell’Indice di rischio cardiovascolare risulteranno approssimati alla seconda cifra
decimale: clicchiamo con il tasto sinistro del mouse su una cella qualunque del foglio
elettronico per far scomparire la selezione.
12
1.3.4 Separatore decimale e separatore delle migliaia
Excel utilizza di default la virgola (,) come separatore decimale e il punto (.) come separatore delle
migliaia.
A livello internazionale succede invece l’opposto: si usa il punto (.) come separatore decimale e la
virgola (,) come separatore delle migliaia.
Anche i più comuni programmi statistici (R compreso) utilizzano questo secondo sistema.
Per far sì che anche Excel utilizzi i separatori internazionali, si procede così:
1) nella barra multifunzione selezionare la scheda File e quindi cliccare su Opzioni,
2) si apre una finestra di dialogo: selezionare Impostazioni avanzate, togliere la spunta a Utilizza
separatori di sistema, quindi digitare i separatori desiderati: il punto (.) come Separatore
decimale e la virgola (,) come Separatore delle migliaia, infine premere OK,
13
3) ora Excel utilizza i separatori internazionali ed ecco come appare il file cui abbiamo lavorato
finora:
4) per tornare ai separatori utilizzati in precedenza, è sufficiente riaprire la finestra di cui al punto 2
e spuntare nuovamente la voce Utilizza separatori di sistema.
1.3.5 Copia / Incolla speciale… Valori
I comandi Copia / Incolla speciale… Valori servono a copiare i valori (senza le formule con le
quali sono stati calcolati) contenuti in alcune celle e a incollarli in altre celle.
Supponiamo di voler in copiare i valori contenuti nella colonna E del file cui abbiamo lavorato
finora (= i valori dell’Indice di rischio cardiovascolare) e di volerli poi incollare nel foglio di lavoro
Foglio 2.
Procediamo:
1) tenendo premuto il tasto sinistro e trascinando il mouse verso il basso, selezionare le celle dalla
E1 alla E16 compresa,
2) mantenendo il puntatore del mouse all’interno dell’area selezionata, cliccare con il tasto destro
del mouse e selezionare Copia,
3) passare al foglio di lavoro Foglio 2 (agire sui tasti in basso a sinistra nel foglio elettronico),
4) mantenendo il puntatore del mouse all’interno della cella A1 (che appare già attiva), cliccare
con il tasto destro e selezionare Opzioni Incolla… Incolla (N): nella colonna A appariranno 15
messaggi di errore (perché questo comando ha incollato le formule presenti nelle celle di origine
che qui però non trovano riferimenti numerici in altre celle e quindi non possono effettuare
alcun calcolo per restituire i valori),
14
5) posizionare nuovamente il puntatore del mouse nella cella A1 e cliccare con il tasto sinistro per
renderla attiva,
6) mantenendo il puntatore del mouse all’interno della cella A1, cliccare con il tasto destro e
selezionare Incolla speciale…,
7) si apre una finestra di dialogo: spuntare la voce Valori e premere OK,
8) questa volta appaiono i valori desiderati:
15
1.3.6 Formula complessa
La Formula di Friedewald permette di stimare il valore della Colesterolemia LDL (mg/dl) di un
soggetto a partire dai suoi valori di Colesterolemia Totale (mg/dl), di Colesterolemia HDL (mg/dl) e
di Trigliceridemia (mg/dl):
Consideriamo un campione di 15 soggetti, in cui sono stati raccolti i dati relativi alle seguenti
variabili (apri: File Excel “Dati”):
- Sesso (variabile qualitativa, con due possibili modalità: maschio oppure femmina),
- Età (variabile quantitativa discreta, con modalità espresse in anni),
- Glicemia (variabile quantitativa continua, con modalità espresse in mg/dl),
- Colesterolemia Totale (variabile quantitativa continua, con modalità espresse in mg/dl),
- Colesterolemia HDL (variabile quantitativa continua, con modalità espresse in mg/dl),
- Trigliceridemia (quantitativa continua, con modalità espresse in mg/dl).
Per calcolare il valore di Colesterolemia LDL per ciascun soggetto mediante la formula di
Friedewald, bisogna procedere così:
1) posizionare il puntatore del mouse sulla cella H1 e cliccare con il tasto sinistro per renderla
attiva,
2) digitare ldl (è la label scelta per la nuova variabile Colesterolemia LDL, variabile quantitativa
continua con modalità espresse in mg/dl),
3) premere INVIO,
4) digitare il segno = (il segno comparirà ovviamente nella cella H2),
5) posizionare il puntatore del mouse sulla cella E2 e cliccare con il tasto sinistro (in questo modo
la cella E2 assumerà un bordo blu e, nella cella H2, dopo il segno = comparirà la scritta E2 nello
stesso colore),
6) digitare il segno – e poi il segno ( (le scritte appaiono sempre nella cella H2),
16
7) posizionare il puntatore del mouse sulla cella F2 e cliccare con il tasto sinistro (in questo modo
la cella F2 assumerà un bordo verde e, nella cella H2, dopo i segni –( comparirà la scritta F2
nello stesso colore),
8) digitare il segno + e poi il segno ( (le scritte appaiono sempre nella cella H2),
9) posizionare il puntatore del mouse sulla cella G2 e cliccare con il tasto sinistro (in questo modo
la cella G2 assumerà un bordo viola e, nella cella H2, dopo i segni +( comparirà la scritta G2
nello stesso colore),
10) digitare il segno / e poi il numero 5 (le scritte appaiono sempre nella cella H2), quindi digitare
due parentesi tonde in chiusura )) ,
11) premere INVIO: nella cella H2 compare il numero 73.2,
12) posizionare il puntatore del mouse sulla cella H2 e cliccare con il tasto sinistro,
13) mantenendo il puntatore all’interno della cella H2, cliccare con il tasto destro del mouse e poi
con il tasto sinistro selezionare Copia,
14) posizionare il puntatore del mouse sulla cella H3,
15) premere il tasto sinistro del mouse e, senza rilasciarlo, trascinare il mouse verso il basso fino a
selezionare tutte le celle da H3 e H16 compresa, che vengono così evidenziate in azzurro,
16) rilasciare il tasto sinistro del mouse,
17) mantenendo il puntatore del mouse all’interno dell’area selezionata, cliccare con il tasto destro e
poi con il tasto sinistro selezionare Opzioni Incolla… Incolla (N): nella colonna H compaiono
tutti i valori della Colesterolemia LDL calcolata per ciascun soggetto con la Formula di
Friedewald (le cifre decimali seguono il numero intero dopo il punto),
18) cliccare con il tasto sinistro del mouse su una cella qualunque del foglio elettronico per far
scomparire la selezione.
17
1.3.7 Formula con costante bloccata
I valori assunti dalla glicemia, come quelli di altri parametri ematochimici, sono tradizionalmente
espressi in milligrammi per decilitro (mg/dl).
Il SI (Sistema Internazionale) di Unità di Misura invece esprime la glicemia in millimoli per litro
(mmol/l).
Il passaggio dai mg/dl alle mmol/l (o viceversa) avviene semplicemente dividendo (o
moltiplicando) il valore della glicemia per 18 (cioè per una costante):
Proviamo a convertire in mmol/l i valori di glicemia (espressi in mg/dl) relativi al campione di 15
soggetti su cui abbiamo lavorato con la formula di Friedewald:
1)
2)
3)
4)
5)
posizionare il puntatore del mouse sulla cella I1 e cliccare con il tasto sinistro,
digitare costante e premere INVIO,
digitare il numero 18 (che verrà a questo punto scritto nella cella I2) e premere INVIO,
posizionare il puntatore del mouse sulla cella J1 e cliccare con il tasto sinistro,
digitare glicemiaSI (è la label scelta per la nuova variabile Glicemia, variabile quantitativa
continua con modalità espresse in mmol/l) e premere INVIO,
6) digitare il segno = (il segno comparirà ovviamente nella cella J2),
7) posizionare il puntatore del mouse sulla cella D2 e cliccare con il tasto sinistro (in questo modo
la cella D2 assumerà un bordo blu e, nella cella J2, dopo il segno = comparirà la scritta D2 nello
stesso colore),
8) digitare in sequenza (senza spaziature) i segni / $ I $ 2 (le scritte appaiono sempre nella cella J2
e notiamo che la cella I2 assume un bordo verde. Il simbolo del dollaro $ serve a bloccare
colonna e riga.),
9) premere INVIO: nella cella J2 compare il numero 5.722222,
10) posizionare il puntatore del mouse sulla cella J2 e cliccare con il tasto sinistro,
11) mantenendo il puntatore del mouse all’interno della cella J2, cliccare con il tasto destro e poi
con il tasto sinistro selezionare Copia,
12) posizionare il puntatore del mouse sulla cella J3,
18
13) premere il tasto sinistro del mouse e, senza rilasciarlo, trascinare il mouse verso il basso fino a
selezionare tutte le celle da J3 e J16 compresa, che vengono così evidenziate in azzurro,
14) rilasciare il tasto sinistro del mouse,
15) mantenendo il puntatore del mouse all’interno dell’area selezionata, cliccare con il tasto destro
del mouse e poi con il tasto sinistro selezionare Opzioni Incolla… Incolla (N): nella colonna J
compaiono i valori di glicemia di ciascun soggetto espressi in mmol/l (le cifre decimali seguono
il numero intero dopo il punto),
16) cliccare con il tasto sinistro del mouse su una cella qualunque del foglio elettronico per far
scomparire la selezione.
19
1.4 La formattazione
1.4.1 Formattare la larghezza delle colonne
Per adattare le dimensioni delle colonne del foglio elettronico al loro contenuto, in modo che la
matrice dei dati risulti nel suo complesso meno larga, bisogna procedere così (continuiamo a
lavorare sempre sullo stesso file):
1) posizionare il puntatore del mouse in corrispondenza della lettera A che individua la prima
colonna del foglio elettronico,
2) premere il tasto sinistro del mouse e, senza rilasciarlo, trascinare il mouse verso destra fino a
selezionare tutte le colonne in cui sono presenti dati (nel nostro caso le colonne dalla A alla J):
le colonne selezionate verranno ombreggiate in azzurro,
3) rilasciare il tasto sinistro del mouse,
4) nella scheda Home della barra multifunzione, selezionare Formato e quindi Adatta larghezza
colonne,
5) cliccare con il tasto sinistro del mouse su una cella qualunque del foglio elettronico per far
scomparire la selezione: a questo punto la larghezza delle colonne del foglio elettronico sarà
adattata al loro contenuto.
20
1.4.2 Eliminare una colonna intera
Immaginiamo di avere un foglio elettronico in cui per sbaglio è stata lasciata una colonna vuota (la
colonna E).
Per eliminarla, si procede nel seguente modo:
1) posizionare il puntatore del mouse in corrispondenza della lettera E che individua la colonna
vuota da eliminare,
2) cliccare con il tasto sinistro del mouse e così evidenziare l’intera colonna E (che apparirà
ombreggiata in azzurro),
3) mantenendo il puntatore del mouse all’interno dell’area selezionata, cliccare con il tasto destro e
poi con il tasto sinistro selezionare Elimina,
4) cliccare con il tasto sinistro del mouse su una cella qualunque del foglio elettronico per far
scomparire la selezione: a questo punto la colonna vuota risulterà eliminata.
21
1.5 L’ordinamento e il filtro dei dati
1.5.1 Ordinamento delle colonne dati
Supponiamo di voler disporre in ordine di età crescente i soggetti del nostro campione (continuiamo
a lavorare sullo stesso file che abbiamo utilizzato finora), in modo che sul foglio elettronico essi
appaiano (con le relative misurazioni) ordinati dall’alto verso il basso dal più giovane al più
anziano.
Si procede così:
1) tenendo premuto il tasto sinistro e trascinando il mouse verso destra e verso il basso, selezionare
tutte le celle comprese nell’area del rettangolo avente per base le celle A2-J2 e per altezza le
celle A2-A16 (escludiamo quindi soltanto le celle contenenti le labels delle variabili),
2) nella scheda Dati della barra multifunzione, selezionare Ordina,
3) si apre una finestra di dialogo: nel primo menu a tendina a sinistra, selezionare età (negli altri
due menu a tendina compariranno automaticamente Valori e Dal più piccolo al più grande) e
premere OK,
22
4) i dati appaiono ordinati per età crescente, ma nella colonna glicemiaSI compaiono messaggi di
errore in quanto la formula in essa presente non trova più il riferimento per eseguire il calcolo:
digitiamo 18 nella cella A2, premiamo INVIO e i dati appariranno come segue,
5) è possibile ripetere il comando con opzioni di ordinamento sequenziali: questa procedura serve
a ordinare valori che in origine non sono in sequenza e permette applicazioni successive per la
selezione, l’eliminazione o l’elaborazione.
1.5.2 Selezione (filtro) di alcuni dati
Supponiamo di voler selezionare solo alcuni soggetti del nostro campione (continuiamo a lavorare
sullo stesso file che abbiamo utilizzato finora), p.es. solo le femmine, poi solo i maschi e infine solo
i soggetti che hanno un’età compresa tra i 30 e i 35 anni.
Si procede così:
1) tenendo premuto il tasto sinistro e trascinando il mouse verso destra e verso il basso, selezionare
tutte le celle comprese nell’area del rettangolo avente per base le celle A1-J1 e per altezza le
celle A1-A16 (cioè selezioniamo anche le celle contenenti le labels delle variabili),
2) nella scheda Dati della barra multifunzione, selezionare Filtro: a destra della label di ogni
variabile comparirà un triangolino,
23
3) cliccare sul triangolino posto alla destra della label sesso e, nel menu conseguentemente
apertosi, togliere la spunta vicino alla lettera m (maschio), quindi premere OK.
I dati appariranno come segue: accanto alla label sesso compare il simbolo di un piccolo imbuto
per indicare che i dati sono filtrati per sesso, nello specifico sono riportati soltanto i dati relativi
alle femmine componenti il nostro campione di 15 soggetti.
4) cliccare sull’imbuto a destra della label sesso e, nel menu conseguentemente apertosi, togliere la
spunta vicino alla lettera f (femmina) e metterla vicino alla lettera m, quindi premere OK
24
Ora appariranno soltanto i dati relativi ai maschi componenti il campione di 15 soggetti: se lo si
desidera, è possibile copiare questi valori, incollarli su un altro foglio di lavoro e quindi
eventualmente inserire formule e funzioni.
5) nella scheda Dati della barra multifunzione, selezionare nuovamente Filtro: in questo modo, il
filtro viene tolto e appaiono i dati relativi a tutti i soggetti,
6) ripetere le operazioni descritte ai punti 1 e 2,
7) cliccare sul triangolino posto alla destra della label età e, nel menu conseguentemente apertosi,
cliccare su Filtri per numeri e poi su Filtro personalizzato,
8) si apre una finestra di dialogo: nel menu a tendina in alto a sinistra selezionare è maggiore o
uguale a, nella casella in alto a destra digitare 30, quindi nel menu a tendina in basso a sinistra
selezionare è minore o uguale a, nella casella in basso a destra digitare 35 e infine premere
OK.
25
I dati appariranno come segue: accanto alla label età compare il simbolo di un piccolo imbuto
per indicare che i dati sono filtrati per età, nello specifico sono riportati soltanto i dati relativi ai
soggetti di età compresa tra i 30 e i 35 anni.
9) nella scheda Dati della barra multifunzione, selezionare nuovamente Filtro: in questo modo, il
filtro viene tolto e appaiono i dati relativi a tutti i soggetti.
26
1.6 Le funzioni
1.6.1 Premessa
In Excel sono presenti centinaia di formule, dalle più semplici alle più complesse, divise per
categorie.
Nella scheda Formule della barra multifunzione, è possibile accedere all’elenco di tutte le funzioni
dal pulsante
oppure scegliere direttamente la categoria interessata dai relativi pulsanti.
Per le funzioni principali indicate di seguito, è possibile utilizzare anche il pulsante  presente nella
scheda Home della barra multifunzione:
Funzione SOMMA
Somma tutti i numeri presenti in un intervallo di celle. P.es. =SOMMA(A1:A10) eseguirà la somma
automatica dei numeri presenti nell’intervallo dalla cella A1 alla cella A10.
Funzione MEDIA
Essa restituisce la media aritmetica degli argomenti. P.es. =MEDIA(A1:A10) eseguirà la media dei
numeri presenti nell’intervallo dalla cella A1 alla cella A10.
Funzione CONTA.NUMERI
Conta quanti valori numerici sono presenti in un intervallo di celle. P.es.
=CONTA.NUMERI(A1:A10) conta quanti numeri sono presenti nell’intervallo dalla cella A1 alla
cella A10.
Funzione MAX
Essa restituisce il valore più alto di una serie di celle. P.es. =MAX(A1:A10) visualizzerà il numero
più alto tra quelli presenti nell’intervallo dalla cella A1 alla cella A10.
Funzione MIN
Essa restituisce il valore più basso di una serie di celle. P.es. =MIN(A1:A10) visualizzerà il numero
più basso tra quelli presenti nell’intervallo dalla cella A1 alla cella A10.
27
1.6.2 Inserire una funzione
Proviamo ad inserire alcune funzioni nel file su cui abbiamo lavorato finora.
Procediamo così:
1) posizionare il puntatore del mouse in corrispondenza della prima cella libera al di sotto dei dati
inseriti nella colonna A (cella A17) e cliccare con il tasto sinistro per renderla attiva,
2) digitare sommatoria e premere INVIO,
3) digitare media e premere INVIO,
4) digitare deviazione standard e premere INVIO,
5) digitare mediana e premere INVIO,
6) le parole inserite eccedono la larghezza della colonna precedentemente adattata: ripetiamo
quindi le operazioni descritte nel paragrafo 1.4.1 “Formattare la larghezza delle colonne” in
modo da ottenere una larghezza ottimale,
7) posizionare il mouse in corrispondenza della cella B17 e cliccare con il tasto sinistro,
8) nella scheda Formule della barra multifunzione, selezionare Inserisci funzione,
9) si aprirà una finestra di dialogo: selezionare la categoria Tutte nel menu a tendina, nell’elenco
selezionare la funzione SOMMA e infine premere OK,
28
10) si aprirà un’altra finestra di dialogo: cliccare sul quadratino indicato dalla freccia nella figura
qui sotto (la finestra di dialogo diventerà più piccola),
11) selezionare, sul foglio elettronico, le celle alle quali si vuole applicare la funzione: nel nostro
caso, selezionare le celle da B2 a B16 inclusa,
12) cliccare nuovamente sul quadratino specificato al punto 10 (la finestra di dialogo tornerà alle
dimensioni originali),
13) premere OK: nella cella B17 appare il valore assunto dalla somma di tutti i dati numerici
contenuti nelle celle dalla B2 alla B16 inclusa (il valore è ovviamente zero, perché la colonna B
nel nostro caso non contiene dati numerici),
14) posizionare il mouse in corrispondenza della cella B18 e cliccare con il tasto sinistro,
15) ripetere la procedura descritta dal punto 8 al punto 13, selezionando però la funzione MEDIA e
facendo poi attenzione a selezionare sempre le celle dalla B2 alla B16,
16) posizionare il mouse in corrispondenza della cella B19 e cliccare con il tasto sinistro,
17) ripetere la procedura descritta dal punto 8 al punto 13, selezionando però la funzione DEV.ST e
facendo poi attenzione a selezionare sempre le celle dalla B2 alla B16,
18) posizionare il mouse in corrispondenza della cella B20 e cliccare con il tasto sinistro,
19) ripetere la procedura descritta dal punto 8 al punto 13, selezionando però la funzione
MEDIANA e facendo poi attenzione a selezionare sempre le celle dalla B2 alla B16
(compaiono messaggi di errore, in quanto queste funzioni non possono essere calcolate per la
variabile qualitativa Sesso).
1.6.3 Copiare una funzione
A questo punto, per inserire le medesime funzioni anche nelle altre colonne contenenti dati, si
procede così:
1) posizionare il puntatore del mouse in corrispondenza della cella contenente il risultato calcolato
dalla funzione SOMMA nella colonna B (cella B17) e cliccare con il tasto sinistro,
2) tenendo premuto il tasto sinistro e trascinando il mouse verso il basso, selezionare le celle dalla
B17 alla B20 compresa,
3) mantenendo il puntatore del mouse all’interno dell’area selezionata, cliccare con il tasto destro e
selezionare Copia,
4) tenendo premuto il tasto sinistro e trascinando il mouse dapprima verso il basso e poi verso
destra, selezionare tutte le celle comprese nell’area del rettangolo avente altezza corrispondente
alle celle C17-C20 e base corrispondente alle celle C20-J20,
29
5) mantenendo il puntatore del mouse all’interno dell’area selezionata, cliccare con il tasto destro e
selezionare Opzioni Incolla… Incolla (N): appariranno i valori calcolati dalle funzioni per tutte
le variabili e i soggetti del campione,
6) nelle colonne B e I compaiono messaggi di errore o valori insensati: è possibile cancellarli e
lasciare vuote le celle, in quanto non ha senso calcolare le funzioni descritte per la variabile
Sesso (variabile qualitativa) e per la costante di conversione delle unità di misura della
glicemia,
7) nella cella B17 compaiono i segni #: indicano che la larghezza della cella è insufficiente per
visualizzare il numero in essa contenuto, per cui ripetiamo ancora una volta la procedura per
adattare la larghezza delle colonne,
8) a questo punto, per meglio visualizzare e diversificare i valori delle funzioni, è possibile dare un
colore diverso alle celle nel seguente modo:
 tenendo premuto il tasto sinistro e trascinando il mouse dapprima verso il basso e poi verso
destra, selezionare tutte le celle comprese nell’area del rettangolo avente altezza
corrispondente alle celle A17-A20 e base corrispondente alle celle A20-J20,
 selezionare la scheda Home nella barra multifunzione,
 nel menu Carattere, scegliere un colore di riempimento (p.es. verde chiaro).
Ecco come appare ora il nostro insieme di dati (dataset):
30
1.7 Lo strumento “Analisi dati”
1.7.1 Installazione
Innanzitutto bisogna aggiungere lo strumento all’interno di Excel, in quanto non viene fornito di
base dal programma.
Per fare ciò, procediamo nel seguente modo:
1) nella scheda File della barra multifunzione, selezionare Opzioni,
2) si apre una finestra di dialogo: selezionare Componenti aggiuntivi, poi Strumenti di analisi VBA e quindi premere Vai,
31
3) si apre un’ulteriore finestra di dialogo, in cui è necessario selezionare Strumenti di analisi e poi
OK,
4) si apre un’ultima finestra di dialogo che richiede una conferma prima di procedere
all’installazione: selezioniamo OK e si avvierà l’installazione,
5) terminata l’installazione, il menu della barra multifunzione apparirà aggiornato: nella scheda
Dati, comparirà infatti la nuova funzione Analisi dati.
32
1.7.2 Calcolo di misure di sintesi
Per calcolare alcune misure di sintesi sul nostro dataset (continuiamo a lavorare sullo stesso file che
abbiamo usato finora), si procede così:
1) sulla barra multifunzione selezionare la scheda Dati e quindi cliccare su Analisi dati,
2) si apre una finestra di dialogo: selezionare Statistica descrittiva e quindi OK,
3) si apre un’altra finestra di dialogo: cliccare sul quadratino indicato dalla freccia nella figura qui
sotto (la finestra di dialogo diventerà più piccola),
4) selezionare, sul foglio elettronico, le celle corrispondenti alla variabile per la quale si vogliono
calcolare le misure di sintesi: p.es., se scegliamo la variabile Età (colonna C), selezioniamo le
celle da C1 a C16 inclusa,
5) cliccare nuovamente sul quadratino specificato al punto 3 (la finestra di dialogo tornerà alle
dimensioni originali e il campo Intervallo di input riporterà l’indicazione delle celle che
abbiamo selezionato),
6) spuntare le voci Etichette nella prima riga (perché, tra le celle selezionate al punto precedente,
è presente anche la cella C1 che contiene la label della variabile Età) e Riepilogo statistiche,
selezionare Nuovo foglio di lavoro e quindi cliccare su OK,
33
7) si apre un nuovo foglio di lavoro (Foglio 4), su cui possiamo applicare la procedura per adattare
la larghezza delle colonne al loro contenuto: vedremo quindi riportati i valori delle statistiche
descrittive relative alla variabile Età, che possiamo confrontare con quelli ottenuti
precedentemente con l’impostazione manuale delle funzioni.
34
1.8 Il grafico scatter plot e la linea di tendenza con R2
Per disegnare un grafico scatter plot e una linea di tendenza con R2, procedere come segue
(continuiamo a lavorare sullo stesso file che abbiamo usato finora):
1) tornare al foglio di lavoro precedente (Foglio 1),
2) selezionare le celle contenenti i valori delle variabili Età e Glicemia (comprese le celle
contenenti le rispettive labels, ma escluse le celle con i valori delle statistiche descrittive),
3) all’interno dell’area selezionata, cliccare con il tasto destro del mouse e selezionare Copia,
4) tornare al foglio di lavoro Foglio 4,
5) posizionare il puntatore del mouse in corrispondenza della cella D1 e cliccare con il tasto
sinistro per renderla attiva,
6) mantenendo il puntatore del mouse all’interno della cella D1, cliccare con il tasto destro e
selezionare Opzioni Incolla… Incolla (N),
7) assicurarsi che le celle contenenti le labels e i valori delle due variabili Età e Glicemia siano
selezionate (se non lo sono, selezionarle),
8) nella barra multifunzione, selezionare la scheda Inserisci,
9) all’interno del menu Grafici, cliccare su Grafico a dispersione e quindi, nel menu a tendina
apertosi, cliccare sulla prima figura in alto a sinistra (Dispersione con solo indicatori),
10) nel Foglio 4 apparirà ora un grafico che illustra come, nel nostro campione di 15 soggetti, la
Glicemia (riportata sull’asse y) varia in funzione dell’Età (riportata sull’asse x):
35
11) occorre però apportare alcune migliorie al suddetto grafico:
 posizionare il puntatore del mouse in corrispondenza del contorno del grafico (il puntatore
assume la forma di quattro piccole frecce ortogonali tra loro),
 tenendo premuto il tasto sinistro e trascinando il mouse, spostare il grafico in modo che non
copra le colonne contenenti dati,
 cliccare con il tasto sinistro del mouse all’interno della casella di testo posizionata al disopra
del grafico e contenente la scritta glicemia (è il titolo del grafico scelto automaticamente da
Excel): cancellare il testo presente e digitare La Glicemia in funzione dell’Età,
 posizionare il puntatore del mouse in corrispondenza di uno qualsiasi dei valori riportati
sull’asse x del grafico, cliccare con il tasto destro e selezionare Formato asse,
 si apre una finestra di dialogo mediante la quale è possibile stabilire il valore minimo e il
valore massimo da rappresentare sull’asse x del grafico: visto che la variabile Età varia da
un minimo di 28 anni a un massimo di 53 anni, spuntiamo la voce Fissa in corrispondenza
di Valore minimo e digitiamo 25 nel rettangolo bianco immediatamente a destra, poi
spuntiamo la voce Fissa in corrispondenza di Valore massimo e digitiamo 55 nel rettangolo
bianco immediatamente a destra, infine clicchiamo su Chiudi,
36
 ripetere l’operazione per l’asse y, fissando 65 come Valore minimo e 105 come Valore
massimo (poiché la variabile Glicemia varia da un minimo di 70 mg/dl a un massimo di 103
mg/dl),
 nel menu Strumenti grafico (che compare solo quando il grafico è selezionato), selezionare
la scheda Layout: nel menu Etichette, cliccare su Titoli degli assi, poi su Titolo asse
orizzontale principale e infine su Titolo sotto l’asse,
 sotto l’asse x del grafico, compare una casella di testo con la scritta Titolo asse: cliccarvi
all’interno con il tasto sinistro del mouse, cancellare il testo presente e digitare Età (anni),
 ripetere la procedura scegliendo Titolo asse verticale principale, poi Titolo ruotato e
quindi digitando Glicemia (mg/dl),
 a questo punto, il nostro grafico appare come segue:
37
12) nel menu Strumenti grafico (che compare solo quando il grafico è selezionato), selezionare la
scheda Layout: nel menu Analisi, cliccare su Linea di tendenza e poi su Altre opzioni linea
di tendenza,
13) si apre una finestra di dialogo: selezionare Lineare, spuntare Visualizza l’equazione sul
grafico e Visualizza il valore R al quadrato sul grafico, quindi cliccare su Chiudi,
14) sul grafico, compare una casella di testo contenente l’equazione e il valore di R al quadrato: se
si sovrappone ai dati, spostarla vicino alla legenda.
38
A questo punto il grafico appare come segue:
39
1.9 La distribuzione di frequenza
Una distribuzione di frequenza rappresenta, mediante una tabella o un grafico, il numero di soggetti
(frequenza assoluta) sui quali viene rilevata ciascuna modalità di una variabile.
1.9.1 Tabella pivot
Per costruire la distribuzione di frequenza della variabile Età nel nostro campione di 15 soggetti
tramite una tabella pivot, procedere nel seguente modo (continuare ad utilizzare il file su cui
abbiamo lavorato finora):
1) portarsi nel foglio di lavoro Foglio 1,
2) sulla barra multifunzione selezionare la scheda Inserisci, quindi cliccare sulla metà inferiore del
pulsante Tabella pivot e selezionare Tabella pivot,
3) si apre una finestra di dialogo: cliccare sul quadratino indicato dalla freccia nella figura qui sotto
(la finestra di dialogo diventerà più piccola),
4) selezionare, sul foglio elettronico, le celle (label + valori) corrispondenti alla variabile di cui si
vuole costruire la distribuzione di frequenza: nel nostro caso, selezionare le celle da C1 a C16
inclusa,
40
5) cliccare nuovamente sul quadratino specificato al punto 3 (la finestra di dialogo tornerà alle
dimensioni originali e, vicino alla dicitura Tabella/Intervallo, riporterà l’indicazione delle celle
appena selezionate),
6) a questo punto spuntare la voce Nuovo foglio di lavoro e premere OK,
7) si apre un nuovo foglio di lavoro (Foglio 5), che riporta nella parte destra l’Elenco campi tabella
pivot e nella parte sinistra un’anteprima della tabella pivot da costruire:
 nell’Elenco campi tabella pivot, sotto la dicitura Selezionare i campi da aggiungere al
rapporto, cliccare con il tasto sinistro del mouse sulla variabile età: tenendo premuto il tasto
sinistro e trascinando il mouse verso il basso, “portare” la variabile età nel riquadro
Etichette di riga e rilasciare il tasto sinistro del mouse,
 ripetere la medesima operazione, trascinando la variabile età nel riquadro Valori,
 nella parte sinistra del foglio di lavoro, si crea sotto i nostri occhi una tabella pivot, che però
non è quella che ci interessa: Excel infatti utilizza di default la funzione somma per
riepilogare i dati e questa funzione non è adatta per costruire la distribuzione di frequenza
della variabile Età (variabile quantitativa continua),
41
8) per ottenere la distribuzione di frequenza della variabile Età, nella parte inferiore destra del
foglio di lavoro cliccare sulla freccia immediatamente a destra della dicitura Somma di età e
quindi selezionare Impostazioni campo valore,
9) si apre una finestra di dialogo: selezionare Conteggio e quindi premere OK,
42
10) la tabella pivot cambia e diventa la seguente (cioè la distribuzione di frequenza della variabile
Età nel nostro campione di 15 soggetti: nella colonna sinistra sono presentate le modalità
assunte dalla variabile Età nel nostro campione e nella colonna destra è specificato il numero di
soggetti che presenta quella modalità):
1.9.2 Grafico pivot
Per visualizzare la distribuzione di frequenza della variabile Età nel nostro campione di 15 soggetti
tramite un grafico pivot, procedere nel seguente modo (continuare ad utilizzare il file su cui
abbiamo lavorato finora):
1) portarsi nel foglio di lavoro Foglio 1,
2) sulla barra multifunzione selezionare la scheda Inserisci, quindi cliccare sulla metà inferiore del
pulsante Tabella pivot e selezionare Grafico pivot,
43
3) si apre una finestra di dialogo: cliccare sul quadratino indicato dalla freccia nella figura qui sotto
(la finestra di dialogo diventerà più piccola),
4) selezionare, sul foglio elettronico, le celle (label + valori) corrispondenti alla variabile di cui si
vuole costruire la distribuzione di frequenza: nel nostro caso, selezionare le celle da C1 a C16
inclusa,
5) cliccare nuovamente sul quadratino specificato al punto 3 (la finestra di dialogo tornerà alle
dimensioni originali e, vicino alla dicitura Tabella/Intervallo, riporterà l’indicazione delle celle
appena selezionate),
6) a questo punto spuntare la voce Nuovo foglio di lavoro e premere OK,
7) si apre un nuovo foglio di lavoro (Foglio 6), che riporta nella parte destra l’Elenco campi tabella
pivot e nella parte sinistra un’anteprima della tabella pivot e del grafico pivot da costruire,
44
8) ripetere le medesime operazioni descritte ai punti 7 (il riquadro Etichette di riga qui si chiama
Campi asse (categorie)), 8 e 9 della procedura per costruire la distribuzione di frequenza della
variabile Età tramite una tabella pivot: questo è il risultato (sull’asse x sono presentate le
modalità assunte dalla variabile Età nel nostro campione e sull’asse y è specificato il numero di
soggetti che presenta quella modalità),
9) se lo desideriamo, possiamo ovviamente cambiare il titolo del grafico, stabilire i titoli degli assi
e fissare il limite massimo (lo poniamo a 2, visto che non ci sono valori più alti) e l’unità
principale dell’asse y (la poniamo a 1, perché non ha senso considerare le mezze unità in quanto
si tratta di persone).
45
Ecco il risultato finale.
46
1.10 Il salvataggio per l’importazione in R
Per poter essere importato e quindi letto dal software R, un foglio elettronico Excel deve essere
salvato in formato .csv oppure in formato .txt.
1.10.1 Formato .csv
Per salvare un foglio elettronico Excel in formato .csv, procedere nel seguente modo:
1) nella scheda File della barra multifunzione, cliccare su Salva con nome,
2) si apre una finestra di dialogo: nel campo Nome file, digitare il nome che si vuole dare al file
(nel nostro caso: Dati) e, nel menu a tendina del campo Salva come, selezionare CSV
(delimitato dal separatore di elenco),
47
3) scegliere la directory in cui si vuole salvare il file e cliccare su Salva,
4) nelle due finestre di dialogo che si aprono successivamente, cliccare OK e Sì.
1.10.2 Formato .txt
Per salvare un foglio elettronico Excel in formato .txt, procedere come per il salvataggio in formato
.csv: l’unica differenza è che, nella finestra di dialogo descritta al punto 2, nel menu a tendina del
campo Salva come, bisogna selezionare Testo (con valori delimitati da tabulazioni).
48
2. Utili nozioni di programmazione in R
2.1 Cos'è R e come utilizzarlo
R è un software (emulatore FREE di Splus) adatto alla manipolazione di dati, al calcolo e alla
visualizzazione grafica; è distribuito gratuitamente in internet all’indirizzo www.r-project.org dove
è anche possibile trovare ogni tipo di supporto per l’utilizzo e lo sviluppo. E' un linguaggio
orientato alla programmazione ad oggetti: ogni variabile in R è detta oggetto ed è associata ad una
determinata classe che ne definisce le proprietà.
Per avviare il programma R è sufficiente fare doppio click sull’icona corrispondente o avviare il
software dal menu di windows cliccando su “Programmi” (come un qualsiasi altro programma).
Lanciando il software appare la commandwindow (o R–console) con un prompt>. Ci sono diversi
modi per interagire con R: uno è quello di eseguire le operazioni direttamente dalla R–console
digitando, dopo il prompt, un comando seguito dal tasto “Invio”.
Ad un primo approccio R potrebbe sembrare una semplice CALCOLATRICE....
7+4
...ma come vedremo più avanti non è solo ciò, anzi...
In alternativa all’uso diretto della R–console si possono usare gli script: dal menu “File”,
scegliendo la voce “Nuovo script”, verrà attivata una nuova finestra con l’aspetto di un file di testo
che è possibile salvare e richiamare in una nuova sessione. Gli script hanno un’estensione .R e
possono essere aperti da R stesso oppure come un normale documento di testo.
Esempio
creo un nuovo file script: menu “File” - “Nuovo script”
salvo il file sul desktop con nome 'es1':
1) menu “File” - "salva con nome" - 'es1'
oppure
2) usare l’icona (floppy) - 'es1'
Per eseguire i comandi riportati nello script è sufficiente posizionare il cursore sulla linea di
interesse e scegliere la voce “Esegui linea o selezione” dal menu “Modifica”, oppure, in alternativa,
usando il tasto F5.
7+4# dopo aver digitato l’operazione premere il tasto F5
49
Quando si vuole uscire dal programma, R chiede se si desidera salvare la R-console (.Rdata) su cui
si è lavorato. In caso di risposta affermativa, questa memorizzerà tutti gli oggetti (espressioni,
numeri, formule) usati nella sessione di lavoro senza output; inoltre, contestualmente alla R-console
(o workspace), verrà salvato anche un file ascii (.Rhistory) che immagazzinerà tutti i comandi
digitati nel prompt. Questa operazione consentirà, al riavvio seguente di R, in maniera istantanea, di
ricaricare il precedente spazio di lavoro (file .RData) e con esso la storia dei comandi associati (file
.RHistory).
Il file .RHistory può risultare molto utile per richiamare, con i tasti "freccia su" e "freccia giù", tutti
i comandi digitati in una precedente sessione di lavoro. Uscendo da R, quindi, potrebbe essere utile
salvare workspace e history con i nomi che si desiderano. Una volta effettuata tale operazione,
difatti, a una successiva apertura del programma, selezionando la voce “Carica area di lavoro” dal
menu “File” e scegliendo i file .RData e .RHistory opportuni, sarà possibile specificare il
workspace su cui si desidera operare.
Se non diversamente specificato, R usa la directory di lavoro corrente per salvare automaticamente i
dati. Spesso però è opportuno specificare la propria directory di lavoro selezionando la voce
“Cambia directory” dal menu “File” e indicando la destinazione opportuna; tale operazione si può
anche effettuare digitando i comandi getwd() e setwd():
Per conoscere la directory di lavoro corrente è necessario usare il comando getwd():
getwd()
Per cambiarla usare il comando setwd(percorso) (alternativo del “Cambia directory”)
setwd("C:\\nome directory")
Ogni qualvolta si digita un comando contenente una path("C:\PROVA\...") R richiede di
raddoppiare lo slash oppure di cambiarne l'inclinazione (tasto maiuscolo + tasto "7")
2.2 Come installare R e le funzioni di aiuto
www.R-project.org
1. Download R→ "scegliere lo stato e il sito da cui fare il download"
2. Download and install R - Windows (95 and later)→base
3. Previous releases → R-2.15.2-win.exe
1.
→
→
50
2.
→
3.
→
→
Per scaricare il manuale - Documentation→Manuals
Sul sito www.R-project.org sono disponibili svariate guide di introduzione ad R ed è inoltre
possibile consultare i suggerimenti e i consigli presenti nelle FAQ (FrequentAskedQuestions)
mentre si sta lavorando. L'istruzione per accedervi è la seguente:
help.start()
da cui apparirà una pagina web off–line attraverso la quale si accede ai manuali e ad informazioni
generali. Inoltre un altro modo semplice per chiedere informazioni consiste nell’anteporre un punto
interrogativo al comando di cui si desidera avere maggiori informazioni:
51
?q
help.search("q")
Infine per ricercare informazioni su precisi argomenti, in R è implementato un motore di ricerca a cui si può
accedere selezionando “search.r-project.org” dal menù “Aiuto” oppure mediante la R-console digitando il
comando RSiteSearch("") (inserendo tra virgolette il nome dell’argomento di cui si vuole
richiedere informazioni). Tale procedura restituirà una serie di link informativi dei comandi e dei
pacchetti che gestiscono la query ricercata.
2.3 Gestione dei pacchetti
Il programma R è arricchito da una serie di pacchetti aggiuntivi che ne aumentano notevolmente le
potenzialità (Cfr. http://rm.mirror.garr.it/mirrors/CRAN/ → Packages).
Sono tre le tipologie di pacchetti utilizzabili:
1) pacchetti già installati e caricati il cui elenco si ottiene con il comando (.packages());
2) pacchetti già installati ma non ancora caricati: si tratta di pacchetti non immediatamente
utilizzabili che è necessario caricare con il comando library(nome pacchetto);
library(MASS) # caricamento del pacchetto MASS
3) pacchetti reperibili in rete. I sistemi di installazione di tali pacchetti sono molteplici: se si dispone
già del pacchetto desiderato (reperito precedentemente dal web) è sufficiente scegliere dal menu
“Pacchetti” la voce “Carica pacchetto”; se invece non si dispone del pacchetto e quindi lo si vuole
scaricare online, dal menu “Pacchetti” si scelga “Installa pacchetti” e, dopo aver specificato il
server distributore del programma a cui si vuole accedere, si selezioni il pacchetto da installare dalla
lista presentata. E’ inoltre possibile visualizzare la lista dei pacchetti già installati digitando il
comando library(). E’ possibile anche richiedere informazioni aggiuntive sui singoli pacchetti
installati (relativamente alla directory in cui sono collocati sul pc, alle versioni, alle dipendenze che
hanno con altri pacchetti ecc.) digitando installed.packages().
Per richiedere informazioni (anche a livello esplorativo) sui comandi dei pacchetti già installati una
funzione utile è help.start()1. Questa reindirizzerà alla home-page dell’help di R da cui sarà
possibile, cliccando su Packages, accedere alla lista di pacchetti caricati sul proprio PC. A quel
1
Alternativamente selezionare “Guida html” dal menù “Aiuto”
52
punto sarà sufficiente cliccare sul pacchetto desiderato per avere informazioni sui comandi che esso
gestisce.
2.4 Nomi e assegnazioni in R
I nomi in R possono essere lettere, cifre o punti. Non sono però ammessi nomi che iniziano con una
cifra o che iniziano con un punto seguito da una cifra.
8c<-3
.4<-2
R è case-sensitive ovvero distingue tra minuscole e maiuscole. Per creare un oggetto è necessario
utilizzare il comando<- o=(oppure anche->) prestando attenzione, nel momento in cui si decide di
crearlo, ad eventuali oggetti preesistenti che possiedono lo stesso nome (questi ultimi verranno
infatti sovrascritti e quindi cancellati). Inoltre per evitare di creare oggetti con nomi già usati dal
default dell’ambiente R, ad esempio q, si suggerisce di consultare l’help. Nei casi di incertezza su
una possibile assegnazione si provi a digitare nella R–console il nome che si desidera attribuire alla
variabile, controllando che non si tratti di un carattere riservato.
x<-3
x
y=2
y
45->z
z
Il comando ls() permette di conoscere cosa è contenuto nel workspace, ovvero gli oggetti presenti
nella memoria di lavoro2. Per rimuovere un oggetto si può usare il comando rm() mentre per
cancellare tutte le variabili esistenti nell’area di lavoro è necessario usare il comando:
rm(list=ls()).
ls()
In R l’uso del carattere # all’inizio di una riga di programma serve a introdurre un commento: si
tratta di una riga di codice che verrà ignorata durante l’esecuzione. I commenti permetteranno di
capire il flusso logico del codice agli utilizzatori e, a chi lo ha scritto, di ricordare immediatamente
il perché di determinate istruzioni. E’ utile precisare inoltre che in R non è consentito il commento
su più linee ovvero viene considerato commento solo la parte della riga di codice che segue il
simbolo #.
#questo è un commento
2
Un comando analogo è objects()
53
2.5 Operazioni elementari
2.5.1 Operatori aritmetici e relazionali
+
*
/
^
(addizione)
(sottrazione)
(moltiplicazione)
(divisione)
(elevamento a potenza)
7 + 3 * 6
x1 <- 7 + 3 * 6
x1
5^2
y1 <- 5^2 ; y1
#il “punto e virgola” permette di scrivere più istruzioni sulla stessa
riga
2.5.2 Alcune funzioni notevoli
R dispone al suo interno di numerose funzioni per ciascuna delle quali è presente un file di aiuto a
cui si può accedere digitando dal prompt "?nomefunzione" oppure "help(nomefunzione)".
Quest’ultimo chiarisce tutti gli argomenti richiesti dalla funzione, il loro nome, il loro ordine, quelli
necessari e quelli opzionali (ovvero quelli per cui un valore di default è già impostato).
?sum
Sotto è presentato un elenco non esaustivo (con esempi) delle funzioni matematiche più utilizzate:
sqrt(), sum(), prod(),min(), max(), log(), log10(), exp(),abs(),
sign(), round().
sum(3,4) #somma
prod(3,4) #prodotto
sqrt(81) #radice quadrata "sqrt"
z1 <- sqrt(81); z1 #assegnazione di radice quadrata
log(1) #logaritmo "log"
z2 <- log(5); z2
z3 <- exp(2); z3 #esponenziale
exp(1) #numero di Eulero
abs(-2) #valore assoluto
54
round(1/3,3) #arrotondamento
log(exp(1)) #esempio di funzioni concatenate
pi #"pi" in R è una costante predefinita corrispondente al numero π
(3.141593)
Esercizi
Esercizio 1
Calcolare l’area di un cerchio di raggio (r) = 3 cm. (Area di un cerchio = r2)
Soluzione:
pi*3^2
[1] 28.27433 # Area del cerchio = 28.27433 cm2
Esercizio 2
Risolvere le seguenti espressioni algebriche:
Soluzione:
1+2/7)*(-2/3)^2+(2-1/2)^3/(-3/2)-3/4*(-4/7)
[1] -1.25 # Risultato: -1.25
Esercizio 3
Soluzione:
(2*sqrt(15)-6)/(sqrt(3)-sqrt(2)-sqrt(5))
[1] -0.9101964 # Risultato: -0.9101964
Esercizio 4
Soluzione:
log(2*4)-log(2*4-1)-3*log(2)+log(7)
[1] 0 # Risultato: 0
55
2.6 Vettori in R
In R gli oggetti appartengono a classi. Le classi principali sono cinque:
1) vettori;
2) matrici;
3) data.frame;
4) array;
5) liste.
In questa dispensa saranno brevemente presentate solo le prime tre. Due comandi utili a interrogare
R per sapere la classe e la struttura di un qualunque oggetto sono class(nome oggetto) e
str(nome oggetto).
Un vettore è una collezione unidimensionale di elementi alfanumerici.
In R un numero viene interpretato come un vettore di dimensione 1×1.
La funzione più comune per creare un vettore è c() (che sta per “concatena”).
Per individuarne gli elementi è necessario specificare il nome del vettore seguito da un indice (di
posizione) delimitato da parentesi quadre.
Di seguito alcuni esempi di operazioni con vettori:
Vett<-c(-3,8,6); Vett # specificazione di un vettore
Vett[1] # estrae l’elemento in posizione 1
Vett[-1] # elimina dal vettore l’elemento in posizione 1
#(l'eliminazione non viene però memorizzata)
Vett
Vett[1:2] # estrae gli elementi dalla posizione 1 alla 2
Vett[c(1,3)] # estrae gli elementi in posizione 1 e 3
In generale le operazioni sui vettori devono essere inserite in un comando di assegnamento per
poter essere memorizzate.
Alcune fra le funzioni più utilizzate che vengono applicate ai vettori sono which(), sort() e
length(). La funzione which()richiede come argomento un vettore di tipo logico. La funzione
sort() ha il compito di ordinare gli elementi del vettore, mentre la funzione length()
restituisce la dimensione del vettore.
Di seguito alcuni esempi:
length(Vett)
max(Vett)
# restituisce la lunghezza del vettore
# restituisce il massimo
min(Vett) # restituisce il minimo
56
Vett[which(Vett>0)]
condizione
# estrae solo gli elementi che soddisfano la
which.min(Vett) # restituisce la posizione del minimo
which.max(Vett) # restituisce la posizione del massimo
sort(Vett)
# ordina gli elementi del vettore
length(Vett)
# restituisce la dimensione del vettore
Un operatore molto utile quando si opera con vettori e che serve per generare successioni di valori
equidistanti è la funzione seq(a,b,by=i) (by=1 è l’opzione di default). Alcuni esempi:
seq(1,10,by=2)
seq(1,5,by=1)
seq(1,21,by=2)
seq(0, 1, length=11)
L'opzione length stabilisce, anziché il passo, il numero di elementi che deve contenere la
sequenza (si noti comunque che stabilendo a priori il numero degli elementi, si definisce
indirettamente il passo della sequenza).
Un'altra funzione, rep(), è altrettanto utile per generare sequenze regolari. Ecco 2 esempi:
rep(1,6) # ripete il valore 1 per 6 volte
Concatenata alla funzione seq():
rep(seq(2,10,by=2),2) # ripete la sequenza (2 4 6 8 10) per 2 volte
Per chiarire:
c(1,6)
c(3,2)
rep(c(1,6),c(3,2)) #l'1 viene replicato 3 volte e il 6 per 2 volte
rep(c(1,6),each=3)
#una variante del comando appena mostrato può essere l'opzione "each"
Da notare che per queste ultime due funzioni vi è una corrispondenza di posizione vettoriale di 1
elemento a 1 elemento.
Con i vettori è possibile effettuare anche operazioni matematiche (ammissibili). Ad esempio:
Vett+3# ad ogni elemento di Vett viene aggiunto 3
Vett*6# ogni elemento di Vett viene moltiplicato per 6
57
Vett+c(1,1)# operazione non ammissibile! (non rispondenza tra le
dimensioni)
2.7 Alcune funzioni statistiche
Esistono anche svariate funzioni statistiche che possono essere applicate a vettori:
mean(c(1,2,3,4,5,6,7,8,9,10)) #media
Un vettore di numeri interi consecutivi può essere inserito anche con l’operatore “:” tra gli estremi
della successione.
1:10
mean(1:10)
median(1:10) #mediana
var(1:10) #varianza (campionaria)
sd(1:10) #deviazione standard
table(1:10) #distribuzione delle frequenze assolute
table(1:10)/length(1:10) #distribuzione delle frequenze relative
mean(Vett)
median(Vett)
sd(Vett)
var(Vett)
var(Vett)*(length(Vett)-1)/length(Vett) # varianza della popolazione
Vett2<-c(0,3,3) #dichiaro il vettore “Vett2”
cov(Vett, Vett2) # covarianza dei vettori “Vett” e “Vett2”
cor(Vett, Vett2) #correlazionedei vettori “Vett” e “Vett2”
2.8 Il ciclo for
Il ciclo for() permette di eseguire una determinata operazione, oppure una serie di istruzioni, per
un numero prefissato di volte. Vi si accede con for (variabile in vettore) { istruzioni }.
58
Esempio: si utilizzi il ciclo for() per definire la somma dei primi 10 numeri naturali.
somma<-0
for (i in 1:10){
#la "i" serve unicamente come puntatore (temporaneo) per passare tutti
gli oggetti,uno alla volta, specificati dopo l'"in"
somma<-somma+i
}
somma
Altro esempio: riempimento vettore
num<-NULL #inizializzo un vettore con zero elementi (vuoto)
for (i in 1:10){
num<-c(num, i)
}
num
Alternativamente:
num<-0 #inizializzo un vettore con zero elementi (vuoto)
for (i in 1:10){
num[i]<-i
}
num
2.9 Matrici in R
Per creare una matrice si usa il comando matrix(); è necessario specificare nrow e/o ncol per
determinare le dimensioni della matrice e la modalità di riempimento (per riga byrow=T, per
colonna, l’opzione di default, byrow=F).
La gestione di una matrice è simile a quella vista per i vettori: ogni elemento di una matrice è
univocamente determinato da due indici, il primo indica la posizione di riga e il secondo si riferisce
alla colonna.
Le funzioni cbind() e rbind() vengono usate per aggiungere rispettivamente colonne e righe
ad una matrice.
Alcuni esempi:
A<-matrix(c(1,4,6,8,-1,-4,0,6,0),nrow=3,ncol=3,byrow=T); A
Vett<-c(-3,8,6); Vett
Amod<-cbind(A,Vett) # aggiunge una colonna ad A
Amod
Amod<-rbind(A,Vett); Amod # aggiunge una riga ad A
A[1,1] # estrae l’elemento in posizione (1,1) ovvero prima colonna, prima
riga
59
A[1,2] # estrae l’elemento in posizione (1,2)
A[1,] # estrae la prima riga
A[,1] # estrae la prima colonna
A[1:2,]# estrae le righe dalla 1 alla 2
A[c(1,3),] # estrae le righe 1 e 3
dim(A) # dimensioni della matrice
dim(A)[1] # numero di righe della matrice
dim(A)[2] # numero di colonne della matrice
diag(3)# matrice identità di ordine 3x3
diag(A)# elementi della diagonale principale
t(A) # trasposta di A
A*A # prodotto elemento per elemento delle due matrici
A%*%A # prodotto scalare
2.10 I data.frame in R
I data.frame sono gli oggetti che più si utilizzano nell’analisi statistica dei dati; sono simili alle
matrici ma con colonne che possono contenere dati di tipo diverso: in un data.frame è possibile
rappresentare contestualmente variabili numeriche e variabili alfanumeriche, cosa che non è
possibile fare in una matrice.
Definisco tre vettori di uguale lunghezza:
eta<-c(44, 49, 52, 62, 53, 58, 56, 59, 53, 50, 64, 58, 42, 58, 63)
sesso<-c("f","m","m","m","m","f","f","m","m","m","m","m","m","m","f")
status<-c(1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0) # La variabile
status indica la condizione di salute del soggetto: 0 indica i sani e 1
indica i malati
Per creare un data.frame si usa il comando data.frame()inserendo nelle parentesi i nomi delle
variabili (vettori) di uguale lunghezza che si vuole siano contenute nel data.frame stesso.
prova<-data.frame(eta,sesso,status)
head(prova) #visualizzo un estratto del data.frame appena creato
Ora rimuovo i tre vettori e lavoro direttamente con il data.frame appena creato (che comunque
contiene le variabili).
rm(eta); rm(sesso); rm(status)
60
La gestione di tale oggetto è simile a quella vista per le matrici. Ogni elemento di un data.frame è
univocamente determinato da due indici: il primo indica la posizione di riga e il secondo si riferisce
alla colonna. Le funzioni cbind() e rbind()vengono usate per aggiungere rispettivamente
colonne e righe:
aggiunta<-c(33, "m",0)
prova1<-rbind(prova, aggiunta); prova1
Inoltre vi sono differenti modi per estrarre parti di data.frame su cui si ha interesse lavorare.
Un modo, analogamente a quanto visto per le matrici, è quello di operare con gli indici di riga e di
colonna.
dati.sub1<- prova[, c(1, 3)]; dati.sub1 # Selezione di colonne mediante
indici
dati.sub2<- prova[3:6, c(1,3)]; dati.sub2 # Selezione di un estratto di
righe e colonne mediante indici (1a e 3a riga delle colonne)
Per eliminare colonne e righe da un data.frame è sufficiente anteporre agli indici il segno “-”:
dati.sub3<- prova[,-c(1,3)]; dati.sub3
dati.sub4<- prova[-c(7,11),]; dati.sub4
Altri possibili modi sono quelli di utilizzare l’operatore == oppure il comando subset(), che
selezionano righe o colonne con condizioni logiche.
Di seguito alcuni esempi.
Selezione di righe
prova[prova$sesso == "m",] # seleziono la parte di dataset relativa ai
maschi
oppure
dati.sub5<- subset(prova, prova$sesso == "m"); dati.sub5# seleziono la
parte di dataset relativa ai maschi
Il carattere dedicato $, specificato tra il nome del data.frame e quello della variabile, consente di
estrarre le variabili (vettori) dal data.frame considerato.
prova$sesso # variabile sesso del data.frame “prova”
Selezione di righe con condizione multipla:
prova[prova$sesso == "m" & prova$status ==0,] # seleziono la parte di
dataset relativa ai maschi sani
61
alternativamente:
dati.sub6<- subset(prova, prova$sesso == "m" & prova$status ==0);
dati.sub6# seleziono la parte di dataset relativa ai maschi sani
Selezione contestuale di un estratto di righe e di intere colonne:
dati.sub7 <- subset(prova, prova$sesso =="m" &prova$status == 1, select =
c(eta, status)); dati.sub7
Selezione di riga con condizione multipla mediante indici:
dati.sub8 <- prova[prova$eta %in% c(53, 64), ]; dati.sub8
Selezione di righe che contengono un valore predeterminato:
row_sub = apply(prova, 1, function(row) any(row ==59 ))
prova[row_sub,]
Selezione di colonne che contengono un valore predeterminato:
col_sub = apply(prova, 2, function(col) any(col ==59 ))
prova[,col_sub]
2.11 Procedure di importazione ed esportazione dei dati
L'importazione di dati, generati da programmi esterni ad R, può avvenire in diversi modi. Le
funzioni dedicate a tale scopo sono diverse:read.table(), read.csv(), read.csv2(),
read.delim(), read.delim2(), scan() sono solo alcune di esse per le quali si consiglia di
consultare l’help del programma.
Idati (o matrice di dati) importati in ambiente R assumono classe data.frame. Tra tutte, la
funzione read.table consente di importare i dati (formato tabella) contenuti in un file di
testo(.txt) in maniera più semplice:
Per importare dei dataset esterni, esiste l'opzione universale file.choose() da inserire
all'interno del comando di importazione relativo al tipo di dataset che si intende importare: tale
l'opzione permette di scegliere il file da importare direttamente con il mouse senza dover digitare (e
quindi ricordarsi) l'esatto nome (questo rende l'importazione interattiva). Per identificare il dataset
importato è sempre consigliato assegnargli un nome (nella fattispecie dati):
dati<-read.table(file.choose(), header= TRUE, dec=",", sep= "")
# importazione del file "esempio.txt"
dati; class(dati) #visualizzo dati e ne verifico la classe
62
Per visualizzare le variabili (solitamente identificate dalle colonne di una matrice di dati) del dataset
importato è difatti necessario assegnare un nome all'importazione e successivamente utilizzare il
comando del tipo ""nome assegnazione dataset importato in R"[,i]" (dove i è
il numero della colonna).
dati[,4] #visualizzo colonna 4 del data.frame "dati"
L'opzione header, se TRUE (il default è FALSE), indica che la prima riga del file contiene i nomi
delle variabili. L’opzione sep comunica a R il carattere separatore (delle colonne) nel file di
origine (in questo caso “uno spazio”). L’opzione dec comunica al software il tipo di separatore
decimale utilizzato nel file di origine.
Vi è poi l'utilissima opzione na.strings che serve per far identificare da R i valori mancanti. A
tale proposito si ricorda che a destra dell'uguale, tra virgolette, si inserisce il carattere che identifica
il valore mancante nel set di dati originario: chiaramente tale carattere deve essere conosciuto a
priori e comune per tutti i missing.
L’utilizzo di quest’ultima opzione è apprezzabile con l’esempio seguente:
passo 1a: importazione del file “esempio con missing.txt” (senza l'opzione na.strings)
dati_M<-read.table(file.choose(), sep= "", dec=",", header= TRUE)
passo 2a: calcolo della media di una variabile del dataset importato (colonna 4) in cui compare un
valore mancante NON considerato tale da R. L’opzione na.rm=TRUE comunica a R di operare
(nella fattispecie di fare la media) rimuovendo i valori mancanti.
mean(dati_M[,4], na.rm = TRUE)
#L’output è NA (NotAvailable) e inoltre viene visualizzato un messaggio
di warning poiché i valori mancanti non sono considerati tali.
passo 1b: importazione del file “esempio con missing.txt” (con l'opzione na.strings), i valori
mancanti sono codificati da "."
dati_C<-read.table(file.choose(), sep= "", header= TRUE, dec=",",
na.strings=".")
passo 2b: calcolo della media di una variabile del dataset importato (colonna 4 in cui compare un
valore mancante considerato tale da R. L’opzione na.rm=TRUE comunica a R di operare (nella
fattispecie di fare la media) rimuovendo i valori mancanti.
head(dati_C)
mean(dati_C[,4], na.rm = TRUE)
#calcola la media sui valori validi effettivi considerando i valori
mancanti come tali!!!!
Per importare i dati da un fileExcel(.xls)è invece necessario:
1) salvare il file Excel con l’estensione ".csv" (dal menu a tendina relativo all’estensione del file);
2) chiudere il file .csv e importarlo in ambiente R con read.csv2
63
# esempio per l’importazione del file "esempio con missing.csv"
considerando i valori mancanti identificati dalla stringa "."
dati_csv<-read.csv2(file.choose(), header= TRUE, sep= ";", dec=",",
na.strings=".")
head(dati_csv)
Per visualizzare la tipologia di carattere separatore utilizzato si consiglia di aprire, prima
dell’operazione di importazione, il file origine (in questo caso “.csv”) con il "blocco note" (nella
fattispecie il “;” comanda la struttura di separazione).
Per le esportazioni di oggetti da R ad altri programmi le operazioni sono simili. Per esempio, per
esportare un oggetto R in un file .txt si può utilizzare la funzione:
write.table(nomeoggetto,"nomefileditesto.txt")
Una specificazione di tale comando potrebbe essere quella di scrivere una matrice o un data.frame
in un file di testo (formato tabella). Un esempio di ciò è il seguente:
write.table(dati_csv,"esempio esportato.txt", sep=" ", row.names=F,
col.names=T)
Nella directory in cui si sta lavorando comparirà il nuovo file appena esportato “esempio
esportato.txt”.
getwd() # per visualizzare la directory di lavoro
Con le opzioni row.names e col.names si specifica (in modo logico: TRUE o FALSE) se le
righe e/o le colonne devono possedere le intestazioni.
Per esportare un file in Excel è consigliabile passare prima dall'estensione .csv
write.table(dati,"esempio esportato in EXCEL.csv", sep=";", dec=",",
row.names=F, col.names=T)
2.11.1 I comandi header, colnames(), $ e attach()
In fase di importazione, a prescindere dal file importato, l’opzione header=TRUE permette di
utilizzare i nomi delle variabili del dataset originario (ottenibili dal comando colnames()).
Questa operazione è consentita attraverso il carattere $ o alternativamente con il comando
attach().
DATI<-read.table(file.choose(), sep= "", header= TRUE, dec=".",
na.strings=".") #importo il file “stroke in young.txt”
colnames(DATI)
DATI$age
64
attach(DATI)
age #visualizza la variabile "age"
Una volta che si è assegnato il nome alla colonna (variabile) è possibile effettuare qualsivoglia
operazione utilizzando tale nome.
mean(age) #media di tutti gli elementi della variabile “age”
var(age) #varianza campionaria di tutti gli elementi della variabile
“age”
2.11.2 Cenni di riordino dei dati
A volte è possibile che il dataset di origine non si presenti con il format consigliato per R ovvero di
tipo “matrice di dati” (righe=soggetti  variabili=colonne). In questi casi per rendere il dataset
maggiormente fruibile dal software è necessario riordinarlo con il programma che ha generato quei
dati. Di seguito un esempio con un file di dati excel (.csv).
In excel, aprire il file “esempio format non matrice di dati.csv”. Come si può notare il dataset è
suddiviso per gruppi (sesso); tuttavia per facilitare le analisi statistiche con R converrebbe avere un
soggetto per ogni riga e quindi predisporre una “matrice di dati” pronta per l’importazione appunto
in R. In questo caso è quindi auspicabile creare una variabile sesso che, per ogni soggetto, mi
discrimini il genere di appartenenza. Quindi, operativamente, si sposteranno i dati del gruppo dei
maschi (senza l’intestazione) immediatamente sotto i dati relativi alle femmine, in modo da
incolonnarli; poi si cancellerà l’intestazione per il gruppo maschi, si dovrà creare la nuova variabile
sesso3, che si riempirà con f o m, e infine si importerà il dataset in R con la procedura sopra
descritta.
dati_mod<-read.csv2(file.choose(), header= TRUE, sep= ";", dec=",")
#importo il file “esempio format non matrice dati.csv” e gli assegno il
nome "dati_mod"
head(dati_mod)
Come si può notare il format dei dati importati in R è di tipo “matrice dei dati” e quindi più
facilmente analizzabile in R.
colnames(dati_mod)
attach(dati_mod)
mean(Peso..kg.[sesso=="m"]) #peso dei maschi
Tale procedura di riordino dei dati è possibile (e forse preferibile) anche in R. Di seguito le
istruzioni.
3
Da notare che l’inserimento della variabile sesso è naturalmente consentito anche in R (dopo l’importazione)
65
dati_mod_R<-read.csv2(file.choose(), header= TRUE, sep= ";", dec=",")
#importo il file “esempio format non matrice dati_R.csv” e gli assegno il
nome "dati_mod_R"
Visualizzo il dataset importato e verifico che il format non è “matrice di dati”
dati_mod_R
dim(dati_mod_R) # verifico le dimensioni del data.frame
Ora seleziono i dati validi del gruppo dei maschi ovvero l’intersezione tra le prime quattro righe e le
colonne a dalla 5 alla 7:
dati.maschi<- dati_mod_R[1:4,5:7]; dati.maschi
Omologo le intestazioni dei due data.frame che voglio aggregare (operazione necessaria per
incolonnare due data.frame):
colnames(dati.maschi)=colnames(dati_mod_R[1:11,1:3])
Aggrego i dati maschili sotto ai dati femminili (selezionati):
dati_generale<- rbind(dati_mod_R[1:11,1:3], dati.maschi); dati_generale
E infine aggiungo il vettore relativo al genere:
dati_finale<-cbind(dati_generale, c(rep("f",11), rep("m",4)))
e associo al data.frame un’intestazione più coerente:
colnames(dati_finale)=c("soggetti", "colesterolo", "peso", "sesso")
Visualizzo quindi il data.frame finale pronto per l’analisi statistica
dati_finale
attach(dati_finale)
mean(peso[sesso=="m"]) #peso dei maschi
66
2.12 Come creare nuove funzioni in R
Oltre alle funzioni notevoli (o dedicate) in R è anche possibile creare delle nuove funzioni tramite il
comando function(): gli argomenti (arg) di tali funzioni, separati da virgole, vengono
dichiarati nelle parentesi tonde, mentre il corpo è generalmente incluso tra parentesi graffe; queste
ultime possono essere omesse se il corpo è costituito da operazioni scritte su un’unica riga dopo
function(). Generalmente il risultato della funzione è l’ultimo elemento calcolato.
Lo schema generale per la definizione e l’applicazione di una nuova funzione è il seguente:
1) Definizione
nome_funzione<- function(arg1,arg2,...)
{
#corpo della funzione
operazione1
operazione2
operazione3
#valore restituito dalla funzione
operazione4
}
2) Applicazione
nome_funzione(arg1, arg2, ...)
Il nome_funzione può essere un qualsiasi nome contenente caratteri alfanumerici (compreso il
“.”).Se già esiste una funzione con lo stesso nome quest’ultima verrà sostituita dalla nuova funzione
definita. Gli argomenti che vengono forniti alla funzione possono essere obbligatori od opzionali.
Ad es., function(x)definisce come singolo argomento obbligatorio x. Se si vuole renderlo
opzionale si deve assegnare un valoreall’argomento, ad es. function(x=0).
A livello di definizione della funzione non viene effettuato alcun controllo di ammissibilità. Ad
esempio, se definisco una funzione che calcola la somma di due valori
Somma<- function(a=0, b) a+b
mi aspetterò che sia a che b siano valori numerici. Tuttavia, se richiamo Somma come
Somma(1,"pippo") si verificherà un errore nel momento di effettuare l’operazione di somma.
Se inveceagli argomenti assegno i valori 1 e 2, Somma(1,2) fornirà la risposta corretta,cioè 3.
Essendo l’argomento a opzionale, potrei voler richiamare la funzione specificando solo il secondo
argomento Somma(b=2) che restituirà il valore 2 (0+2). Infine, una funzione può anche non
contenere argomenti o prevedere per ciascuno un valore di default; in questo caso potrà essere
richiamata semplicemente digitando nome_funzione().
Il corpo della funzione contiene tutte le operazioni (comandi) in R che definiscono ciò che
la funzione effettivamente esegue. Gli argomenti e le variabili che sono create all’interno della
funzione sono variabili locali, nel senso che al termine della funzione il loro valore non viene
mantenuto. Nell’esecuzione dei comandi all’interno della funzione le variabili locali hanno
precedenza sulle variabili globali definite a livello di R-console; chiaramente tutte le variabili non
definite localmente devono essere definite a livello di R-console altrimenti si produrrà un errore
(vedi esempio seguente).
67
Definizione della nuova funzione “Es.fun”:
Es.fun<- function(a=0)
# definisco una nuova funzione che contempla il solo argomento opzionale
#“a”
{
# “b” è invece una variabile utilizzata solo nel corpo della funzione
a+b
}
Applicazione di “Es.fun”:
Es.fun() # da notare che b non è definita né localmente né globalmente
In questo caso, siccome b non è definita né localmente né globalmente, R restituisce un messaggio
di errore:
Error in Es.fun() : Object "b" not found
Se però la definisco globalmente nella R-console (fuori dalla funzione):
b <- 2
la funzione non va in errore:
Es.fun() #(=2)
Il valore restituito dalla funzione è il risultato dell’ultima operazione valutata. E’
possibile specificare esplicitamente cosa una funzione debba restituire attraverso i comandi
return(): ad es. return(x) restituisce il contenuto dell’oggetto x. Tuttavia per default una
funzione restituisce il risultato dell’ultima operazione. Inoltre un comando che spesso è utile per
stampare a video i risultati è cat().
Scrivere delle funzioni è il modo più semplice in R per memorizzare una serie di comandi. Scritta
una funzione si può utilizzare il comando edit(nome funzione) per richiamare un editore di testo,
solitamente il Blocco Note, che visualizza il corpo della funzione. In una successiva sessione di
lavoro le funzioni create possono essere richiamate utilizzando il comando source(nome file),
oppure utilizzando la voce “Sorgente codice R…” dal menu “File”. Per conoscere gli argomenti di
una funzione sono disponibili le funzioni args(nome funzione), attributes(nome funzione) e
body(nome funzione).
Di seguito un esempio di creazione di funzione.
Calcolo di una media ponderata:
Definizione:
media.ponderata<- function(x, peso) {
mp<-sum(x*peso)/sum(peso)
cat("la media ponderata è ", mp,"\n")
}
68
Applicazione della funzione media.ponderata: media-voto di 5 esami (ponderata per i crediti
formativi universitari attribuiti a ogni esame).
voti <- c(23, 26, 30, 27, 21) # inserisco i voti dei 5 esami
cfu<- c(10, 2, 8, 6, 6)
# inserisco i crediti dei 5 esami (l’ordine d’inserimento dà la
corrispondenza con i singoli voti)
media.ponderata(voti, cfu) #(=25.3125)
Prima di passare al paragrafo successivo elimino tutti gli oggetti finora creati:
rm(list=ls())
2.13 Elementi di analisi esplorativa e nozioni elementari sulla
gestione dei grafici
In un generico dataset (matrice di dati) ogni riga rappresenta un’unità statistica e ogni colonna
rappresenta una variabile rilevata sull’unità.
dati<-read.table(file.choose(), sep= "", header= TRUE, dec=".",
na.strings=".") #importo il file “stroke in young.txt”
colnames(dati) # visualizzo i nomi delle colonne del dataset importato
dim(dati) # visualizzo la dimensione del dataset importato
fix(dati) # visualizzo i dati con un editor di R "user-friendly"
attach(dati) # comunico al software che intendo lavorare con il nome
delle variabili del dataset originario
A seconda della natura delle variabili oggetto di studio, si utilizzano strumenti diversi per l’analisi
statistica. I dati si dividono in due gruppi principali: qualitativi e quantitativi. I qualitativi sono così
chiamati poiché le variabili da cui derivano possono essere descritte attraverso attributi (come ad
esempio il genere, il tipo di trattamento, ecc.), eventualmente posti tra loro in relazione d’ordine (ad
esempio il livello del titolo di studio, ecc.). Le variabili qualitative sono dunque rilevate su scala
nominale e ordinale, rispettivamente. I dati numerici importati in R vengono di default letti come
variabili quantitative; se però il ricercatore sa che tali dati corrispondono a fenomeni qualitativi,è
necessario specificare l’attributo factor (oppure ordered nel caso di modalità ordinali).
apoe # variabile numerica
Apoe<-factor(apoe); Apoe # variabile qualitativa nominale
Apoe.ord<-ordered(apoe); Apoe.ord # variabile qualitativa ordinale
Anche per le variabili quantitative, benché a livello di programmazione non cambi molto, si
possono distinguere due sotto-tipologie: quelle discrete e quelle continue. In generale si hanno
69
variabili quantitative discrete quando le caratteristiche sono rilevate attraverso operazioni di
conteggio (come ad esempio il numero di figli per coppia, il numero di guasti, ecc.). Si attribuisce
invece natura continua a quelle variabili che attengono a misurazioni di grandezze fisiche (ad
esempio lunghezza, temperatura, tempo,ecc.).
La prima fase di ogni analisi statistica consiste nell’organizzazione e sintesi delle osservazioni,
prima di utilizzarle nell’analisi. Opportune rappresentazioni tabellari e grafiche dei dati sono
strumenti essenziali nell’elaborazione dell’informazione.
In questo paragrafo vengono introdotti alcuni comandi che permettono di estrarre da un set di dati
informazioni di riepilogo sulla base della natura qualitativa o quantitativa delle variabili. Vengono
poi presentati alcuni metodi grafici con cui è possibile ispezionare le caratteristiche del campione in
esame.
In primo luogo, soprattutto per variabili qualitative (es. Apoe) o quantitative discrete (es. apoe),
un utile strumento per avere una panoramica iniziale è la tabella delle frequenza assolute (o
relative): il comando per ottenere ciò è table.
table(apoe) #distribuzione delle frequenze assolute
Per estrarre la frequenza di una specifica modalità, l’operatore di selezione (interno al comando
table) è il medesimo di prima (==).
table(apoe[apoe==2])
Un commando alternativo, applicabile a variabili qualitative e che gestisce anche i valori mancanti,
è summary:
summary(Apoe) # si ricordi che Apoe (con A maiuscola) è nominale
summary è un comando molto importante anche per visualizzare le principali statistiche di sintesi
e riepilogare le informazioni contenute in una variabile quantitativa continua.
summary(age)
Per ottenere la distribuzione delle frequenze relative è sufficiente dividere per la numerosità
campionaria.
table(apoe)/length(apoe)
oppure
table(apoe)/sum(table(apoe))
Mentre per la distribuzione cumulate il commando è cumsum
cumsum(table(apoe)) # frequenze assolute cumulate
cumsum(table(apoe))/length(apoe) # frequenze relative cumulate
Se poi per una variabile quantitativa volessi ottenere una distribuzione di frequenza più sintetica
sarebbe opportuno dividere i dati in classi. Per esempio, la variabile age potrei raggrupparla così:
70
classi = c(10, 20, 30, 40, 50, 60)
classi
assegnando, con il comando cut, ciascuna età della variabile alla sua classe di appartenenza:
age.per.classi=cut(age, breaks = classi); age.per.classi
e creando infine la tabella di frequenza:
table(age.per.classi) # frequenze assolute
table(age.per.classi) / sum(table(age.per.classi)) # frequenze relative
Se poi volessi lasciare ad R l’onere di costruire le classi, c’è la possibilità di scegliere solo il
numero di classi in cui vogliamo suddividere il nostro insieme di dati:
age.per.classi.R=cut(age, breaks = 5); age.per.classi.R
table(age.per.classi.R)
In questo caso abbiamo semplicemente una suddivisione in 5 intervalli del campo di variazione dei
dati.
Il comando table è anche utile per creare tavole di contingenza per 2 variabili: l’esempio che
segue è illuminante:
A <- factor(c(0,0,0,0,1,1,2,2,2,2,2,2,2))
B <- factor(c(0,1,0,0,1,1,1,1,0,0,1,1,1))
table(B, A) #la prima variabile si colloca per riga, la seconda per
colonna
Benché le distribuzioni di frequenza siano strumenti esaurienti dal punto di vista dell’informazione
che contengono, spesso è molto meglio darne anche una rappresentazione grafica.
Il sistema grafico di R si sviluppa su due insiemi di funzioni di base: le funzioni di alto livello
creano le vere e proprie immagini complete (ovvero la parte corposa del grafico); le funzioni di
basso livello (od opzioni) consentono invece di manipolare un grafico esistente aggiungendo o
raffinando particolari elementi.
Di seguito un elenco non esaustivo di funzioni di alto livello, contemplanti le rilevazioni contenute
nei vettori x e y (sotto dichiarati), utile alla realizzazione di differenti tipi di grafici.
x<-c(1,2,3,4,5,6,7,8,9,10,11,12,13)
y<-c(5,4,3,2,8,2,4,6,8,10,0,3,-4)
hist(y) # fornisce l’istogramma sulla base delle frequenze del vettore y
71
plot(x,y) #fornisce il grafico a dispersione di x e y
barplot(x) # fornisce un grafico a barre del vettore x (1 barra per ogni
elemento del vettore)
72
pie(table(y)) #fornisce un grafico a torta del vettore x
boxplot(y) # fornisce il boxplot4 del vettore y
install.packages("vioplot"); require(vioplot) #installo e carico il
pacchetto "violplot"
vioplot(y, names="") # fornisce il violin-plot del vettore y
4
I pallini rappresentati sono gli outlier (valori estremi o anomali) che distano dal primo quartile (in senso decrescente) e
dal terzo (in senso crescente) di più di ‘1,5 × range interquartile dei dati’ (il range interquartile è la differenza tra il
terzo e il primo quartile).
73
par(mfrow=c(1,2))
finestra
#
permette
di
visualizzare
più
grafici5in
un’unica
boxplot(x, xlab= "box plot"); vioplot(x, names="violin plot") # grafici
appaiati6 dal comando "par(mfrow=c(…,…))"
Quando due variabili inserite nel comando plot sono rispettivamente nominale e quantitativa, R
restituisce un’unica finestra grafica i boxplots della seconda per ogni modalità della prima.
plot(B,x)
5
6
A seconda dei numeri inseriti nel vettore: c(numero di righe, numero di colonne).
Nella fattispecie due grafici disposti su una riga e due colonne.
74
Per il violin plot non esiste questa possibilità e di conseguenza bisogna operare con le condizioni
logiche:
vioplot(x[B==0],x[B==1], names=c("0","1"))
dev.off() # chiudo la finestra grafico (alternativo alla "x" in alto a
destra)
75
Di seguito un elenco, sempre non esaustivo, di funzioni di basso livello:
main : assegna un titolo al grafico. Esempio:
plot(x,y,main="titolo del grafico")
sub : assegna un sottotitolo al grafico. Esempio:
plot(x, y, sub="sottotitolo del grafico")
76
xlab:assegna un nome all’asse delle ascisse.
ylab: assegna un nome all’asse delle ordinate. Esempio:
plot(x,y, xlab="ascisse", ylab="ordinate")
xlim=c(a, b) : delimita l’asse delle ascisse tra il valore a e il valore b
ylim=c(c, d) : delimita l’asse delle ordinate tra il valore c e il valore d. Esempio:
plot(x,y,xlim=c(0, 5), ylim=c(0, 8))
77
type : indica il tipo di grafico (a dispersione) che viene rappresentato. Esempio:
plot(x[1:6],y[1:6],type="o") # grafico (a dispersione) per segmenti
lty: tipo di linea che viene disegnata. Esempio:
plot(x[1:4],y[1:4],type="o",lty=3)
78
lwd: larghezza della linea che viene disegnata. Esempio:
plot(x[1:4],y[1:4],type="o",lty=3, lwd=3)
labels=T: visualizza la frequenza di ciascuna colonna. Esempio:
hist(x, labels=T) # fornisce l’istogramma sulla base delle frequenze del
vettore x
C’è poi anche la possibilità di specificare una legenda informativa nel riquadro grafico: il comando
legend e l’opzione locator(1) rendono questa operazione interattiva.
plot(x,y, xlab="ascisse", ylab="ordinate")
legend(locator(1), "unità statistica", pch=1)
79
plot(x,y, xlab="ascisse", ylab="ordinate")
legend(locator(1),c("maschi","femmine"),pch=c(1,1))
legend(locator(1),c("maschi","femmine"),pch=c(1,1),col=c(2,3))
Per ulteriori informazioni si rimanda all'help di R:
?plot
?plot.default(graphics)
80
La seguenti tabelle schematizzano alcune rappresentazioni grafiche unidimensionali e
bidimensionali a seconda del tipo di variabile.
variabile qualitativa
(factor o ordered)
Grafico a barre
plot(x)
Diagramma a bastoncini
plot(table(x))
Areogramma a settori circolari
(torta)
pie(table(x))
x\y→
↓
variabile qualitativa
(factor o ordered)
variabile quantitativa
variabile quantitativa
discreta
Grafico a barre
barplot(x)
Diagramma a bastoncini
plot(table(x))
Areogramma a settori circolari
(torta)
pie(table(x))
variabile quantitativa
continua
Istogramma
hist(x)
Scatter plot
plot(x)
Boxplot
boxplot(x)
variabile qualitativa
variabile quantitativa
(factor o ordered)
Areogramma a colonne
Boxplots di y per i livelli di x
plot(x,y)
sovrapposte
plot(x,y)
Boxplots di x per i livelli di y
Scatter plot
plot(x,y)
plot(x,y)
2.14 La ricodifica di variabili in R
In ambiente R esistono numerosi metodi (anche personalizzabili) di ricodifica delle modalità; di
seguito ne vengono presentati tre fra i più usati.
1°metodo – Ricodifica dicotomica
In questo primo metodo viene attuata una binarizzazione con operatori relazionali quali<, > o ==.
Tale operazione restituisce degli output logici di TRUE o FALSE a seconda che la condizione
specificata tra parentesi sia rispettata o meno. Tali output saranno quindi moltiplicati(*) per 1 per
essere trasformati numericamente in 1 o 0 e quindi più facilmente analizzabili. Di seguito qualche
esemplificazione.
gii<-1*(ii>1); gii
gapoe<-1*(apoe>3); gapoe
2° metodo – Ricodifica mediante l’uso dell’operatore relazionale == (uguale)
Importo il dataset:
dati<-read.table("datiSNPs.csv", sep= ";", header= TRUE, na.strings="NA")
head(dati)
colnames(dati)
attach(dati)
81
Ricodifico i primi tre SNPs del dataset seguendo lo schema sotto riportato:
Variabile Modalità origine
rs2808630
0
rs2808630
1
rs2808630
2
→ Modalità destinazione
CC
→
CT
→
TT
→
rs2516839
rs2516839
rs2516839
0
1
2
→
→
→
CC
CT
TT
rs7575840
rs7575840
rs7575840
0
1
2
→
→
→
GG
GT
TT
dati.3SNPs<-subset(dati, select=c(rs2808630, rs2516839, rs7575840))
#estraggo gli SNPs di interesse daldataset importato
head(dati.3SNPs); table(dati.3SNPs) #verifico che le modalità origine
siano quelle specificate (ovvero 0, 1, 2)
dati.3SNPs; dim(dati.3SNPs) #visualizzo dati.3SNPs e ne verifico le
dimensioni
Ricodifico gli SNPs di dati.3SNPs: nella fattispecie devo passare da variabili categoriche di tipo
numerico (int) a variabili categoriche di tipo stringa (motivo per cui devo bordare di apici le
nuove modalità):
str(dati.3SNPs) #verifico il formato delle variabili
La procedura è la seguente: con la stringa dati.3SNPs[,1] comunico al software di operare
sulla prima colonna del data frame dati.3SNPs; la stringa [dati.3SNPs[,1]==0] indica a
R la condizione logica che deve applicare per la ricodifica (nella fattispecie considera le
osservazioni che hanno la variabile rs2808630, alias dati.3SNPs[,1], pari a 0). Infine con
l’assegnazione (<-'C/C') segnalo il nuovo valore alfanumerico che dovrà assumere la modalità
origine. Infine ripeto le medesime istruzioni (mutatismutandis) per le altre modalità e per le altre
variabili.
dati.3SNPs[,1][dati.3SNPs[,1]==0]<-'C/C'
dati.3SNPs[,1][dati.3SNPs[,1]==1]<-'C/T'
dati.3SNPs[,1][dati.3SNPs[,1]==2]<-'T/T'
dati.3SNPs[,2][dati.3SNPs[,2]==0]<-'C/C'
dati.3SNPs[,2][dati.3SNPs[,2]==1]<-'C/T'
dati.3SNPs[,2][dati.3SNPs[,2]==2]<-'T/T'
dati.3SNPs[,3][dati.3SNPs[,3]==0]<-'G/G'
dati.3SNPs[,3][dati.3SNPs[,3]==1]<-'G/T'
dati.3SNPs[,3][dati.3SNPs[,3]==2]<-'T/T'
head(dati.3SNPs) #visualizzo un estratto del dataset ricodificato
82
Un modo più efficiente di gestire questo tipo di ricodifica è quello di implementarla in una funzione
adhoc; l’esempio che segue, utile per ricodificare SNPs con modalità identiche, è illuminante:
dati.4SNPs<-subset(dati, select=c(rs780094,rs10510293,rs864265,
rs12654264)); #estraggo gli SNPs di interesse (che hanno modalità uguali)
head(dati.4SNPs); table(dati.4SNPs) #verifico che le modalità origine
siano quelle specificate (ovvero 0, 1, 2)
Definisco la nuova funzione recode.snp:
recode.snp<-function(dataset,mod.origine,mod.dest){
dataset<-as.matrix(dataset)
for (i in 1:dim(dataset)[2]){
for (j in 1:length(mod.origine)){
dataset[,i][dataset[,i]==mod.origine[j]]=mod.dest[j]
}
}
return(as.data.frame(dataset))
}
Applico recode.snp e le assegno il nome del dataset che voglio ricodificare: si ricordi che
l’ultima operazione della funzione è return(as.data.frame(dataset)) e quindi l’output
è proprio un data.frame ricodificato.
dati.4SNPs<-recode.snp(dati.4SNPs,c(0,1,2),c('C/C','C/T','T/T'))
head(dati.4SNPs) #visualizzo un estratto del dataset ricodificato
3° metodo – Il comando recode del pacchetto epicalc
Per utilizzare questa procedura è necessario che la variabile ricodificata rispetti il formato della
variabile origine (es. character → character, integer → integer, ecc.).
Importo il dataset:
datiSNP<-read.table("datiSNPs.csv", sep= ";", header= TRUE,
na.strings="NA")
install.packages("epicalc") #installo il pacchetto epicalc
library(epicalc) #carico il pacchetto epicalc
colnames(datiSNP)
head(datiSNP); dim(datiSNP)
83
Ora ricodifico gli SNPs del dataset secondo il seguente schema:
Variabile Modalità origine
0; 1; 2
rs2808630
“
rs2516839
“
rs7575840
“
rs1260326
“
rs780094
“
rs10510293
“
rs864265
“
rs12654264
“
rs5370
“
rs328
“
rs3890182
“
rs875434
“
rs3135506
“
rs662799
“
rs1507203
“
rs1800588
“
rs1800775
“
rs7231460
“
rs1529729
“
rs688
“
rs4420638
“
rs10500295
→ Modalità destinazione
C/C; C/T; T/T
→
C/C; C/T; T/T
→
G/G; G/T; T/T
→
C/C; C/T; T/T
→
C/C; C/T; T/T
→
C/C; C/T; T/T
→
G/G; G/T; T/T
→
A/A; A/T; T/T
→
G/G; G/T; T/T
→
C/C; C/G; G/G
→
A/A; A/G; G/G
→
C/C; C/T; T/T
→
C/C; C/G; G/G
→
A/A; A/G; G/G
→
C/C; C/T; T/T
→
C/C; C/T; T/T
→
A/A; A/C; C/C
→
C/C; C/T; T/T
→
C/C; C/T; T/T
→
C/C; C/T; T/T
→
A/A; A/G; G/G
→
A/A; A/G; G/G
→
des(datiSNP) #visualizzo la classe delle variabili contenute nel
dataframe “datiSNP”
datiSNP2=matrix(factor(as.matrix(datiSNP)),ncol=23)
datiSNP2=as.data.frame(datiSNP2)
#converto le variabili del dataframe in formato “factor” per avere la
corrispondenza con la varibili ricodificate (per fare questo passaggio mi
appoggio su un oggetto di tipo matrice)
colnames(datiSNP2)=colnames(datiSNP)
des(datiSNP2)
head(datiSNP2)
attach(datiSNP2) #gestisco le variabili utilizzando il loro nome
(operazione necessaria per l’opzione vars del comando recode)
recode(vars=c(rs2808630, rs2516839, rs1260326, rs780094, rs10510293,
rs875434, rs1507203, rs1800588, rs7231460, rs1529729, rs688),
old.value=c('0','1','2'), new.value=c('C/C','C/T','T/T'), dataFrame =
datiSNP2)
84
recode(vars=c(rs7575840, rs864265, rs5370), old.value=c('0','1','2'),
new.value=c('G/G','G/T','T/T'), dataFrame = datiSNP2)
recode(vars=rs12654264, old.value=c('0','1','2'),
new.value=c('A/A','A/T','T/T'), dataFrame = datiSNP2)
recode(vars=c(rs328,rs3135506),old.value=c('0','1','2'),
new.value=c('C/C','C/G','G/G'), dataFrame = datiSNP2)
recode(vars=rs1800775, old.value=c('0','1','2'),
new.value=c('A/A','A/C','C/C'), dataFrame = datiSNP2)
recode(vars=c(rs3890182, rs662799, rs4420638, rs10500295),
old.value=c('0','1','2'), new.value=c('A/A','A/G','G/G'), dataFrame =
datiSNP2)
head(datiSNP2)
detach(datiSNP2); detach(package:epicalc) #disattivo l’attach del
dataframe datiSNP2 e il pacchetto epicalc
85
Esercitazione 1
Esercizi di “Elementi di programmazione in R e statistica descrittiva”
Esercizio 1
Il numero di decessi per malattie del lavoro in 10 zone industriali è descritto dalla seguente serie:
29
42
20
39
23
27
32
19
40
23
Costruire la distribuzione delle frequenze assolute e relative.
Calcolare la moda, la mediana, la media, la varianza campionaria, la deviazione standard e il
coefficiente di variazione. Infine collocare le misure appena citate nella sezione opportuna della
tabella sottostante e giustificare la scelta.
Misure di posizione
Misure di variabilità
Soluzione:
Inserisco i dati come un vettore:
decessi<-c(29,42,20,39,23,27,32,19,40,23)
Alternativamente posso usare la funzione scan():
decessi<-scan()
29 42 20 39 23 27 32 19 40 23
table(decessi) # distribuzione delle frequenze assolute
decessi
19 20 23 27 29 32 39 40 42
1 1 2 1 1 1 1 1 1
table(decessi)/length(decessi) # distribuzione delle frequenze relative
decessi
19
0.1
20
0.1
23
0.2
27
0.1
29
0.1
32
0.1
39
0.1
40
0.1
42
0.1
86
Calcolo gli indici richiesti:
which.max(table(decessi)) #moda (la modalità con la frequenza maggiore)
"23"
median(decessi) # mediana
28
mean(decessi)# media
29.4
var(decessi) # varianza campionaria
72.71111
sd(decessi) # deviazione standard
8.527081
sqrt(var(decessi)) # altra formula per la deviazione standard
8.527081
sd(decessi)/mean(decessi) # coefficiente di variazione
0.2900368
Misure di posizione
 Moda
 Mediana
 Media
Misure di variabilità
 Varianza
 Deviazione standard
 Coefficiente di variazione
87
Esercizio 2
Dopo aver importato il file “altezze.csv” relativo alla statura (in cm) di 90 studenti di una scuola
media superiore, definito il numero di classi uguale a 6 con ampiezza costante uguale a 5 cm,
calcolare le frequenze assolute, relative e relative cumulate per ogni classe:
Classi
Frequenza
assoluta
Frequenza
relativa
Frequenza
relativa
cumulata
(160; 165]
(165; 170]
(170; 175]
(175; 180]
(180; 185]
(185; 190]
Totale
90
Soluzione:
Importo il file assegnandogli il nome altezze, ne visualizzo un estratto ed eseguo l’attach:
altezze<- read.csv2(file.choose(), sep=";", dec=",", header = T) #importo
il file altezze.csv
head (altezze)
attach (altezze)
Definisco le classi in cui suddividere le altezze:
classi = c(160, 165, 170, 175, 180, 185, 190)
classi
Con il comando cut, ciascuna altezza sarà collocata nella sua classe di appartenenza:
classi.altezza<-cut(Altezza, breaks = classi); classi.altezza
88
Creo infine le tabelle di frequenza:
table(classi.altezza) # frequenze assolute
(160,165]
3
(165,170]
13
(170,175]
31
(175,180]
31
(180,185]
10
(185,190]
2
table(classi.altezza) / sum(table(classi.altezza)) # frequenze relative
(160,165] (165,170] (170,175] (175,180] (180,185] (185,190]
0.03333333 0.14444444 0.34444444 0.34444444 0.11111111 0.02222222
cumsum(table(classi.altezza)) / sum(table(classi.altezza)) #frequenze
relative cumulate
(160,165] (165,170] (170,175] (175,180] (180,185] (185,190]
0.03333333 0.17777778 0.52222222 0.86666667 0.97777778 1.00000000
Esercizio 3
Dicotomizzare la variabile Altezza dell’esercizio 2 su una soglia di 175 cm (0 se minore, 1 se
maggiore o uguale), assegnarle in nome di altezza01, assemblarla al data.frame originario e
esportare l’oggetto assemblato in un file formato .txt.
Soluzione:
altezza01 <- 1*(Altezza>=175); altezza01
data.altezza <- data.frame(altezze,altezza01)
write.table(data.altezza,"data.altezza.txt", sep=" ", dec=",",
row.names=F, col.names=T)
89
Esercizio 4
Importare in R i datasets “sesso.csv” e “peso.csv” e:
a) assemblarli al data.frame altezze già importato assegnandogli il nome soggetti,
b) calcolare media, mediana e varianza (generali e per sesso) per la variabile peso; costruire
quindi la distribuzione di frequenza per il sesso,
c) rappresentare il box-plot della variabile Altezza per ogni sesso e valutare qualitativamente
se le mediane nei due sessi sono diverse, se le distribuzioni sono simmetriche e simili e se
esistono eventuali outliers (valori estremi),
d) esportare il data.frame soggetti in un file .txt.
Soluzione:
Importo i datasets “sesso.csv” e “peso.csv”, li assemblo al data.frame altezze e creo due
ulteriori data.frame (uno per i maschi e uno per le femmine):
sesso<-read.csv2(file.choose(), sep=";", header = T) #importo il file
sesso.csv
peso<-read.csv2(file.choose(),
peso.csv
sep=";",
header
=
T)
#importo
il
file
soggetti<-data.frame(altezze, sesso, peso)
head (soggetti)
maschi<- subset(soggetti, soggetti$sesso == "m"); maschi # seleziono la
parte di dataset relativa agli uomini
femmine<- subset(soggetti, soggetti$sesso == "f"); femmine # seleziono la
parte di dataset relativa alle donne
Calcolo media, mediana e varianza campionaria per la variabile peso e costruisco la distribuzione di
frequenza per il sesso:
mean(soggetti$peso); mean(maschi$peso); mean(femmine$peso)
[1] 80.12222
[1] 80.4375
[1] 79.7619
median(soggetti$peso); median(maschi$peso); median(femmine$peso)
[1] 81
[1] 81
[1] 80
90
var(soggetti$peso); var(maschi$peso); var(femmine$peso)
[1] 29.8613
[1] 27.48537
[1] 33.06388
table(soggetti$sesso) # distribuzione di frequenza di sesso
f m
42 48
plot(soggetti$sesso, soggetti$Altezza, ylab="altezza (in cm)",
col=c("pink","lightblue")) #box plot dell’altezza per sesso
Esporto il data.frame soggetto in un file .csv:
write.table(soggetti,"soggetti.txt", sep="\t", dec=",", row.names=F,
col.names=T)
91
Esercizio 5
Dopo aver importato in R il dataset del file “stroke in young.csv” risolvere i seguenti punti:
a) per ogni variabile (eccetto ‘Id’) descrivere opportunamente il campione a livello sia
esplorativo sia grafico e completare i seguenti items:
1] la media del BMI è ………. Kg/m2;
2] il totale dei soggetti fumatori è ………;
3] il soggetto più anziano ha ……… anni;
4] i soggetti affetti da diabete mellito sono …………;
b) ricodificare la variabile ‘MTHFR’ in 0 (assenza dell’allele T) e 1 (presenza dell’allele T) e
utilizzare un comando/metodo che sia adeguato a descrivere la distribuzione del gene
ricodificato.
Informazioni supplementari per l’esercizio 5:
Legenda delle variabili presenti nel dataset:
Id = id code;
cc = condizione di salute [1 = malato, 0 = sano];
sex = sesso [1 = maschi, 2 = femmine];
age = età in anni;
bmi = Body Mass Index (BMI) in Kg/m2;
hyp = ipertensione [1 = NO, 2 = SI];
dm = diabete mellito [1 = NO, 2 = SI];
smoke = fumatore [1 = NO, 2 = SI];
hypercho = ipercolesterolemia [1 = NO, 2 = SI];
ii = fattore II G20210A [1 = GG, 2 = GA, 3 = AA];
v = fattore V G1691A [1 = NO, 2 = SI];
MTHFR = gene MTHFR [1 = CC, 2 = CT, 3 = TT];
APOE = gene APOE [diviso per categorie].
Soluzione:
dati<-read.csv2(file.choose(), header= TRUE, sep=";", na.string="#NULL!")
fix(dati) # visualizzo i dati con un editor di R “user-friendly”
colnames(dati) # ricavo i nomi delle variabili del dataset importato
attach(dati) # accedo alle variabili digitando il loro nome
92
Comunico al software la natura qualitativa delle seguenti variabili; essendo codificate
numericamente, R, di default, le riconosce come quantitative anche se per il ricercatore non lo sono.
SEX <- factor(sex)
HYP <- factor(hyp)
DM <- factor(dm)
SMOKE <- factor(smoke)
HYPERCHO <- factor(hypercho)
CC <- factor(cc)
II <- factor(ii)
FV <- factor(v)
MTHFR <- factor(mthfr)
APOE <- factor(apoe)
Quindi ora le variabili MAIUSCOLE sono considerate dal software come qualitative (o
categoriche).
Effettuo una prima analisi esplorativa descrivendo quantitativamente e qualitativamente le
caratteristiche del campione:
table(CC)
0
1
164 163
table(SEX)
1
2
169 158
table(HYP)
1
2
290 37
table(DM)
1
2
317 10
table(SMOKE)
1
2
210 117
table(HYPERCHO)
1
2
250 77
summary(age)
Min.
1st Qu.
11.00
30.00
Median
36.00
Mean
34.92
3rd Qu.
40.00
Max.
52.00
93
summary(bmi)
Min.
1st Qu.
14.84
21.18
Median
23.52
Mean
23.98
3rd Qu.
26.26
Max.
40.13
NA's
19
Descrizione quantitativa delle variabili genetiche mediante tabelle di frequenza:
table(II) # 1=GG, 2=GA, 3=AA
1
2
3
306 13
2
table(FV) # 1=assente 2=presente
1
2
310 11
table(MTHFR) # 1=CC, 2=CT, 3=TT
1
2
3
112 158 57
table(APOE) # 1=e2e2, 2=e2e3, 3=e3e3, 4=e2e4, 5=e3e4, 6=e4e4
1
2
3
4
5
6
2 28 231 61
1
2
Descrizione qualitativa (grafici) delle variabili cliniche:
plot(CC, ylim=c(0,200),col=c(3,2), names=c("sani","malati"),
main="Ripartizione di malati e sani")
legend(locator(1),c("164 sani","163 malati"),fill=c(3,2))
94
barplot(table(SEX), main="Ripartizione per sesso",ylim=c(0,200),
col=c("cyan","rosybrown2"), names=c("maschi","femmine"))
legend(1.5,200, c(length(SEX[SEX==1]), length(SEX[SEX==2])),
fill=c("cyan","rosybrown2"))
par(mfrow=c(1,2))
hist(age,main="Distribuzione per età", ylim=c(0,100), xlab="Età",
labels=TRUE, breaks=seq(10,60,5))
boxplot(bmi,main="Boxplot del Body Mass Index", ylab="Kg/m2",col=
"yellow")
95
par(mfrow=c(2,2))
barplot(table(HYP), main="Distribuzione ipertensione",ylim=c(0,300),
col=c(3,2), names=c("No","Si"))
legend(1.5,270,c(length(HYP[HYP==1]),length(HYP[HYP==2])),
fill=c(3,2))
barplot(table(DM), main="Ripartizione per diabete mellito",
ylim=c(0,330), col=c(3,2), names=c("No","Si"))
legend(1.5,280,c(length(DM[DM==1]),length(DM[DM==2])),
fill=c(3,2))
barplot(table(SMOKE), main="Ripartizione per attitudine al fumo",
ylim=c(0,270), col=c(3,2), names=c("No","Si"))
legend(1.5,220,c(length(SMOKE[SMOKE==1]),length(SMOKE[SMOKE==2])),
fill=c(3,2))
barplot(table(HYPERCHO), main="Ripartizione per ipercolesterolemia",
ylim=c(0,300), col=c(3,2), names=c("No","Si"))
legend(1.5,270,c(length(HYPERCHO[HYPERCHO==1]),length(HYPERCHO[HYPERCHO
==2])),fill=c(3,2))
mean(bmi, na.rm=T) # (La media del BMI è 23.97578)
[1] 23.97578
table(SMOKE) # (i fumatori sono 117)
1
2
210 117
96
max(age) # (il soggetto più anziano ha 52 anni)
[1] 52
table(DM) # (i soggetti affetti da diabete mellito sono 10)
1
2
317 10
gmthfr<-1*(mthfr>1) # codifica per l’allele T
table(gmthfr)
0
1
112 215
table(gmthfr)/length(gmthfr)
0
1
0.3425076
0.6574924
97
Esercizio 6
Dopo aver importato il file “altezze.csv” relativo alla statura (in cm) di 90 studenti di una scuola
media superiore, definito il numero di classi uguale a 6 con ampiezza costante uguale a 5 cm,
calcolare:
a. le frequenze assolute e relative per ogni classe;
b. calcolare mediante funzioni (function()) la media ponderata e la varianza ponderata; da
queste ricavare quindi la deviazione standard e il coefficiente di variazione.
Classi
Valore
centrale
di classe
(160; 165]
162.5
(165; 170]
167.5
(170; 175]
172.5
(175; 180]
177.5
(180; 185]
182.5
(185; 190]
187.5
Totale
Frequenza
assoluta
Frequenza
relativa
90
Soluzione:
Importo il file assegnandogli il nome altezze, ne visualizzo un estratto ed eseguo l’attach:
altezze <- read.csv2
altezze.csv
(file.choose(),
header
=
T) #
Importo
il
file
head (altezze)
attach (altezze)
Definisco le classi in cui suddividere le altezze:
classi = c (160, 165, 170, 175, 180, 185, 190)
classi
98
Con il comando cut, ciascuna altezza sarà collocata nella sua classe di appartenenza:
classi.altezza <- cut (Altezza, breaks = classi); classi.altezza
Creo le tabelle di frequenza:
table(classi.altezza) # frequenze assolute
(160,165]
3
(165,170]
13
(170,175]
31
(175,180]
31
(180,185]
10
(185,190]
2
table(classi.altezza) / sum(table(classi.altezza)) # frequenze relative
(160,165] (165,170] (170,175] (175,180] (180,185] (185,190]
0.03333333 0.14444444 0.34444444 0.34444444 0.11111111 0.02222222
Calcolo la media ponderata e la varianza ponderata mediante funzioni di R ad hoc create.
Media ponderata:
Valori = valori centrali di classe;
Ponderazioni = frequenze assolute di classe.
Definisco la funzione:
media.ponderata <- function(x, peso) {
mp <- sum(x*peso)/sum(peso)
cat("la media ponderata è ", mp,"\n")
}
Definisco gli oggetti su cui applicare la funzione:
valori <- c (162.5, 167.5, 172.5, 177.5, 182.5, 187.5) # Valori
num.classe <- c (3, 13, 31, 31, 10, 2) # Ponderazioni
Applico la funzione:
media.ponderata (valori, num.classe)
# (= 174.6111)
Varianza ponderata:
Valori = valori centrali di classe;
Centro = media ponderata calcolata con la funzione precedente (media = 174.6111) ;
Ponderazioni = frequenze assolute di classe.
Definisco la funzione:
varianza.ponderata <- function(x, media, peso) {
vp <- sum(((x-media)^2)* peso) / (sum(peso)-1)
cat("la varianza ponderata è ", vp,"\n")
}
99
Definisco gli oggetti su cui applicare la funzione:
valori <- c (162.5, 167.5, 172.5, 177.5, 182.5, 187.5) # Valori
media <- 174.6111 # Centro
num.classe <- c (3, 13, 31, 31, 10, 2) # Ponderazioni
Applico la funzione:
varianza.ponderata (valori, media, num.classe) # (= 27.51561)
Ora calcolo deviazione standard e coefficiente di variazione:
sqrt(27.51561)
# (= 5.245532, deviazione standard)
5.245532 / 174.6111
# (= 0.03004123, coefficiente di variazione)
100
3. Principi di inferenza statistica
3.1 Distribuzioni di campionamento (teoriche) e variabili
casuali
Le distribuzioni campionarie sono alla base dell’inferenza statistica. Esse permettono di analizzare
le proprietà probabilistiche delle statistiche campionarie, da cui discende la teoria necessaria per le
procedure di inferenza statistica. La distribuzione campionaria è la distribuzione di tutti i possibili
valori che possono essere assunti da una statistica, ossia da una funzione dei dati (ad esempio,
media, varianza, ecc), calcolata su campioni di uguale dimensione ed estratti casualmente dalla
stessa popolazione.
Le distribuzioni campionarie possono essere empiricamente costruite attraverso R:
(1) si estraggono M campioni di dimensione n da una variabile casuale (popolazione) di
riferimento;
(2) si calcola la statistica di interesse per ogni campione;
(3) si costruisce l’istogramma della statistica dei diversi valori osservati.
Esempio con la statistica media campionaria:
# inizializzo a zero l’oggetto mu
mu=0 # In mu (vettore) inserirò tutti i valori di media campionaria,
calcolati su ogni campione e su cui andrò a produrre l’istogramma.
#scelgo arbitrariamente il numero di campioni (M) che simulerò e la
relativa numerosità campionarie (n)
M=10000 # campioni estratti con campionamento casuale semplice
n=1000; # dimensione campionaria di ogni campione
for(i in 1:10000){ #(1)
x = rnorm(1000,60,9.2) #variabile casuale di riferimento: Normale(60,9.2)
mu[i] = mean(x) #(2)
}
#(3)
hist(mu, xlim=c(58,62), prob=F, main="Istogramma delle simulazioni di
media campionaria su 10000 campioni di ampiezza 1000")
101
Da cui si può ottenere la distribuzione delle frequenze relative (probabilistica)
hist(mu,ylim=c(0,1.6), xlim=c(58,62), prob=T, main="Istogramma delle
frequenze relative delle simulazioni di media campionaria su 10000
campioni di ampiezza 1000")
#sovrappongo la funzione di densità di una variabile casuale normale di
media 60 e deviazione standard 0.29=deviazione standard/n
curve(dnorm(x,60,0.29),58,62, add = TRUE)
L’approssimazione è più che eccellente!!!
102
Capita spesso che studiando un fenomeno aleatorio si sia anche interessati a una qualche funzione
dei possibili esiti oltre agli esiti stessi. Queste funzioni teoriche di valori, definite sullo spazio
campionario, sono note come variabili casuali. I valori di una variabile casuale sono determinati
dall’esito di un qualche esperimento a cui possiamo associare delle probabilità: tali probabilità
produrranno la distribuzione teorica di campionamento della variabile casuale.
3.2 Alcune variabili casuali notevoli
Lo standard dei comandi che R segue per le variabili casuali (v. c.) notevoli è quello di identificare
il nome specifico, ad esempio binom per la v. c. binomiale, e farlo precedere dalle lettere d, p e q
per identificare rispettivamente la densità (o probabilità), la distribuzione cumulata e i quantili;
inoltre il prefisso r serve per generare delle determinazioni casuali dalla variabile in oggetto. Nello
specifico:
• d permette di ottenere la funzione di densità (o probabilità) della variabile, indicando quindi un
numero o un vettore di numeri rispetto ai quali si desidera ottenere la funzione di densità o di
probabilità;
• p permette di ottenere la funzione di ripartizione (distribuzione cumulata) della variabile; in tal
caso è necessario indicare il quantile o il vettore dei quantili rispetto ai quali si vuole calcolare il
valore della funzione di ripartizione (aggiungendo l’opzione lower.tail=F si ottiene la
probabilità dell’evento complementare);
• q permette di ottenere i quantili della variabile specificata, indicando la coda inferiore di
probabilità o il vettore delle code superiori di probabilità legate ai quantili corrispondenti;
• r permette di generare numeri casuali dalla variabile specificata, indicando un numero intero
corrispondente alla numerosità del campione che si vuole ottenere. Per un campione di numeri
casuali piuttosto numeroso, la distribuzione empirica di questi ultimi, ad esempio tramite un
istogramma, simula la funzione di densità della variabile da cui è stato generato il campione stesso.
Oltre al prefisso, tali funzioni, per loro natura, richiedono anche la specificazione dei parametri
della distribuzione. Ad esempio per la v. c. normale è necessario inserire mean= e sd= un
qualsivoglia comando.
Lista delle radici dei comandi in R per gestire le variabili casuali più conosciute
Variabile Casuale
Bernoulli
Binomiale
Poisson
Normale
Chi-quadro
T di Student
F di Snedecor/Fisher
Tipologia Parametri Radice comando in R
binom
Discreta
1, prob
binom
Discreta
n, prob
pois
Discreta
media
norm
Continua media, dev.st.
chisq
Continua
gdl
t
Continua
gdl
f
Continua
gdl1,gdl2
prob=probabilità, dev. st. = deviazione standard, gdl= gradi di libertà
103
Di seguito due esempi sull’uso dei comandi appena descritti
1. Supponendo che la statura dei bambini di 10 anni si distribuisca pressoché normalmente con una
media di 122 cm e una deviazione standard di 12, calcolare
a. La percentuale che un bambino scelto a caso nella popolazione abbia una statura maggiore di 145
cm;
b. La probabilità che un bambino sia alto da 126 a 130 cm;
c. L’altezza dei bambini relativa al 95° percentile;
d. In una popolazione di 10000 individui quanti bimbini ci si attende abbiano una statura inferiore a
118 cm?
Grafico la distribuzione di densità della v.c. Normale (mu=122, sd=12)
curve(dnorm(x,122,12),82,162, xlab= "statura", ylab="densità")
a. La percentuale che un bambino scelto a caso nella popolazione abbia una statura maggiore di 145
cm;
1-pnorm(145, 122, 12) # 2.76 %
#(complemento della funzione di ripartizione a 145)
b. La probabilità che un bambino sia alto da 126 a 130 cm;
104
pnorm(130,122,12)-pnorm(126,122,12) # 0.1169488
#(differenza di funzione di ripartizione)
c. L’altezza dei bambini relativa al 95° percentile;
qnorm(0.95,122,12) # 141.7382
d. In una popolazione di 10000 individui quanti bimbini ci si attende abbiano una statura inferiore a
118 cm?
pnorm(118,122,12)*10000 # 3694
2. Da uno studio condotto sullo sviluppo di malattie cardiovascolari nel reparto alzhaimer di una
clinica geriatrica è risultato che il 70% degli anziani presenta placche aterosclerotiche a livello
diffuso. Supponendo che la v. c. che governa tale patologia sia una binomiale con probabilità di
evento pari a 0.7, e supponendo che si debbano visitare 10 nuovi pazienti anziani dementi, si
calcoli:
a. la probabilità che cinque pazienti presentino placca aterosclerotica;
b. sette presentino la placca;
c. al più quattro presentino la patologia;
Grafico la distribuzione di probabilità della v.c. Binomiale (n=10,p=0.7)
plot(0:10,dbinom(0:10,10,0.7),type="h",xlab="malati alzhaimer",
ylab="rischio alzhaimer",ylim=c(0,.6),lwd=3)
105
a. la probabilità che cinque presentino placca aterosclerotica;
dbinom(5,10,0.7) #0.1029193
b. sette presentino la placca;
dbinom(7, 10, 0.7) #0.2668279
c. al più quattro presentino la patologia;
pbinom(4, 10, 0.7) # 0.04734899
3.3 Stime e stimatori
Quando si raccoglie un campione di popolazione la prima operazione che viene immediata è quella
di descriverlo con opportuni indici di sintesi (o parametri). Sopra ne abbiamo già visti diversi, quali
media, varianza, mediana, proporzione ecc.; ma se si desidera estendere i risultati trovati sul
campione a un’intera popolazione i valori di quegli indici sono ancora validi? In questa fase emerge
la grande differenza tra stima e stimatore. Per stima statistica “puntuale” si intende il valore
dell’indice (parametro) calcolato appunto sul campione. Lo stimatore è invece qualcosa di più
raffinato e sottintende al concetto frequentista di campionamento ripetuto. Difatti considerando
sequenzialmente numerosi (potenzialmente infiniti) campioni di uguale struttura, e calcolando su
ciascuno di essi, di volta in volta, la stima puntuale, si genera in automatico una variabile casuale a
cui è associata una distribuzione di probabilità (o campionaria): tale variabile casuale è appunto lo
stimatore dell’indice di sintesi. Dato questa piccola introduzione, R, mediante simulazioni, ci
fornisce la possibilità di reiterare il campionamento e quindi di verificare la forma delle
distribuzioni di probabilità degli stimatori degli indici di sintesi a cui siamo interessati. Le
distribuzioni di probabilità saranno essenziali per poter fare inferenza (test di significatività e
intervalli di confidenza) ovvero quel processo che ci consente di estendere i risultati dal campione
alla popolazione.
Inoltre, un altro concetto molto importante è quello della variabile casuale di partenza o modello
probabilistico di riferimento. Difatti, a seguito del campionamento ripetuto, quando si genera uno
stimatore (e quindi una distribuzione di probabilità) spesso è ben conosciuta la legge casuale
(ovvero il caso) che a priori governa il fenomeno di interesse. Dato ciò, sono molteplici le
circostanze in cui è la variabile casuale normale ad assurgere a tale ruolo.
Di seguito è illustrata la verifica, mediante simulazioni, delle distribuzioni di probabilità di tre
stimatori: media campionaria, varianza campionaria e rapporto di varianze campionarie.
Simulazione di stime di media campionaria da 10000 campioni di numerosità 1000. Variabile
casuale di partenza con parametri scelti arbitrariamente: N (=60, =9.2). Stimatore media
campionaria (convergenza a una normale standardizzata)
Inizializzo a zero i vettori “mu” e “z”. Il primo conterrà tutte le medie campionarie dei 10000
campioni simulati, il secondo i valori della statistica test z= media campionaria standardizzata sui
veri valori parametrici.
mu=0
z=0
106
for(i in 1:10000){
x = rnorm(1000,60,9.2)
mu[i] = mean(x) # stima del parametro oggetto di analisi
z[i] = (mu[i]-60)/(9.2/sqrt(1000)) #statistica test o q.tà pivotale
}
var(z) # 1
mean(z) # 0
Sovrappongo l’istogramma dei valori z prodotti dalla simulazione alla densità di una vera variabile
casuale normale standardizzata: l’approssimazione è più che eccellente.
hist(z,ylim=c(0,0.8), xlim=c(-4,4), prob=T, main="Istogramma delle
simulazioni di media campionaria (standardizzata) su 10000 campioni di
ampiezza 1000")
curve(dnorm(x),-4,4, add = TRUE) #densità di una v.c. normale
Lo stimatore media campionaria si distribuisce come una variabile casuale normale!
Simulazione di stime di varianza campionaria da 10000 campioni di numerosità 40 (n). Stimatore
varianza campionaria (convergenza a una distribuzione 2 con gradi di libertà 39 (40-1), a meno di
una costante). Variabile casuale di partenza con parametri scelti arbitrariamente: N (=60, =9.2).
Inizializzo a zero i vettori “varianza” e “X2”. Il primo conterrà tutte le varianze campionarie dei
10000 campioni simulati, il secondo i valori della statistica test X2= varianza×39/2
varianza=0
X2=0
for(i in 1:10000){
y = rnorm(40,60,9.2)
varianza[i] = var(y) #stima del parametro oggetto di analisi
X2[i] = varianza[i]*39/9.2^2 # statistica test o q.tà pivotale
}
107
Sovrappongo l’istogramma dei valori chi prodotti dalla simulazione a una vera variabile casuale 2
con 39 gradi di libertà: l’approssimazione è più che eccellente.
hist(X2, prob=T, main="Istogramma delle simulazioni di X2
campionarie su 10000 campioni di ampiezza 40")
curve(dchisq(x,39), add = TRUE) #densità di una v.c. 2 con 39 g.d.l.
Lo stimatore varianza campionaria (moltiplicato per la costante “(n-1)/varianza della popolazione”)
si distribuisce come una variabile  con gradi di libertà pari alla numerosità campionaria meno
uno!
Simulazione di stime di rapporto di varianze da 10000 coppie di campioni di numerosità 25.
Stimatore: rapporto di varianze (convergenza a una distribuzione F di Fisher con gradi di libertà n-1
per il numeratore e n-1 per il denominatore). Le variabili casuali di partenza sono due normali con
parametri scelti arbitrariamente (le varianze devono essere uguali, mentre le medie possono essere
diverse): N (=60, =9.2) e N (=80, =9.2).
Inizializzo a zero il vettore “F” che conterrà tutti i valori della statistica test F= var(x1)/var(x2)
F=0 # inizializzo a zero l’oggetto F
for(i in 1:10000){
x1 = rnorm(25,60,9.2)
x2 = rnorm(25,80,9.2)
F[i] = var(x1)/var(x2) #statistica test (q.tà pivotale)
}
Sovrappongo l’istogramma dei valori F prodotti dalla simulazione a una vera variabile casuale F di
Fisher con gradi di libertà 24 per il numeratore e 24 per il denominatore: l’approssimazione è più
che eccellente.
hist(F, ylim=c(0,1.2),prob=T, main="Istogramma delle simulazioni di
rapporto di varianze su 10000 campioni di ampiezza 25",
breaks=seq(0,7,length=100))
curve(df(x,24,24), add = TRUE) #densità di una v.c. F di Fisher con
g.d.l. 24 per il numeratore e 24 per il denominatore
108
Lo stimatore rapporto di varianze si distribuisce come una variabile F di Fisher con gradi di libertà
pari alla numerosità campionaria meno uno per il numeratore e altrettanti per il denominatore!
3.4 Gli elementi e la filosofia dei test di significatività
Scopo del test: fornire un risultato statistico contro un’ipotesi (congettura) di ricerca data per
forte o assodata; in altri termini, tentare di negare l’ipotesi nulla (dominante… fino a prova
contraria).
Passi:
1) Stabilire la variabile osservata su cui fare il test e una variabile casuale (modello
probabilistico di riferimento) che la governi;
2) Stabilire la o le popolazioni di riferimento su cui è stata osservata la variabile;
3) Specificare il parametro (indice) da indagare;
4) Formulare sul parametro sia l’ipotesi nulla (preponderante fino a prova contraria) che
l’ipotesi alternativa;
5) Stabilire un livello di significatività;
6) Definire una statistica test (o funzione di confronto (perdita) o quantità pivotale); tale
oggetto deve essere funzione del campione e del parametro da indagare ma la sua
distribuzione deve essere nota (tabulata) e non funzione di questi due (cfr. paragrafo
precedente);
7) Appurare lo stimatore (o variabile casuale della statistica test) e la sua distribuzione
(cfr. paragrafo precedente);
8) Definire la regola di decisione per il rifiuto dell’ipotesi nulla: approccio del quantile vs.
approccio del p-value.
109
3.5 Test di significatività parametrici
confidenza
e intervalli di
…da modello probabilistico normale
3.5.1 Sulla media di una variabile casuale normale con  noto (Test Z a un
campione)
Test Z a un campione (esempio di test a due code)
Alcuni ricercatori sono interessati ad ottenere una risposta alla seguente domanda: “è possibile
concludere che l’età media di una certa popolazione d’interesse è uguale a 45 anni?” (Ipotesi nulla
H0).
Passo 1:
età<-c(64, 95, 28, 64, 62, 54, 92, 96, 86, 69, 102, 75, 33, 33, 68, 86,
45, 37, 59, 20, 33, 18, 7, 18, 38, 66, 45, 66, 80, 69, 58, 44, 41, 70,
25, 51, 71, 68, 13, 38)
età ~ N(,2=202) (modello probabilistico di partenza da informazioni preliminari)
Passo 2: una popolazione (“…una certa popolazione d’interesse…”)
Passo 3: 
Passo 4: H0: =45; H1: ≠45 (test a due code: ipotesi alternativa bidirezionale)
Passo 5:  = 0.05
Passo 6: statistica test
Passo 7: Z ~ N(0,1)
Passo 8:
In R:
Calcolo la media campionaria:
mean(età) # 54.675 = media campionaria
110
Calcolo lo z osservato:
z_oss=(mean(età)-45)/(20/sqrt(length(età))); z_oss # 3.059504
Approccio del quantile
Mi calcolo lo z critico a un livello 0.025 (alpha/2) poiché il livello di significatività è ripartito
simmetricamente tra le due code della Normale (0.025 per coda).
z_cri <- qnorm(0.975); z_cri # z(1-alpha/2)= 1.96
Ora grafico la distribuzione dello stimatore per avere chiaro l’oggetto con cui sto operando:
curve(dnorm(x), -4, 4, xlab= "z", ylab="f(z)")
abline(v=-1.96, lty="longdash") #quantile -z(1-alpha/2)
abline(v=1.96, lty="longdash") # quantile z(1-alpha/2)
abline(v=z_oss, lwd=4) #quantile z osservato
abs(z_oss) > z_cri # comando logico: restituisce TRUE o FALSE
regola di decisione => abs(z_oss) > z (1-alpha/2) ?
Nella fattispecie abs(z_oss) è maggiore dello z critico (z(1-alpha/2)) e quindi rifiuto H0
(età media = 45): lo “z” osservato è significativo
Approccio p-value: regola di decisione (soglia del 0.05) => p-value <  ?
p.value <- 2 * (1-pnorm(abs(z_oss)) # moltiplico per due poiché il test è
a due code
111
p.value # 0.0022 < 0.05
Confronto con p=0.05 e pervengo alla stessa decisione: rifiuto H0. Ho una consistente evidenza
contro H0 di =45; In altri termini, data vera H0, la probabilità di ottenere z_oss o addirittura
valori più estremi è "bassa" (0.0022 <0.05) e quindi il valore osservato del test Z (z_oss) è da
considerarsi statisticamente significativo.
Graficamente:
xv<-seq(-4,4,0.01)
yv<-dnorm(xv)
plot(xv,yv,type="l",xlab="z",ylab="f(z)")
polygon(c(xv[xv<=-abs(z_oss)], -abs(z_oss)), c(yv[xv<=abs(z_oss)],yv[xv==-4]), col="red")
polygon(c(xv[xv>=abs(z_oss)],abs(z_oss)),c(yv[xv>=abs(z_oss)],yv[xv==4]),
col="red")
abline(v=-1.96, lty="longdash")
abline(v=1.96, lty="longdash")
abline(v=z_oss, lwd=4) #quantile z osservato
legend(-3.7,0.4,"p value",fill="red")
legend(-3.7,0.35,"p value=0.05",lty=2,bty="n")
112
Test Z a un campione (esempio di test a una coda: coda destra)
Alcuni ricercatori sono interessati ad ottenere una risposta alla seguente domanda: “è possibile
concludere che l’età media di una certa popolazione d’interesse è minore di 45 anni?” (ipotesi nulla
H0).
Passo 1:
età<-c(64, 95, 28, 64, 62, 54, 92, 96, 86, 69, 102, 75, 33, 33, 68, 86,
45, 37, 59, 20, 33, 18, 7, 18, 38, 66, 45, 66, 80, 69, 58, 44, 41, 70,
25, 51, 71, 68, 13, 38)
età ~ N(,2=202) (modello probabilistico di partenza da informazioni preliminari)
Passo 2: una popolazione (“…una certa popolazione d’interesse…”)
Passo 3: 
Passo 4: H0: = 45; H1: ≥ 45 (test a una coda: ipotesi alternativa unidirezionale)
Passo 5:  = 0.05
113
Passo 6: statistica test
Passo 7: Z ~ N(0,1)
Passo 8:
In R:
Calcolo la media campionaria:
mean(età) # 54.675 = media campionaria
Calcolo lo z osservato:
z_oss=(mean(età)-45)/(20/sqrt(length(età))); z_oss # 3.059504
Approccio del quantile
Mi calcolo lo z critico a un livello 0.05 (alpha) poiché il livello di significatività viene collocato
nella zona dell’ipotesi H1, che in questo caso corrisponde alla coda di destra della Normale:
z_cri <- qnorm(0.95); z_cri # z(1-alpha)= 1.644854
Ora grafico la distribuzione dello stimatore per avere chiaro l’oggetto con cui sto operando:
curve(dnorm(x), -4, 4, xlab= "z", ylab="f(z)")
abline(v= 1.644854, lty="longdash") # quantile z(1-alpha)
abline(v=z_oss, lwd=4) #quantile z osservato
114
z_oss > z_cri # comando logico: restituisce TRUE o FALSE
regola di decisione => abs(z_oss) > z (1-alpha) ?
Nella fattispecie abs(z_oss) è maggiore dello z critico (z(1-alpha)) e quindi rifiuto H0 (età
media = 45): lo “z” osservato è significativo.
Approccio p-value: regola di decisione (soglia del 0.05) => p-value <  ?
p.value <- 1-pnorm(z_oss) # NON moltiplico per due poiché il test è a una
coda
p.value # 0.00110852 < 0.05
Confronto con p=0.05 e pervengo alla stessa decisione: rifiuto H0. Ho una consistente evidenza
contro H0: = 45. In altri termini, data vera H0, la probabilità di ottenere z_oss o addirittura valori
più estremi è "bassa" (0.00110852 < 0.05) e quindi il valore osservato del test Z (z_oss) è da
considerarsi statisticamente significativo.
Graficamente:
xv<-seq(-4,4,0.01)
yv<-dnorm(xv)
plot(xv,yv,type="l",xlab="z",ylab="f(z)")
polygon(c(xv[xv>=abs(z_oss)],abs(z_oss)),c(yv[xv>=abs(z_oss)],yv[xv==4]),
col="red")
abline(v=1.644854, lty="longdash")
abline(v=z_oss, lwd=4) #quantile z osservato
legend(-3,0.4,"p value",fill="red")
legend(-3,0.35,"p value=0.05",lty=2,bty="n")
115
Test Z a un campione (esempio di test a una coda: coda sinistra)
Alcuni ricercatori sono interessati ad ottenere una risposta alla seguente domanda: “è possibile
concludere che l’età media di una certa popolazione d’interesse è maggiore di 45 anni?” (ipotesi
nulla H0).
Passo 1:
età<-c(64, 95, 28, 64, 62, 54, 92, 96, 86, 69, 102, 75, 33, 33, 68, 86,
45, 37, 59, 20, 33, 18, 7, 18, 38, 66, 45, 66, 80, 69, 58, 44, 41, 70,
25, 51, 71, 68, 13, 38)
età ~ N(,2=202) (modello probabilistico di partenza da informazioni preliminari)
Passo 2: una popolazione (“…una certa popolazione d’interesse…”)
Passo 3: 
Passo 4: H0: = 45; H1: ≤ 45 (test a una coda: ipotesi alternativa unidirezionale)
Passo 5:  = 0.05
Passo 6: statistica test
Passo 7: Z ~ N(0,1)
Passo 8:
In R:
Calcolo la media campionaria:
mean(età) # 54.675 = media campionaria
Calcolo lo z osservato:
z_oss=(mean(età)-45)/(20/sqrt(length(età))); z_oss # 3.059504
Approccio del quantile
Mi calcolo lo z critico a un livello 0.05 (alpha) poiché il livello di significatività viene collocato
nella zona dell’ipotesi H1, che in questo caso corrisponde alla coda di sinistra della Normale:
z_cri <- qnorm(0.05); z_cri # z(alpha)= -1.644854
116
Ora grafico la distribuzione dello stimatore per avere chiaro l’oggetto con cui sto operando:
curve(dnorm(x), -4, 4, xlab= "z", ylab="f(z)")
abline(v=-1.644854, lty="longdash") #quantile -z(1-alpha)
abline(v=z_oss, lwd=4) #quantile z osservato
z_oss < z_cri # comando logico: restituisce TRUE o FALSE
regola di decisione => z_oss < z (alpha) ?
Nella fattispecie z_oss è maggiore dello z critico (z(alpha)) e quindi non rifiuto H0 (età media
= 45): lo “z” osservato non è significativo
Approccio p-value: regola di decisione (soglia del 0.05) => p-value <  ?
p.value <- pnorm(z_oss) # NON moltiplico per due poiché il test è a una
coda
p.value # 0.9988915 > 0.05
Confronto con p=0.05 e pervengo alla stessa decisione: non rifiuto H0. Non ho nessuna evidenza
contro H0 di = 45; In altri termini, data vera H0, la probabilità di ottenere z_oss o addirittura
valori più estremi è "alta" (0.9988915 > 0.05) e quindi il valore osservato del test Z (z_oss) è da
considerarsi non statisticamente significativo.
Graficamente:
xv<-seq(-4,4,0.01)
yv<-dnorm(xv)
plot(xv,yv,type="l",xlab="z",ylab="f(z)")
117
polygon(c(xv[xv<=abs(z_oss)], abs(z_oss)), c(yv[xv<=abs(z_oss)],yv[xv==4]), col="red")
abline(v=-1.644854, lty="longdash")
abline(v=z_oss, lwd=4) #quantile z osservato
legend(1,0.4,"p value",fill="red")
legend(1,0.35,"p value=0.05",lty=2,bty="n")
Intervalli di confidenza (IC)
Esempio:
Fissiamo un livello di confidenza pari 0.95 = 1 - 
Calcolo il 97.5° percentile poiché il 5% (), complemento a 100 del livello di confidenza, è ripartito
sulle code simmetriche in due parti uguali di 2,5%.
qnorm(0.975) # 1.959964 (= a z_critico di prima)
se=20/sqrt(length(età)); se # 3.162278
L1<- mean(età)- 1.959964*se
L2<- mean(età)+ 1.959964*se
cat("95%CI Media = ", L1, L2, "\n")
95%CI Media =
48.47705 60.87295
118
Con una probabilità del 95% la vera età media della popolazione è contenuta nell’intervallo di
valori compreso tra 48 e 61 anni, ovvero con un livello di confidenza del 95% si considera
verosimile che l’età media sia compresa tra 48 e 61 anni (interpretazione di Fisher). In altri termini,
replicando l’esperimento un numero elevato di volte, circa il 95% degli intervalli di confidenza
osservati dovrebbe contenere il vero valore del parametro μ (interpretazione frequentista di
Neyman); Inoltre, grazie alla dualità tra i test e gli IC tutti i valori di 0 che sono compresi
nell’intervallo non sono rifiutati da un test di significatività a due code (al 5% =livello di
significatività, complemento a 100 del livello di confidenza); quindi, siccome il 45 dell’ipotesi nulla
non è contenuto, già dall’IC 95% posso rifiutare H0:=45 senza fare il test (infatti il p-value era
<0,05 e avevo una consistente evidenza contro H0).
Corollario su IC
Ora verifichiamo empiricamente l’interpretazione frequentista di Neyman dell’intervallo di
confidenza; prima si era detto che replicando l’esperimento un numero elevato di volte, circa il 95%
(poiché quello è il livello di confidenza dai fissato a priori) degli intervalli di confidenza osservati
avrebbe contenuto il vero valore del parametro μ (probabilità di copertura). Per verificare tale
proposizione si può ricorrere a una simulazione per valutare il livello di copertura effettivo di un
intervallo di confidenza appunto di livello 0,95. Chiaramente la simulazione avverrà sul parametro
m oggetto di indagine.
Le seguenti istruzioni sono necessarie per generare 1000 campioni simulati, su cui calcolare gli
intervalli di confidenza di cui memorizzerò gli estremi nella matrice mu.ic di 1000 righe (numero
dei campioni simulati) e 2 colonne (gli estremi dell’IC per ogni campione):
1) età ~ N(,2=202) (modello probabilistico di partenza da informazioni preliminari)
2) Numerosità di ogni campione: 40
3) Livello di confidenza = 95%
Inizializzo a zero la matrice mu.ic che conterrà tutti gli estremi degli IC (livello di confidenza
=0.95)
mu.ic = matrix(0, ncol = 2, nrow = 1000)
…e poi faccio la simulazione
for (i in 1:1000) {
n = 40
x = rnorm(n, mean = 50, sd = 20)
mu = mean(x)
mu.lower = mu - qnorm(0.975)*20/sqrt(n)
mu.upper = mu + qnorm(0.975)*20/sqrt(n)
mu.ic[i,1] = mu.lower
mu.ic[i,2] = mu.upper
}
Verifico che la probabilità di copertura sia molto prossima a 0.95 (95%)
mean((mu.ic[,1] <= 50) & (mu.ic[,2] >= 50))
119
E rappresento un estratto di ciò graficamente (estraggo solo 100 IC 95% sui 1000 simulati)
ESTR<-sample(1:1000, 100, replace = FALSE)
plot(mu.ic[ESTR,1], 1:100, xlim=c(30,70), xlab = "età media (mu)", ylab =
"campioni simulati", cex=0.6)
points(mu.ic[ESTR,2],1:100, , cex=0.6)
segments(mu.ic[ESTR,1],1:100,mu.ic[ESTR,2],1:100)
abline(v = 50, col = 2)
MODO "AUTOMATICO" PER AVERE TEST E IC
install.packages("BSDA") #installo il pacchetto "BSDA" (Basic Statistics
and Data Analysis)
library(BSDA) #carico il pacchetto appena installato
z.test(età, mu = 45, sigma.x = 20, alternative = "two.sided", conf.level = 0.95)
One-sample z-Test
data: età
z = 3.0595, p-value = 0.002217
alternative hypothesis: true mean is not equal to 45
95 percent confidence interval:
48.47705 60.87295
sample estimates:
mean of x
54.675
Quindi in R, la regola decisionale per i test “rifiuto/non rifiuto” segue l’approccio del p-value!
120
Altro esempio: stesso test ma cambio l’ipotesi nulla ovvero modifico il passo 4
Passo 4: H0: =45; H1: ≥45 (test a una coda: ipotesi alternativa unidirezionale)
z.test(età, mu = 45, sigma.x = 20, alternative = "greater", conf.level = 0.95)
One-sample z-Test
data: età
z = 3.0595, p-value = 0.001109
alternative hypothesis: true mean is greater than 45
95 percent confidence interval:
49.47352
NA
sample estimates:
mean of x
54.675
Altro esempio: stesso test ma cambio l’ipotesi nulla ovvero modifico solo il passo 4
Passo 4: H0: =45; H1: ≤45 (test a una coda: ipotesi alternativa unidirezionale)
z.test(età, mu = 45, sigma.x = 20, alternative = "less", conf.level = 0.95)
One-sample z-Test
data: età
z = 3.0595, p-value = 0.9989
alternative hypothesis: true mean is less than 45
95 percent confidence interval:
NA 59.87648
sample estimates:
mean of x
54.675
Ora vedremo esempi degli altri test di significatività solo mediante il modo automatico…per
velocizzare le cose!!!
121
3.5.2 Sulla media di una variabile casuale normale con  ignoto (Test T a un
campione)
Modello probabilistico di partenza da informazioni preliminari
età ~ N(,2), test a due code, ipotesi uguali a quelle di prima, livello di confidenza=0.90)
t.test(età, mu = 45, alternative = "two.sided", conf.level=0.9)
One Sample t-test
data: età
t = 2.4647, df = 39, p-value = 0.01822
alternative hypothesis: true mean is not equal to 45
90 percent confidence interval:
48.06104 61.28896
sample estimates:
mean of x
54.675
Per i test unidirezionali (a una coda) i comandi sono analoghi al test spiegato al punto a) mutatis
mutandis.
3.5.3 Sulla differenza tra medie di due variabili casuali normali con  noti e
uguali (Test Z per due campioni indipendenti)
Modello probabilistico di partenza da informazioni preliminari
età maschi ~ N(,2=202); età femmine ~ N(,2=202)
età<-c(64, 95, 28, 64, 62, 54, 92, 96, 86, 69, 102, 75, 33, 33, 68, 86,
45, 37, 59, 20, 33, 18, 7, 18, 38, 66, 45, 66, 80, 69, 58, 44, 41, 70,
25, 51, 71, 68, 13, 38)
età.maschi<-età[1:20]; età.maschi
[1] 64 95
37 59 20
28
64
62
54
92
96
86
69 102
75
33
33
68
86
45
età.femmine<-età[21:40]; età.femmine
[1] 33 18
7 18 38 66 45 66 80 69 58 44 41 70 25 51 71 68 13 38
mean(età.maschi) # 63.4
mean(età.femmine) # 45.95
mean(età.maschi) - mean(età.femmine) # 17.45
122
z.test(età.maschi,età.femmine, mu=0, sigma.x=20, sigma.y=20, alternative
= "two.sided")
Two-sample z-Test
data: età.maschi and età.femmine
z = 2.7591, p-value = 0.005796
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
5.054099 29.845901
sample estimates:
mean of x mean of y
63.40
45.95
3.5.4 Sulla differenza tra medie di due variabili casuali normali con  ignoti ma
uguali (Test T per due campioni indipendenti)
Modello probabilistico di partenza da informazioni preliminari
età maschi ~ N(,2); età femmine ~ N(,2)
t.test(età.maschi, età.femmine, mu = 0, alternative = "two.sided",
var.equal = TRUE)
Two Sample t-test
data: età.maschi and età.femmine
t = 2.3477, df = 38, p-value = 0.0242
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
2.403057 32.496943
sample estimates:
mean of x mean of y
63.40
45.95
3.5.5 Sulla differenza tra medie di due variabili casuali normali con  ignoti e
diversi (Test T per due campioni indipendenti)
Modello probabilistico di partenza da informazioni preliminari
età maschi ~ N(,2); età femmine ~ N(,2)
t.test(età.maschi, età.femmine, mu = 0, alternative = "two.sided",
var.equal = FALSE)
123
Welch Two Sample t-test
data: età.maschi and età.femmine
t = 2.3477, df = 37.5, p-value = 0.02427
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
2.396467 32.503533
sample estimates:
mean of x mean of y
63.40
45.95
3.5.6 Sulla differenza tra medie di due variabili casuali normali con  ignoti ma
uguali (Test T per due campioni appaiati)
Modello probabilistico di partenza da informazioni preliminari
PAD 0 (prima) ~ N(,2); PAD 1 (dopo) ~ N(,2)
pressione<- read.csv2(file.choose(), sep=";", dec=",", header = T)
#importo il file pressione.csv
attach(pressione)
mean(PAD[gruppo==0]); mean(PAD[gruppo==1])
[1] 126.1
[1] 133.1
t.test(PAD~gruppo, mu = 0, alternative = "two.sided", paired=T)
Paired t-test
data: PAD by gruppo
t = -0.6058, df = 9, p-value = 0.5596
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-33.14072 19.14072
sample estimates:
mean of the differences
-7
Alternativamente
t.test(PAD[gruppo==0], PAD[gruppo==1], mu = 0, alternative = "two.sided",
paired=T)
124
Paired t-test
data: PAD[gruppo == 0] and PAD[gruppo == 1]
t = -0.6058, df = 9, p-value = 0.5596
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-33.14072 19.14072
sample estimates:
mean of the differences
-7
3.5.7 Sul rapporto di varianze di due variabili casuali normali (Test F per due
campioni indipendenti)
Modello probabilistico di partenza da informazioni preliminari
età maschi ~ N(,2); età femmine ~ N(,2)
var.test(età.maschi, età.femmine, ratio = 1, alternative = "two.sided")
F test to compare two variances
data: età.maschi and età.femmine
F = 1.2611, num df = 19, denom df = 19, p-value = 0.6182
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.4991395 3.1859847
sample estimates:
ratio of variances
1.261051
3.6 Test di significatività da modello probabilistico non
Normale
Test di significatività mediante approssimazione normale (n > 30)
3.6.1 Su una proporzione (Test Z su proporzione)
Passo 1: XpiomboSI~Be(ppiomboSI)
continua!)
(≠ XpiomboSI~N(,2) !) e XpiomboSI osservata dicotomica (non
Passo 4: H0: ppiomboSI ≥ 0.15; H1: ppiomboSI < 0.15 (test a una coda: ipotesi alternativa unidirezionale)
Grazie al teorema centrale del limite (versione DeMoivre-Laplace) posso applicare il test Z
prop.test(25, 250, p=0.15, alternative="less", correct=F)
125
1-sample proportions test without continuity correction
data: 25 out of 250, null probability 0.15
X-squared = 4.902, df = 1, p-value = 0.01341
alternative hypothesis: true p is less than 0.15
95 percent confidence interval:
0.0000000 0.1356179
sample estimates:
p
0.1
Il commando di R in cui è implementato questo test (e il successivo) restituisce un valore osservato
di statistica test in scala 2 (X-squared). Tuttavia grazie alla corrispondenza biunivoca 21gdl = Z
facendo appunto la radice quadrata di quel valore è possibile ottenere il quantile z osservato proprio
come spiegato nelle lezioni teoriche.
sqrt(4.902) # = z osservato
3.6.2 Sulla differenza di due proporzioni (Test Z su differenza di proporzioni)
Passo 1: XPSAalto~Be(palto) e XPSAbasso~Be(pbasso) (≠ X~N(,2) !) e XPSAalto e XPSABasso osservate
dicotomiche (non continue!)
Passo 4: H0: palto ≤ pbasso, cioè palto – pbasso ≤ 0; H1: palto > pbasso, cioè palto – pbasso > 0 (test a una coda:
ipotesi alternativa unidirezionale)
Grazie al teorema centrale del limite (versione DeMoivre-Laplace) posso applicare il test Z
Tab<-matrix(c(46, 10, 21, 47), nrow=2, ncol=2, dimnames=
list(c("PSA alto", "PSA basso"), c("malati", "sani"))); Tab
malati sani
PSA alto
46
21
PSA basso
10
47
prop.test(Tab, alternative = "greater", correct=F)
2-sample test for equality of proportions without continuity
correction
data: Tab
X-squared = 32.4889, df = 1, p-value = 5.994e-09
alternative hypothesis: greater
95 percent confidence interval:
0.3864044 1.0000000
sample estimates:
prop 1
prop 2
0.6865672 0.1754386
Le proporzioni vengono calcolate per riga (46/67=0.6865, 10/57=0.1754) e quindi il test
implementato in R considera le variabili casuali disposte appunto per riga e i “successi” (malati
nella fattispecie) collocati nella prima colonna.
126
Alternativamente, cambiando le modalità di inserimento…
Malati_per_PSA=c(46,10)
totali=c(67,57)
prop.test(x = Malati_per_PSA, n = totali, alternative = "greater",
correct=F)
2-sample test for equality of proportions without continuity
correction
data: Malati_per_PSA out of totali
X-squared = 32.4889, df = 1, p-value = 5.994e-09
alternative hypothesis: greater
95 percent confidence interval:
0.3864044 1.0000000
sample estimates:
prop 1
prop 2
0.6865672 0.1754386
Oppure ancora…definendo dapprima i valori di cella, creando quindi due vettori e da questi la
tavola di contingenza 2x2 su cui applicare il test
a<-46;
b<-21;
c<-10;
d<-47;
a
b
c
d
PSA<-c(rep("PSA Alto",a),rep("PSA Alto",b),rep("PSA Basso",c),rep("PSA
Basso",d))
status<-c(rep("malati",a),rep("sani",b),rep("malati",c),rep("sani",d))
table(PSA,status)
PSA alto
PSA basso
malati sani
46
21
10
47
prop.test(table(PSA,status), alternative = "two.sided", correct=F)
2-sample test for equality of proportions without continuity
correction
data: table(PSA, status)
X-squared = 32.4889, df = 1, p-value = 1.199e-08
alternative hypothesis: two.sided
95 percent confidence interval:
0.3625105 0.6597466
sample estimates:
prop 1
prop 2
0.6865672 0.1754386
127
Test di significatività per l’associazione di due fenomeni
3.6.3 Test di indipendenza
Passo 1: Xm~Be(pm) e Xf~Be(pf) (≠ X~N(,2) !) e Xm e Xf osservate dicotomiche (non continue!)
N.B.: Frequenze attese > 5
Esempio
Passo 4: H0: pm = pf ; H1: pm ≠ pf (test a due code: ipotesi alternativa bidirezionale)
Fenomeni: daltonismo e sesso
Costruiamo il test “manualmente”:
#Frequenze osservate
a1<-38 #daltonici maschi
b1<-6 #daltonici femmine
c1<-442 #non daltonici maschi
d1<-514 #non daltonici femmine
obs1<-matrix(c(a1, c1, b1, d1), nrow=2, ncol=2, dimnames=
list(c("daltonici", "normali"), c("maschi", "femmine"))); obs1
daltonici
normali
maschi femmine
38
6
442
514
#Frequenze attese
n1<-a1+b1+c1+d1
ea1<-(a1+b1)*(a1+c1)/n1
eb1<-(a1+b1)*(b1+d1)/n1
ec1<-(c1+d1)*(a1+c1)/n1
ed1<-(c1+d1)*(b1+d1)/n1
exp1<-matrix(c(ea1, ec1, eb1, ed1), nrow=2, ncol=2, dimnames=
list(c("daltonici", "normali"), c("maschi", "femmine"))); exp1
maschi femmine
daltonici 21.12
22.88
normali
458.88 497.12
#test X2
x2<- sum((obs1-exp1)^2/exp1); x2 # x2 osservato = 27.13874
px2 <- 2*(1-pnorm(sqrt(x2))); px2 # p-value = 1.893646e-07
128
Rifiutiamo H0
Alternativamente e automaticamente… :
chisq.test(obs1, correct=F)
Pearson's Chi-squared test
data: obs1
X-squared = 27.1387, df = 1, p-value = 1.894e-07
Test di significatività non parametrici
3.6.4 Sull’uguaglianza di due variabili casuali (Test U di Mann-Whitney)
attraverso le mediane (X0.5)
Passo 1: XE~??? e XNe~??? (XE e XNe ≠ ~N(,2) !) e XE e XNe osservate numeriche; n<30.
Passo 4: H0: XE)=XNe) → EX0.5=NeX0.5; H1: EX0.5 ≠
bidirezionale)
NeX0.5
(test a due code: ipotesi alternativa
Esposti<-c(14.4, 14.2, 14.8, 14.5, 14.1, 16.6, 14.9, 15.6, 14.1, 15.3,
15.7, 14.4, 14.7, 14.3, 19)
Non_esposti<- c(17.4, 16.2, 17.1, 17.5, 12, 16, 16.9, 13.5, 16.3, 16.8)
Per eseguire questo test è necessario installare e caricare il pacchetto exactRankTests:
install.packages("exactRankTests")
library(exactRankTests)
Il commando wilcox.exact applica il test
wilcox.exact(Esposti, Non_esposti)
Exact Wilcoxon rank sum test
data: Esposti and Non_esposti
W = 41, p-value = 0.06016
alternative hypothesis: true mu is not equal to 0
129
3.6.5 Sulla normalità di una distribuzione (Test di Shapiro-Wilk)
Passo 1: X~??? (≠ X~N(,2) ?) e X osservata numerica
Passo 4: H0: X)= N(,2); H1: X) ≠ N(,2) (test a due code: ipotesi alternativa bidirezionale)
shapiro.test(Non_esposti)
Shapiro-Wilk normality test
data: Non_esposti
W = 0.7814, p-value = 0.008621
130
Esercitazione 2
Test di significatività e intervalli di confidenza
Esercizio 1
Importare in R il dataset del file altezze.csv relativo alla statura (in cm) di un campione
costituito da 90 studenti di una scuola media superiore e risolvere i seguenti punti:
a) verificare la normalità della distribuzione della variabile Altezza nella popolazione di
riferimento,
b) conoscendo la varianza della variabile Altezza nella popolazione di riferimento (2 = 25
cm2), è possibile affermare con una confidenza del 95% che la statura media degli studenti delle
scuole medie superiori è uguale a 170 cm?
c) non conoscendo la varianza della variabile Altezza nella popolazione di riferimento, è
possibile affermare con una confidenza del 90% che la statura media degli studenti delle scuole
medie superiori è uguale a 170 cm?
Soluzione:
Importo in R il dataset del file altezze.csv, visualizzo le etichette delle variabili ed eseguo
l’attach():
altezze <- read.csv2 (file.choose(), header = T)
colnames (altezze)
attach (altezze)
Punto a:
Verifico la normalità della distribuzione della variabile Altezza nella popolazione di riferimento
mediante il test di Shapiro-Wilk:
H0: X)= N(,2); H1: X) ≠ N(,2)
shapiro.test(Altezza)
Shapiro-Wilk normality test
data: Altezza
W = 0.9841, p-value = 0.3406
p=0.3406>0.05: non posso rifiutare H0: la variabile è distribuita normalmente.
131
Punto b:
Dovendo fare inferenza statistica sulla media () di una variabile casuale normale con 2 noto e
disponendo dei dati rilevati su un singolo campione, applico il comando del test Z a un campione,
con: H0: = 170 cm; H1: ≠ 170 cm (test a due code: ipotesi alternativa bidirezionale) per
ottenere l’IC 95% necessario a risolvere l’esercizio.
install.packages("BSDA") # Installo il pacchetto "BSDA" (Basic Statistics
and Data Analysis)
library(BSDA) # Carico il pacchetto appena installato
z.test(Altezza, mu = 170, sigma.x = 5, alternative = "two.sided", conf.level =
0.95)
One-sample z-Test
data: Altezza
z = 9.9085, p-value < 2.2e-16
alternative hypothesis: true mean is not equal to 170
95 percent confidence interval:
174.1892 176.2552
sample estimates:
mean of x
175.2222
Il valore 170 (cm) non ricade nell’IC 95% (174.189; 176.255) e quindi non è una stima verosimile
per la statura media degli studenti delle scuole medie superiori. Inoltre ho una decisiva evidenza
contro H0: Altezza = 170 cm (p<0.001) e quindi rifiuto l’ipotesi nulla in un test a due code.
Punto c:
Dovendo fare inferenza statistica sulla media () di una variabile casuale normale con 2 ignoto e
disponendo dei dati rilevati su un singolo campione, applico il comando del test T a un campione, con:
H0: = 170 cm; H1: ≠ 170 cm (test a due code: ipotesi alternativa bidirezionale) per ottenere
l’IC 90% necessario a risolvere l’esercizio.
t.test(Altezza, mu = 170, alternative = "two.sided", conf.level = 0.90)
One Sample t-test
data: Altezza
t = 9.943, df = 89, p-value = 4.198e-16
alternative hypothesis: true mean is not equal to 170
90 percent confidence interval:
174.3492 176.0952
sample estimates:
mean of x
175.2222
132
Il valore 170 (cm) non ricade nell’IC 90% (174.35; 176.095) e quindi non è una stima verosimile
per la statura media degli studenti delle scuole medie superiori. Inoltre ho una decisiva evidenza
contro H0: Altezza = 170 cm (p<0.001) e quindi la rifiuto in un test a due code.
detach (altezze)
133
Esercizio 2
Importare in R il dataset del file stroke in young.txt e risolvere i seguenti punti:
a) è possibile affermare che esiste un’associazione significativa tra il fumo di tabacco e
l’ipertensione arteriosa?
b) è possibile affermare con un livello confidenza del 99% che nella popolazione di riferimento le
fumatrici donne sono pari al 20%?
c) benché non ci siano evidenze in letteratura, è possibile affermare che nella popolazione di
riferimento i fumatori hanno una probabilità maggiore di manifestare ipercolesterolemia rispetto
ai non fumatori?
Informazioni supplementari per l’esercizio 2:
Legenda delle variabili presenti nel dataset:
Id = id code;
cc = condizione di salute [1 = malato, 0 = sano];
sex = sesso [1 = maschi, 2 = femmine];
age = età in anni;
bmi = Body Mass Index (BMI) in Kg/m2;
hyp = ipertensione arteriosa [1 = NO, 2 = SI];
dm = diabete mellito [1 = NO, 2 = SI];
smoke = fumatore [1 = NO, 2 = SI];
hypercho = ipercolesterolemia [1 = NO, 2 = SI];
ii = fattore II G20210A [1 = GG, 2 = GA, 3 = AA];
v = fattore V G1691A [1 = NO, 2 = SI];
MTHFR = gene MTHFR [1 = CC, 2 = CT, 3 = TT];
APOE = gene APOE [diviso per categorie].
Soluzione:
Importo in R il dataset del file stroke in young.txt, visualizzo i dati e le etichette delle
variabili ed eseguo l’attach():
dati <- read.table (file.choose(), sep = "", header = TRUE, dec = ".",
na.strings = ".")
colnames(dati) # Ricavo i nomi delle variabili del dataset importato.
attach(dati) # Accedo alle variabili digitando il loro nome.
Punto a:
Comunico al software la natura qualitativa delle variabili oggetto di studio (essendo codificate
numericamente, sono di default riconosciute da R come quantitative anche se per il ricercatore non
lo sono):
HYP <- factor(hyp) # Considero la variabile hyp come qualitativa e le
assegno il nome HYP.
134
SMOKE <- factor(smoke) # Considero la variabile smoke come qualitativa e
le assegno il nome SMOKE.
Le variabili considerate sono qualitative dicotomiche. Per testarne la significatività
dell’associazione, bisogna applicare il test di significatività per l’associazione di due fenomeni
(test di indipendenza), con: H0: phyp=SI|smoke=SI = phyp=SI|smoke=NO; H1: phyp=SI|smoke=SI ≠
phyp=SI|smoke=NO (test a due code: ipotesi alternativa bidirezionale).
Innanzitutto è necessario creare un oggetto contenente la tabella 2×2 delle due variabili in esame:
Tabella <- table (SMOKE, HYP); Tabella
HYP
SMOKE
1
1 194
2 96
2
16
21
Eseguo quindi il test di indipendenza:
chisq.test (Tabella, correct = F)
Pearson's Chi-squared test
data: Tabella
X-squared = 7.9896, df = 1, p-value = 0.004705
Ho una consistente evidenza contro H0 (p=0.005<0.05): phyp=SI|smoke=SI = phyp=SI|smoke=NO, per cui
rifiuto l’ipotesi nulla H0 e affermo che esiste un’associazione significativa tra il fumo e
l’ipertensione arteriosa.
Punto b:
Comunico al software la natura qualitativa delle variabili oggetto di studio (essendo codificate
numericamente, sono di default riconosciute da R come quantitative anche se per il ricercatore non
lo sono):
SEX <- factor(sex) # Considero la variabile sex come qualitativa e le
assegno il nome SEX.
Tabulo le due variabili considerate:
addmargins (table (SEX, SMOKE))
SEX
1
2
Sum
SMOKE
1
2
91 78
119 39
210 117
Sum
169
158
327
Il comando addmargins() aggiunge le frequenze marginali alla tabella.
Le fumatrici femmine sono 39 su un totale di 158 femmine presenti nel campione.
135
Dovendo fare inferenza su una proporzione (pfumatrici.femmine) ed essendo la numerosità campionaria >
30 soggetti, posso calcolare mediante approssimazione normale, un IC 90% su proporzione
che sarà associato a un test Z con: H0: pfumatrici.femmine =  ; H1: pfumatrici.femmine ≠  (test a due code:
ipotesi alternativa bidirezionale).
prop.test (39, 158, p = 0.20, alternative = "two.sided", correct = F,
conf.level = 0.99)
1-sample proportions test without continuity correction
data: 39 out of 158, null probability 0.2
X-squared = 2.1661, df = 1, p-value = 0.1411
alternative hypothesis: true p is not equal to 0.2
99 percent confidence interval:
0.1698814 0.3441949
sample estimates:
p
0.2468354
La probabilità 0.20 ricade nell’IC 90% (0.169; 0.344) e quindi è una stima verosimile per la
proporzione di donne fumatrici nella popolazione. Inoltre non ho evidenza contro H0: pfumatrici.femmine
=  (p=0.141>0.05) e quindi non la posso rifiutare in un test a due code.
Punto c:
Comunico al software la natura qualitativa delle variabili oggetto di studio (essendo codificate
numericamente, sono di default riconosciute da R come quantitative anche se per il ricercatore non
lo sono):
HYPERCO <- factor(hypercho) # Considero
qualitativa e le assegno il nome HYPERCO.
la
variabile
hypercho
come
Creo un oggetto contenente la tabella 2×2 delle due variabili in esame:
Tabella <- table (SMOKE, HYPERCO); Tabella
HYPERCO
SMOKE
1
2
1 166 44
2 84 33
Su 77 ipercolesterolemici presenti nel campione, 33 sono fumatori e 44 sono non fumatori.
Dovendo fare inferenza sulla differenza di due proporzioni (pfumatori – pnon.fumatori) ed essendo la
numerosità campionaria > 30 soggetti, posso eseguire un test di significatività mediante
approssimazione normale e precisamente un test Z su differenza di proporzioni, con: H0: pfumatori –
pnon.fumatori =  ; H1: pfumatori – pnon.fumatori ≠  (test a due code: ipotesi alternativa bidirezionale).
prop.test (Tabella, alternative = "two.sided", correct = F)
136
2-sample test for equality of proportions without continuity
correction
data: Tabella
X-squared = 2.1955, df = 1, p-value = 0.1384
alternative hypothesis: two.sided
95 percent confidence interval:
-0.02585098 0.17090593
sample estimates:
prop 1
prop 2
0.7904762 0.7179487
Non ho nessuna evidenza contro H0 (p=0.1384>0.05): pfumatori – pnon.fumatori = per cui non rifiuto
H0 e quindi non posso affermare che i fumatori hanno una probabilità maggiore di manifestare
ipercolesterolemia (benché nel campione tale probabilità era maggiore: 0.28 (1-0.72) vs. 0.21 (10.79))
detach (dati)
137
Esercizio 3
Importare in R il dataset del file Metabolismo.csv e risolvere i seguenti punti:
a) dopo aver controllato se la variabilità della colesterolemia totale tra i fumatori è uguale a quella
tra i non fumatori, sapendo che i livelli medi di colesterolemia totale tra i primi non sono mai
minori, verificare se sono più alti. La variabile coltot segue una distribuzione normale in
entrambe le popolazioni di riferimento,
b) verificare se gli uomini che praticano attività fisica hanno una glicemia media diversa di quella
degli uomini che non la praticano. La variabile glicemia segue una distribuzione normale
con 2 = 169 mg2/dl2 in entrambe le popolazioni di riferimento. Fornire quindi un IC 95% e la
sua interpretazione,
c) è raro che le donne abbiano una colesterolemia HDL media più bassa di quella degli uomini. E’
possibile affermare che la colesterolemia HDL media delle donne è più alta? La variabile HDL
segue una distribuzione normale con 2 ignote e diverse in entrambe le popolazioni di
riferimento. Calcolare quindi un intervallo di confidenza al 99% e da questo decidere se è
possibile rifiutare un’ipotesi nulla H0: HDLdonne - HDLuomini = 3 mg/dl (formulare una ipotesi
alternativa H1 bidirezionale) a un livello di significatività dell’1%.
N.B. = i valori mancanti nel dataset sono codificati con n.n.
Informazioni supplementari per l’esercizio 3:
Legenda delle variabili presenti nel dataset:
id = codice identificativo personale;
azienda = azienda per cui ogni soggetto lavora;
sesso = sesso [M = maschi, F = femmine];
età = età in anni;
peso = peso in Kg;
altezza = altezza in cm;
BMI = Body Mass Index (BMI) in Kg/m2;
esiti.BMI = valutazione del BMI [Sottopeso, Normopeso, Sovrappeso, Obeso];
addome = circonferenza addominale in cm;
PAS = pressione arteriosa sistolica in mmHg;
PAD = pressione arteriosa diastolica in mmHg;
glicemia = glicemia in mg/dl;
insulinemia = insulinemia in mU/l;
tgl = trigliceridemia in mg/dl;
coltot = colesterolemia totale in mg/dl;
HDL = colesterolemia HDL in mg/dl;
LDL = colesterolemia LDL in mg/dl;
uricemia = uricemia in mg/dl;
PCR = Proteina C Reattiva in mg/dl;
fumo = fumo [Sì, No];
attività.fisica = attività fisica [Sì, No];
diabete.mellito = diabete mellito [Sì, No].
138
Soluzione:
Importo in R il dataset del file Metabolismo.csv, visualizzo i dati e le etichette delle variabili:
Metabolismo <- read.csv2 (file.choose(), sep = ";", dec = ".", header =
T, na.strings = "n.n.")
head(Metabolismo)
colnames(Metabolismo)
importato
#
Ricavo
i
nomi
delle
variabili
del
dataset
attach(Metabolismo)
summary(Metabolismo[,2:22]) #statistiche di sintesi in maniera compatta,
leggerle “con buon senso”
Punto a:
Dovendo fare inferenza statistica sulla variabilità del colesterolo per valutarne l’equivalenza nelle
due popolazioni (fumatori e non), applico il test F per due campioni indipendenti, con: H0:
fumatorinon.fumatori= 1; H1: fumatorinon.fumatori≠ 1 (test a due code: ipotesi alternativa
biderezionale).
Dapprima rendo logica la variabile fumo: assegno 1 alla categoria non fumatori e 0 alla fumatori:
in questo modo la modalità 0 sarà sempre considerata “prima”, es. al numeratore del rapporto di
varianze o come primo membro nella differenza di medie.
FUMO<-1*(fumo=="No")
var.test (coltot~FUMO, ratio = 1, alternative = "two.sided")
F test to compare two variances
data: coltot by FUMO
F = 1.0726, num df = 566, denom df = 1719, p-value = 0.2984
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
0.9398417 1.2297627
sample estimates:
ratio of variances
1.072592
Verifico il valore del rapporto:
var(coltot[fumo=="Sì"],na.rm=T) / var(coltot[fumo=="No"], na.rm=T)
Comunque, in ogni caso, non ho nessuna evidenza (p=0.2984>0.05) contro H0:
fumatorinon.fumatori= 1, per cui non rifiuto l’ipotesi nulla H0 e considero le due varianze uguali.
139
Ora, dovendo fare inferenza statistica sulla differenza tra medie (fumatorinon.fumatori) di due
variabili casuali normali con 2 ignote ma uguali (appena verificato) e disponendo dei dati rilevati
su due campioni, applico il test T per due campioni indipendenti, con: H0: fumatorinon.fumatori= 0
mg/dl; H1: fumatorinon.fumatori> 0 mg/dl (test a una coda: ipotesi alternativa unidirezionale).
t.test (coltot~FUMO, mu = 0, var.equal = TRUE, alternative = "greater")
Two Sample t-test
data: coltot by FUMO
t = 0.6027, df = 2285, p-value = 0.2734
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
-1.792548
Inf
sample estimates:
mean in group 0 mean in group 1
200.3069
199.2709
Anche qui non ho nessuna evidenza (p=0.2734>0.05) contro H0: fumatorinon.fumatori= 0 mg/dl, per
cui non rifiuto l’ipotesi nulla H0 e quindi il livello medio di colesterolo tra i fumatori non è
significativamente più alto.
Punto b:
Creo due sottoinsiemi del dataset Metabolismo, ognuno dei quali corrisponde a una delle due
popolazioni di riferimento:
maschi.sportivi <- subset (Metabolismo, (Metabolismo$sesso == "M") &
(Metabolismo$attività.fisica == "Sì")) # uomini che praticano attività
fisica.
maschi.sedentari <- subset (Metabolismo, (Metabolismo$sesso == "M") &
(Metabolismo$attività.fisica == "No")) # uomini che non praticano
attività fisica.
Dovendo fare inferenza statistica sulla differenza tra medie (uomini.sportiviuomini.sedentari) di due
variabili casuali normali con 2 note e uguali e disponendo dei dati rilevati su due campioni, applico
il test Z per due campioni indipendenti, con: H0: maschi.sportivimaschi.sedentari= 0 mg/dl; H1:
uomini.sportiviuomini.sedentari≠ 0 mg/dl (test a due code: ipotesi alternativa bidirezionale).
library (BSDA) # Carico il pacchetto BSDA
z.test (maschi.sportivi$glicemia, maschi.sedentari$glicemia, mu = 0,
sigma.x = 13, sigma.y = 13, alternative = "two.sided", conf.level = 0.95)
140
Two-sample z-Test
data: maschi.sportivi$glicemia and maschi.sedentari$glicemia
z = -2.0855, p-value = 0.03702
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-2.95835258 -0.09181371
sample estimates:
mean of x mean of y
84.51705 86.04213
Ho una moderata evidenza (P= 0.037<0.05) contro H0: uomini.sportiviuomini.sedentari= 0 mg/dl, per
cui rifiuto l’ipotesi nulla H0. I livelli medi di glicemia nelle due popolazioni non sono
significativamente diversi.
Punto c:
Dapprima rendo logica la variabile sesso: assegno 1 alla categoria uomini e 0 alle donne: in
questo modo la modalità 0 sarà sempre considerata “prima”, es. al numeratore del rapporto di
varianze o come primo membro nella differenza di medie.
SESSO<-1*(sesso=="M")
Dovendo fare inferenza statistica sulla differenza tra medie (donneuomini) di due variabili casuali
normali con 2 ignote e diverse e disponendo dei dati rilevati su due campioni, applico il test T per
due campioni indipendenti, con: H0: donneuomini= 0 mg/dl; H1: donneuomini> 0 mg/dl (test a
una coda: ipotesi alternativa unidirezionale).
t.test (HDL~SESSO, mu = 0, var.equal = FALSE, alternative = "greater",
conf.level = 0.95)
Welch Two Sample t-test
data: HDL by SESSO
t = 23.463, df = 1367.54, p-value < 2.2e-16
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
12.23658
Inf
sample estimates:
mean in group 0 mean in group 1
62.88550
49.72573
Ho una decisiva evidenza (p<0.001) contro H0: donneuomini= 0 mg/dl, per cui rifiuto l’ipotesi
nulla H0. I livelli di colesterolemia HDL sono significativamente più alti nelle donne.
Calcolo ora l’intervallo di confidenza la 99%.
t.test (HDL~SESSO, mu = 0, var.equal = FALSE, alternative = "two.sided",
conf.level = 0.99)
141
Welch Two Sample t-test
data: HDL by SESSO
t = 23.463, df = 1367.54, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
99 percent confidence interval:
11.71303 14.60650
sample estimates:
mean in group 0 mean in group 1
62.88550
49.72573
Con un livello di confidenza del 99% è verosimile affermare che le donne hanno un livello di
colesterolemia HDL maggiore degli uomini e che tale differenza va da 11.71303 mg/dl a 14.6065
mg/dl. In altri termini, c’è una probabilità del 99% che l’intervallo di valori da 11.71303 mg/dl a
14.6065 mg/dl contenga la vera medie delle differenza.
Inoltre siccome il valore di H0=3 non è contenuto nell’IC 99% posso rifiutarlo automaticamente a
un livello di significatività dell’1% poiché l’IC contiene tutti i valori di ipotesi nulla che non
vengono rifiutati da un test a due code con un livello di significatività 100%-99% (si ricordi che il
livello di significatività è uguale al complemento a 100 del livello di confidenza).
142
Esercizio 4
Considerando solo i primi 25 soggetti del dataset stabilire se una regolare attività fisica influenza il
livello plasmatico di colesterolo HDL.
Soluzione:
Dapprima rendo logica la variabile attività fisica: assegno 1 se il soggetto non la pratica e
0 altrimenti: in questo modo la modalità 0 sarà sempre considerata “prima”, es. al numeratore del
rapporto di varianze o come primo membro nella differenza di medie.
AF<-1*( attività.fisica=="No")
Avendo una numerosità campionaria < 30, non è possibile applicare un test di ipotesi parametrico.
La variabile HDL è continua, stiamo considerando due popolazioni e quindi è possibile fare
inferenza statistica sull’uguaglianza delle distribuzioni () di due variabili casuali attraverso la
mediana (X0.5); applicando il test U di Mann-Whitney, con: H0: sportivisedentari; → spX0.5 =
seX0.5; H1: spX0.5 ≠ seX0.5 (test a due code: ipotesi alternativa bidirezionale).
library(exactRankTests)
wilcox.exact(HDL[1:25]~AF[1:25])
Exact Wilcoxon rank sum test
data: HDL[1:25] by AF[1:25]
W = 74, p-value = 0.3824
alternative hypothesis: true mu is not equal to 0
Non c’è nessuna evidenza (p=0.3824) contro H0: sportivisedentari → spX0.5 = seX0.5 per cui non
rifiuto l’ipotesi nulla H0. Le mediane e quindi le due distribuzioni sono uguali: l’attività fisica non
influenza il livello plasmatico di colesterolo HDL.
143
Esercizio 5
Importare in R il dataset del file Dieta.csv relativo alla glicemia (mg/dl) misurata in 42 soggetti
prima (tempo 0) e dopo (tempo 1) una dieta ipocalorica di 30 giorni.
Stabilire se al tempo 0 la glicemia media del campione è più alta di quella al tempo 1 (ipotesi
alternativa H1). Nella popolazione di riferimento, la glicemia segue una distribuzione normale con
varianza ignota ma uguale nelle due misurazioni (tempo 0 e tempo 1). Calcolare un IC 95% e
interpretarlo.
N. B.: i valori mancanti nel dataset sono codificati con n.n.
Soluzione:
Importo in R il dataset del file Dieta.csv, visualizzo i dati e le etichette delle variabili ed eseguo
l’attach():
Dieta <- read.csv2 (file.choose(), sep = ";", dec = ".", header = T,
na.strings = "n.n.")
fix(Dieta) # Visualizzo i dati con un editor di R “user-friendly”.
colnames(Dieta) # Ricavo i nomi delle variabili del dataset importato.
attach (Dieta)
Dovendo fare inferenza statistica sulla differenza tra medie (prima  dopo) di due variabili casuali
normali con  ignoti ma uguali e disponendo dei dati rilevati in uno stesso campione prima e dopo
un trattamento, applico il test T per due campioni appaiati, con H0: prima  dopo = 0 mg/dl; H1:
prima  dopo > 0 mg/dl (test a una coda: ipotesi alternativa unidirezionale).
t.test (glicemia~tempo, mu = 0, alternative = "greater", paired = T,
conf.level = 0.95)
Paired t-test
data: glicemia by tempo
t = 8.3007, df = 41, p-value = 1.285e-10
alternative hypothesis: true difference in means is greater than 0
95 percent confidence interval:
72.11405
Inf
sample estimates:
mean of the differences
90.45238
Ho una decisiva evidenza (p<0.001) contro H0: prima  dopo = 0 mg/dl, per cui rifiuto l’ipotesi
nulla H0. La dieta ipocalorica funziona (media delle differenze = +90.4523) e produce una
significativa diminuzione dei livelli medi di glicemia.
144
Ora calcolo l’IC 95%:
t.test (glicemia~tempo, mu = 0, alternative = "two.sided", paired = T,
conf.level = 0.95)
Paired t-test
data: glicemia by tempo
t = 8.3007, df = 41, p-value = 2.57e-10
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
68.44543 112.45933
sample estimates:
mean of the differences
90.45238
Con un livello di confidenza del 95% è verosimile affermare che la dieta fa diminuire il livello
medio di glicemia da 112.5 a 68.4 mg/dl. In altri termini, c’è una probabilità del 95% che
l’intervallo di valori da 68.4 mg/dl a 112.5 mg/dl contenga la vera media delle differenze. Inoltre
l’IC 95% contiene tutti quei valori di ipotesi nulla che non vengono rifiutati da un test a due code a
un livello di significatività del 5%.
detach (Dieta)
145
Esercitazione 3
Analisi della varianza (ANOVA), regressione lineare e correlazione
Schema riassuntivo:
Variabile di risposta
(y)
Quantitativa
continua
Quantitativa
continua
Quantitativa
continua
Quantitativa
continua
o qualitativa
ordinale
Variabile esplicativa
(x)
Qualitativa
Tipo di relazione
MODELLO
Causale
Quantitativa
continua
Quantitativa
continua
Quantitativa
continua
o qualitativa
ordinale
Causale
*Analisi della varianza
(ANOVA)
*Regressione
lineare
*Correlazione
di Pearson
Simmetrica
Simmetrica
Correlazione
di Spearman
* = Ipotesi di normalità
Sommario:
1)
2)
3)
4)
5)
6)
7)
analisi della varianza -ANOVA- a una via,
confronti multipli secondo Tukey,
analisi della varianza -ANOVA- non parametrica a una via: test di Kruskal-Wallis,
analisi della varianza -ANOVA- a una via con blocchi,
analisi della varianza -ANOVA- a due vie con repliche e interazione,
modello di regressione lineare semplice,
correlazione (Pearson e Spearman).
146
Esercizio 1 (Analisi della varianza -ANOVA- a una via)
Miller e Vanhoutte hanno condotto una ricerca sperimentale su un campione di 18 cani femmine
adulte a cui erano state precedentemente asportate le ovaie (ovariectomizzate).
I 18 cani del campione sono stati casualmente assegnati a uno dei quattro trattamenti previsti dalla
sperimentazione: trattamento 1 (controllo, cioè nessun trattamento), trattamento 2 (estrogeni),
trattamento 3 (progesterone) e trattamento 4 (estrogeni + progesterone).
I dati della sperimentazione sono raccolti nel dataset del file anova1_1.csv.
Determinare se i trattamenti hanno o meno effetti diversi sulla concentrazione sierica di
progesterone espressa in ng/dl (variabile risposta).
Soluzione:
Importo in R il dataset anova1_1.csv, ne visualizzo un estratto, le dimensioni (numero di
righe, numero di colonne) e le etichette delle variabili:
data_estrogeni <- read.csv2 (file.choose(), header = TRUE, sep =
";", dec = ",", na.strings = " ")
head (data_estrogeni)
1
2
3
4
5
6
un..sperimentale
1
2
3
4
5
6
risposta
117
124
40
88
40
440
trattamento
1
1
1
1
1
2
dim (data_estrogeni)
[1] 18
3
colnames (data_estrogeni)
[1] "un..sperimentale" "risposta"
"trattamento"
Per il ricercatore, la variabile trattamento è una variabile qualitativa. Essendo però codificata
numericamente, R la interpreta di default come una variabile quantitativa.
Devo quindi creare, all’interno del data.frame importato, la variabile qualitativa TRATTAMENTO,
allo scopo di comunicare al software la natura qualitativa della variabile originaria:
data_estrogeni$TRATTAMENTO <- factor (data_estrogeni$trattamento)
Eseguo poi l’attach() del del data.frame importato:
attach (data_estrogeni)
147
Visualizzo le statistiche di sintesi delle variabili risposta e TRATTAMENTO:
summary (risposta)
# Capisco che risposta è una variabile
quantitativa
continua,
perché
il
comando
summary(risposta)
fornisce il valore del minimo, del massimo, del primo e del terzo
quartile, della mediana e della media della variabile stessa.
Min.
40.0
1st Qu.
127.0
Median
412.5
Mean
848.2
3rd Qu.
1312.0
Max.
3584.0
summary (TRATTAMENTO)
# Capisco che TRATTAMENTO è una variabile
qualitativa, perché il comando summary restituisce le frequenze
assolute di ogni modalità assunta dalla variabile stessa.
1
5
2
4
3
4
4
5
Visualizzo graficamente (mediante un boxplot e un violinplot affiancati) le variabili risposta e
TRATTAMENTO:
par (mfrow = c(1,2)) # Divido la finestra grafica in due settori.
plot (TRATTAMENTO,risposta)
install.packages("vioplot") # Installo il pacchetto vioplot.
library (vioplot) # Carico il pacchetto appena installato.
vioplot (risposta [TRATTAMENTO == 1], risposta [TRATTAMENTO == 2],
risposta [TRATTAMENTO == 3], risposta [TRATTAMENTO == 4], names =
c("1","2","3","4"))
148
Graficamente, le quattro distribuzioni appaiono approssimativamente simmetriche e non uguali in
mediana: in particolare il gruppo 4 fa riscontrare valori nettamente superiori a quelli degli altri
gruppi. La variabilità tra i gruppi sembra diversa.
Ho dunque a che fare con una variabile di risposta (risposta) quantitativa continua e una
variabile esplicativa (TRATTAMENTO) qualitativa. Lo sperimentatore suppone che le due variabili
siano in relazione causale (TRATTAMENTO  risposta) e quindi, per analizzarle, posso
applicare il modello di analisi della varianza (ANOVA).
In particolare, avendo un’unica variabile esplicativa, applico il modello di analisi della varianza
(ANOVA) a una via, con:
H0: μ1 = μ2 = μ3 = μ4 (la concentrazione sierica media di progesterone è uguale per tutti i quattro
trattamenti),
H1: μ1 ≠ μ2 ≠ μ3 ≠ μ4 (non tutte le μk sono uguali, almeno un trattamento dà una risposta media
diversa).
anova (lm(risposta ~ TRATTAMENTO))
Analysis of Variance Table
Response: risposta
Df
Sum Sq Mean Sq F value
Pr(>F)
TRATTAMENTO 3 15865083 5288361 27.364 4.089e-06 ***
Residuals
14 2705585 193256
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Alternativamente posso usare i seguenti comandi:
aov (lm(risposta ~ TRATTAMENTO))
Call:
aov(formula = lm(risposta ~ TRATTAMENTO))
Terms:
Sum of Squares
Deg. of Freedom
TRATTAMENTO Residuals
15865083
2705585
3
14
Residual standard error: 439.609
Estimated effects may be unbalanced
summary (aov (lm(risposta ~ TRATTAMENTO)))
Df
Sum Sq Mean Sq F value
Pr(>F)
TRATTAMENTO 3 15865083 5288361
27.36 4.09e-06 ***
Residuals
14 2705585 193256
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
149
Il p-value è pari a 4.09 ∙ 106, cioè è < 0.05, per cui rifiuto l’ipotesi nulla H0: μ1 = μ2 = μ3 = μ4 e
posso affermare che almeno uno dei quattro trattamenti considerati determina diverse
concentrazioni sieriche medie di progesterone.
Verifico che siano rispettati i tre assunti necessari per l’applicazione dell’ANOVA.
Eseguo dapprima una verifica qualitativa, eseguendo una diagnostica grafica del modello ANOVA
applicato:
par (mfrow
settori.
=
c(2,2))
#
Divido
la
finestra
grafica
in
quattro
plot (aov(lm(risposta ~ TRATTAMENTO)))
Considerando soltanto la prima riga di grafici, dal primo grafico possiamo constatare che la media
dei residui è approssimativamente pari a 0 e che l’omoschedasticità (uguale varianza dei residui tra
gruppi) non sembra garantita dal trattamento 4 (ultima colonna di punti).
Per quanto riguarda la distribuzione dei residui (secondo grafico) si può notare che quelli centrali
seguono approssimativamente un andamento normale, mentre per le code c’è uno scostamento da
tale ipotesi distributiva.
150
Eseguo quindi una diagnostica quantitativa dei tre assunti:
1) normalità dei residui entro gruppi:
Verifico (quantitativamente) la normalità dei residui all’interno di ciascuno del quattro trattamenti
dividendo in quattro gruppi i seguenti residui:
resid (aov(lm(risposta ~ TRATTAMENTO))) # Visualizzo i residui per
ogni unità statistica componente il campione.
1
2
3
4
5
6
7
8
35.20
42.20 -41.80
6.20
-41.80 174.75 -1.25
-44.25
9
-129.25
10
82.25
11
12
103.25 -137.75
13
-47.75
14
15
16
322.80 -263.20 1242.80
17
18
-801.20 -501.20
ovvero:
shapiro.test (resid(aov(lm(risposta
== "1"])
Shapiro-Wilk normality test
~
TRATTAMENTO)))[TRATTAMENTO
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "1"]
W = 0.8451, p-value = 0.1794
shapiro.test (resid(aov(lm(risposta
== "2"])
Shapiro-Wilk normality test
~
TRATTAMENTO)))[TRATTAMENTO
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "2"]
W = 0.9489, p-value = 0.7096
shapiro.test (resid(aov(lm(risposta
== "3"])
Shapiro-Wilk normality test
~
TRATTAMENTO)))[TRATTAMENTO
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "3"]
W = 0.9065, p-value = 0.4641
shapiro.test (resid(aov(lm(risposta
== "4"])
Shapiro-Wilk normality test
~
TRATTAMENTO)))[TRATTAMENTO
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "4"]
W = 0.9289, p-value = 0.5889
151
L’ipotesi di normalità è confermata da tutti i quattro test.
2) omoschedasticità dei residui entro gruppi:
install.packages("car") # Installo il pacchetto car.
library(car)
leveneTest (resid(aov(lm(risposta ~ TRATTAMENTO))), TRATTAMENTO) #
Verifica quantitativa dell’omoschedasticità dei residui.
Levene's Test for Homogeneity of Variance (center = median)
Df F value Pr(>F)
group 3 3.2539 0.05379 .
14
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Considerando un livello  = 0.05, il test di Levene risulta ai limiti della significatività (p-value =
0.053), come era possibile apprezzare qualitativamente osservando i violinplot. Tuttavia è possibile
affermare che siamo in presenza di omoschedasticità.
3) indipendenza dei residui entro gruppi:
install.packages("lmtest") # Installo il pacchetto lmtest.
library(lmtest)
dwtest (aov(lm(risposta ~ TRATTAMENTO))) # Verifica quantitativa
dell’indipendenza dei residui.
Durbin-Watson test
data: aov(lm(risposta ~ TRATTAMENTO))
DW = 2.671, p-value = 0.7862
alternative hypothesis: true autocorrelation is greater than 0
Anche in questo caso, non è possibile rifiutare l’ipotesi nulla di incorrelazione tra i residui. Quindi
anche il terzo assunto (indipendenza dei residui) risulta valido.
I tre assunti sono rispettati e quindi il risultato dell’ANOVA “Il p-value è pari a 4.09 ∙ 106, cioè è <
0.05, per cui rifiuto l’ipotesi nulla H0: μ1 = μ2 = μ3 = μ4 e posso affermare che almeno uno dei
quattro trattamenti considerati determina diverse concentrazioni sieriche medie di progesterone” è
valido.
152
Esercizio 2 (Confronti multipli secondo Tukey)
Con l’analisi della varianza (ANOVA) a una via applicata ai dati dell’esercizio 1 abbiamo ottenuto
un p-value < 0.05 e quindi abbiamo potuto affermare che almeno uno dei quattro trattamenti
considerati ha effetti diversi sulla concentrazione sierica di progesterone espressa in ng/dl (variabile
risposta).
Determinare quale/i dei quattro trattamenti ha/hanno reso significativa l’ANOVA, cioè quale/i
ha/hanno un effetto diverso rispetto agli altri sulla concentrazione sierica di progesterone.
Soluzione:
Riprendiamo il modello di analisi della varianza (ANOVA) a una via applicato ai dati
dell’esercizio 1, assegnandogli il nome anova.estrogeni:
anova.estrogeni <- aov (lm(risposta ~ TRATTAMENTO))
anova.estrogeni
Call:
aov(formula = lm(risposta ~ TRATTAMENTO))
Terms:
Sum of Squares
Deg. of Freedom
TRATTAMENTO Residuals
15865083
2705585
3
14
Residual standard error: 439.609
Estimated effects may be unbalanced
…e confrontiamo i trattamenti due a due mediante i confronti multipli secondo Tukey, con:
H0(2-1): 2 = 1 vs. H1(2-1): 2 ≠ 1;
H0(3-1): 3 = 1 vs. H1(3-1): 3 ≠ 1;
H0(4-1): 4 = 1 vs. H1(4-1): 4 ≠ 1;
H0(3-2): 3 = 2 vs. H1(3-2): 3 ≠ 2;
H0(4-2): 4 = 2 vs. H1(4-2): 4 ≠ 2;
H0(4-3): 4 = 3 vs. H1(4-3): 4 ≠ 3.
153
TukeyHSD (anova.estrogeni)
Tukey multiple comparisons of means
95% family-wise confidence level
Fit: aov(formula = lm(risposta ~ TRATTAMENTO))
$TRATTAMENTO
diff
2-1
183.45
3-1
440.95
4-1 2259.40
3-2
257.50
4-2 2075.95
4-3 1818.45
lwr
-673.6928
-416.1928
1451.2781
-646.0078
1218.8072
961.3072
upr
1040.593
1298.093
3067.522
1161.008
2933.093
2675.593
p adj
0.9232880
0.4658803
0.0000061
0.8401641
0.0000311
0.0001282
Otteniamo p-values < 0.05 solo nei confronti in cui è presente il trattamento 4, per cui possiamo
rifiutare solo le ipotesi nulle concernenti il trattamento 4, vale a dire H0(4-1): 4 = 1, H0(4-2): 4 = 2
e H0(4-3): 4 = 3. Possiamo quindi concludere che l’ANOVA applicata ai dati dell’esercizio 1 è stata
resa significativa dal trattamento 4. Il trattamento 4 ha un effetto diverso rispetto agli altri sulla
concentrazione sierica di progesterone.
Visualizzo graficamente i risultati:
plot (TukeyHSD(anova.estrogeni))
Possiamo vedere che i confronti in cui è presente il gruppo 4 fanno sempre emergere la
significatività (rispetto a un livello  = 0.05).
detach (data_estrogeni) # Disattivo il comando attach ().
rm (list = objects()) #
nell’area di lavoro di R.
Cancello
tutti
gli
oggetti
presenti
154
Esercizio 3 (Analisi della varianza -ANOVA- non parametrica a una via: test di
Kruskal-Wallis)
Altri ricercatori hanno condotto una ricerca sperimentale analoga a quella di Miller e Vanhoutte su
un campione di 120 cani femmine adulte a cui erano state precedentemente asportate le ovaie
(ovariectomizzate).
I 120 cani del campione sono stati casualmente assegnati a uno dei quattro trattamenti previsti dalla
sperimentazione: trattamento 1 (controllo, cioè nessun trattamento), trattamento 2 (estrogeni),
trattamento 3 (progesterone) e trattamento 4 (estrogeni + progesterone).
I dati della sperimentazione sono raccolti nel dataset del file data_KW.csv.
Determinare se i trattamenti hanno o meno effetti diversi sulla concentrazione sierica di
progesterone espressa in ng/dl (variabile risposta).
Soluzione:
Importo in R il dataset data_KW.csv, ne visualizzo un estratto, le dimensioni (numero di righe,
numero di colonne) e le etichette delle variabili:
data_KW <- read.csv2 (file.choose(), header = TRUE, sep = ";", dec
= ",", na.strings = " ")
head (data_KW)
1
2
3
4
5
6
unità
1
2
3
4
5
6
trattamento
1
1
1
1
1
1
risposta
795.2401
776.7010
697.1153
803.2520
808.8335
751.3667
dim (data_KW)
[1] 120
3
colnames (data_KW)
[1] "unità"
"trattamento"
"risposta"
Per il ricercatore, la variabile trattamento è una variabile qualitativa. Essendo però codificata
numericamente, R la interpreta di default come una variabile quantitativa.
Devo quindi creare, all’interno del data.frame importato, la variabile qualitativa TRATTAMENTO,
allo scopo di comunicare al software la natura qualitativa della variabile originaria:
data_KW$TRATTAMENTO <- factor (data_KW$trattamento)
155
Eseguo poi l’attach() del del data.frame importato:
attach (data_KW)
Visualizzo le statistiche di sintesi delle variabili risposta e TRATTAMENTO:
summary (risposta)
# Capisco che risposta è una variabile
quantitativa
continua,
perché
il
comando
summary(risposta)
fornisce il valore del minimo, del massimo, del primo e del terzo
quartile, della mediana e della media della variabile stessa.
Min.
2.473
1st Qu.
551.600
Median
749.700
Mean
617.900
3rd Qu.
849.700
Max.
972.000
summary (TRATTAMENTO)
# Capisco che TRATTAMENTO è una variabile
qualitativa, perché il comando summary restituisce le frequenze
assolute di ogni modalità assunta dalla variabile stessa.
1
30
2
30
3
30
4
30
Ho dunque a che fare con una variabile di risposta (risposta) quantitativa continua e una
variabile esplicativa (TRATTAMENTO) qualitativa. Lo sperimentatore suppone che le due variabili
siano in relazione causale (TRATTAMENTO  risposta) e quindi, per analizzarle, posso
applicare il modello di analisi della varianza (ANOVA).
In particolare, avendo un’unica variabile esplicativa, applico il modello di analisi della varianza
(ANOVA) a una via, con:
H0: μ1 = μ2 = μ3 = μ4 (la concentrazione sierica media di progesterone è uguale per tutti i quattro
trattamenti),
H1: μ1 ≠ μ2 ≠ μ3 ≠ μ4 (non tutte le μk sono uguali, almeno un trattamento dà una risposta media
diversa).
anova (lm(risposta ~ TRATTAMENTO))
Analysis of Variance Table
Response: risposta
Df
Sum Sq Mean Sq F value
Pr(>F)
TRATTAMENTO
3 11950757 3983586 1270.1 < 2.2e-16 ***
Residuals
116
363837
3137
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Finora abbiamo applicato l’ANOVA a una via come nell’esercizio 1.
156
Ora passiamo direttamente alla verifica dell’assunzione di normalità:
normalità dei residui entro gruppi:
shapiro.test
== "1"])
(resid(aov(lm(risposta
~
TRATTAMENTO)))[TRATTAMENTO
Shapiro-Wilk normality test
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "1"]
W = 0.959, p-value = 0.2922
shapiro.test
== "2"])
(resid(aov(lm(risposta
~
TRATTAMENTO)))[TRATTAMENTO
Shapiro-Wilk normality test
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "2"]
W = 0.967, p-value = 0.461
shapiro.test
== "3"])
(resid(aov(lm(risposta
~
TRATTAMENTO)))[TRATTAMENTO
Shapiro-Wilk normality test
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "3"]
W = 0.981, p-value = 0.8515
shapiro.test
== "4"])
(resid(aov(lm(risposta
~
TRATTAMENTO)))[TRATTAMENTO
Shapiro-Wilk normality test
data: resid(aov(lm(risposta ~ TRATTAMENTO)))[TRATTAMENTO == "4"]
W = 0.7533, p-value = 1.03e-05
L’ipotesi di normalità non è confermata per tutti i quattro gruppi.
Applichiamo quindi un’ANOVA non parametrica a una via, cioè il test di Kruskal-Wallis con:
H0: Med1 = Med2 = Med3 = Med4 (la concentrazione sierica “mediana” di progesterone è uguale per
tutti i quattro trattamenti),
H1: Med1 ≠ Med2 ≠ Med3 ≠ Med4 (non tutte le Medk sono uguali, almeno un trattamento dà una
risposta “mediana” diversa).
kruskal.test (risposta ~ TRATTAMENTO)
157
Kruskal-Wallis rank sum test
data: risposta by TRATTAMENTO
Kruskal-Wallis chi-squared = 109.4817, df = 3, p-value < 2.2e-16
Il p-value è pari a 2.2 ∙ 1016, cioè < 0.05, per cui rifiuto l’ipotesi nulla H0: Med1 = Med2 = Med3 =
Med4 e posso affermare che i quattro trattamenti considerati hanno effetti diversi sulla
concentrazione sierica “mediana” di progesterone.
158
Esercizio 4 (Analisi della varianza -ANOVA- a una via)
Azoulay e Dupuis hanno condotto una ricerca sperimentale su un campione di 20 topi femmina
infettati da Streptococcus pneumoniae, allo scopo di studiare l’efficacia di cinque farmaci per
debellare l’infezione polmonare sostenuta da questo batterio.
I 20 topi del campione sono stati casualmente assegnati a uno dei sei trattamenti previsti dalla
sperimentazione: trattamento 1 (controllo, cioè nessun trattamento), trattamento 2 (Amoxicillina:
iniezione di 50 mg/kg), trattamento 3 (Eritromicina: iniezione di 50 mg/kg), trattamento 4
(Temafloxacina: iniezione di 50 mg/kg), trattamento 5 (Ofloxacina: iniezione di 100 mg/kg) e
trattamento 6 (Ciprofoloxacina: iniezione di 100 mg/kg).
I dati della sperimentazione sono raccolti nel dataset del file anova1_2.csv.
Determinare se i trattamenti hanno o meno effetti diversi sul numero di batteri nelle vie aeree
espresso in Log cfu/ml di polmone omogeneizzato (variabile risposta).
Soluzione:
Importo in R il dataset anova1_2.csv, ne visualizzo un estratto, le dimensioni (numero di
righe, numero di colonne) e le etichette delle variabili:
data_topi <- read.csv2 (file.choose(), header = TRUE, sep = ";",
dec = ",", na.strings = " ") # Importa dataset "anova1_2.csv"
head (data_topi)
1
2
3
4
5
6
un..sperimentale
1
2
3
4
5
6
risposta
8.8
8.6
8.1
8.4
8.8
2.6
trattamento
1
1
1
1
1
2
dim (data_topi)
[1] 20
3
Per il ricercatore, la variabile trattamento è una variabile qualitativa. Essendo però codificata
numericamente, R la interpreta di default come una variabile quantitativa.
Devo quindi creare, all’interno del data.frame importato, la variabile qualitativa TRATTAMENTO,
allo scopo di comunicare al software la natura qualitativa della variabile originaria:
data_topi$TRATTAMENTO <- factor (data_topi$trattamento)
Eseguo poi l’attach() del del data.frame importato:
attach (data_topi)
159
Visualizzo le statistiche di sintesi delle variabili risposta e TRATTAMENTO:
summary (risposta)
# Capisco che risposta è una variabile
quantitativa
continua,
perché
il
comando
summary(risposta)
fornisce il valore del minimo, del massimo, del primo e del terzo
quartile, della mediana e della media della variabile stessa.
Min.
2.600
1st Qu.
2.600
Median
4.950
Mean
5.254
3rd Qu.
7.920
Max.
8.800
summary (TRATTAMENTO)
# Capisco che TRATTAMENTO è una variabile
qualitativa, perché il comando summary restituisce le frequenze
assolute di ogni modalità assunta dalla variabile stessa.
1
5
2
3
3
3
4
3
5
3
6
3
Visualizzo graficamente (mediante un boxplot e un violinplot affiancati) le variabili risposta e
TRATTAMENTO:
par (mfrow = c(1,2)) # Divido la finestra grafica in due settori.
plot (TRATTAMENTO,risposta)
install.packages("vioplot") # Installo il pacchetto vioplot.
library (vioplot) # Carico il pacchetto appena installato.
vioplot (risposta [TRATTAMENTO == 1], risposta [TRATTAMENTO == 2],
risposta [TRATTAMENTO == 3], risposta [TRATTAMENTO == 4], risposta
[TRATTAMENTO == 5], risposta [TRATTAMENTO == 6], names =
c("1","2","3","4","5","6"))
Graficamente, le quattro distribuzioni appaiono non simmetriche e non uguali in mediana. La
variabilità tra i gruppi sembra diversa.
160
Ho dunque a che fare con una variabile di risposta (risposta) quantitativa continua e una
variabile esplicativa (TRATTAMENTO) qualitativa. Lo sperimentatore suppone che le due variabili
siano in relazione causale (TRATTAMENTO  risposta) e quindi, per analizzarle, posso
applicare il modello di analisi della varianza (ANOVA).
In particolare, avendo un’unica variabile esplicativa, applico il modello di analisi della varianza
(ANOVA) a una via, con:
H0: μ1 = μ2 = μ3 = μ4 = μ5 = μ6 (il numero medio di batteri nelle vie aeree è uguale per tutti i quattro
trattamenti),
H1: μ1 ≠ μ2 ≠ μ3 ≠ μ4 ≠ μ5 ≠ μ6 (non tutte le μk sono uguali, almeno un trattamento dà una risposta
media diversa).
anova (lm(risposta ~ TRATTAMENTO))
Analysis of Variance Table
Response: risposta
Df Sum Sq Mean Sq F value
Pr(>F)
TRATTAMENTO 5 126.901 25.3802
41.19 6.916e-08 ***
Residuals
14
8.626 0.6162
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Il p-value è pari a 6.916 ∙ 108, cioè è < 0.05, per cui rifiuto l’ipotesi nulla H0: μ1 = μ2 = μ3 = μ4 =
μ5 = μ6 e posso affermare che i sei trattamenti considerati hanno effetti diversi sul numero medio di
batteri nelle vie aeree.
detach(data_topi)
161
Esercizio 5 (Analisi della varianza -ANOVA- a una via con blocchi)
E’ stato condotto un esperimento su un campione di 10 soggetti per saggiare gli effetti di quattro
farmaci (trattamenti) diversi sul tempo di coagulazione del sangue (in minuti).
Ogni soggetto corrisponde a un blocco (variabile blocco).
Il campione di sangue di ogni soggetto è stato diviso in quattro sotto-campioni uguali: i quattro
sotto-campioni sono stati destinati a caso ad essere saggiati con uno dei quattro trattamenti
considerati (variabile trattamento), in modo tale che, all’interno di ogni blocco, fossero testati
tutti i quattro trattamenti.
I dati dell’esperimento sono raccolti nel dataset del file anova1_4 BLOCCO.csv.
I quattro farmaci testati hanno effetti differenti sul tempo di coagulazione del sangue espresso in
minuti (variabile risposta)?
Soluzione:
Importo in R il dataset anova1_4 BLOCCO.csv, ne visualizzo un estratto, le dimensioni
(numero di righe, numero di colonne) e le etichette delle variabili:
data_coagulazione <- read.csv2 (file.choose(), header = TRUE, sep
= ";", dec = ",", na.strings = " ")
head (data_coagulazione)
1
2
3
4
5
6
blocco risposta trattamento
1
1.5
1
2
1.4
1
3
1.8
1
4
1.3
1
5
2.0
1
6
1.1
1
dim (data_coagulazione)
[1] 40
3
colnames (data_coagulazione)
[1] "blocco"
"risposta"
"trattamento"
Per il ricercatore, le variabili blocco e trattamento sono variabili qualitative. Essendo
però codificate numericamente, R le interpreta di default come variabili quantitative.
Devo quindi creare, all’interno del data.frame importato, le variabili qualitative BLOCCO e
TRATTAMENTO, allo scopo di comunicare al software la natura qualitativa delle variabili
originarie:
162
data_coagulazione$BLOCCO <- factor (data_coagulazione$blocco)
data_coagulazione$TRATTAMENTO <- factor (data_coagulazione$trattamento)
Eseguo poi l’attach() del del data.frame importato:
attach (data_coagulazione)
Visualizzo le statistiche di sintesi delle variabili BLOCCO, TRATTAMENTO e risposta:
summary (BLOCCO) # Capisco che BLOCCO è una variabile qualitativa,
perché il comando summary restituisce le frequenze assolute di
ogni modalità assunta dalla variabile stessa.
1 2 3 4 5 6 7 8 9 10
4 4 4 4 4 4 4 4 4 4
summary (TRATTAMENTO) # Capisco che TRATTAMENTO è una variabile
qualitativa, perché il comando summary restituisce le frequenze
assolute di ogni modalità assunta dalla variabile stessa.
1 2 3 4
10 10 10 10
summary (risposta) # Capisco che risposta è una variabile
quantitativa
continua,
perché
il
comando
summary(risposta)
fornisce il valore del minimo, del massimo, del primo e del terzo
quartile, della mediana e della media della variabile stessa.
Min.
1.000
1st Qu.
1.300
Median
1.500
Mean
1.535
3rd Qu.
1.700
Max.
2.300
Ho dunque a che fare con una variabile di risposta (risposta) quantitativa continua, una variabile
esplicativa (TRATTAMENTO) qualitativa e una variabile qualitativa di blocco (BLOCCO). Lo
sperimentatore suppone che le prime due variabili siano in relazione causale (TRATTAMENTO 
risposta) e quindi, per analizzarle, posso applicare il modello di analisi della varianza
(ANOVA).
In particolare, avendo un’unica variabile esplicativa e una di blocco, applico il modello di analisi
della varianza (ANOVA) a una via con blocchi, con:
H0: 1 = 2 = 3 = 4 = 0 (gli scostamenti dei trattamenti dalla media complessiva sono uguali e nulli
→ gli effetti dei trattamenti sono uguali e nulli),
H1: 1 ≠ 2 ≠ 3 ≠ 4 ≠ 0 (non tutti le τ j sono uguali, almeno uno scostamento dalla media
complessiva è diverso
→ almeno un trattamento dà una risposta media diversa).
163
anova (lm(risposta ~ TRATTAMENTO + BLOCCO))
Analysis of Variance Table
Response: risposta
Df Sum Sq Mean Sq F value
Pr(>F)
TRATTAMENTO 3 0.363 0.12100 14.392 8.568e-06 ***
BLOCCO
9 3.341 0.37122 44.154 7.547e-14 ***
Residuals
27 0.227 0.00841
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Il p-value relativo alla variabile TRATTAMENTO è pari a 8.568 ∙ 106, cioè è < 0.05, per cui rifiuto
l’ipotesi nulla H0: 1 = 2 = 3 = 4 = 0 e posso affermare che gli effetti dei trattamenti non sono
uguali e nulli.
L’ipotesi nulla e il P-value relativi alla variabile BLOCCO non vengono considerati, poiché tale
variabile è meramente strumentale ed è inserita nel disegno dello studio solo per controllare a priori
una fonte di variabilità che può agire sulla variabile risposta e confondere i risultati
relativamente alla variabile TRATTAMENTO.
detach(data_coagulazione)
164
Esercizio 6 (Analisi della varianza -ANOVA- a due vie con repliche e
interazione)
Il valore nutritivo di un certo frutto commestibile è stato valutato su un campione di 72 esemplari
del frutto in esame. I 72 frutti del campione appartengono a quattro varietà diverse (variabile
varietà), provenienti da tre zone geografiche distinte (variabile zona): ogni zona geografica ha
fornito 6 esemplari di frutto per ogni varietà.
Determinare, tenendo conto dell’interazione tra le variabili zona e varietà, se le diverse zone
geografiche e le diverse varietà hanno o meno effetti diversi sulla concentrazione di polveri sottili
nei frutti espressa in ppm (variabile risposta).
Soluzione:
Importo in R il dataset anova2_1R.csv, ne visualizzo un estratto, le dimensioni (numero di
righe, numero di colonne) e le etichette delle variabili:
data_frutti <- read.csv2 (file.choose(), header = TRUE, sep = ";",
dec = ",", na.strings = " ")
head(data_frutti)
1
2
3
4
5
6
zona
1
1
1
1
1
1
risposta
6.9
11.8
6.2
9.2
9.2
6.2
varietà
1
1
1
1
1
1
dim(data_frutti)
[1] 72
3
colnames(data_frutti)
[1] "zona"
"risposta" "varietà"
Per il ricercatore, le variabili zona e varietà sono variabili qualitative. Essendo però
codificate numericamente, R le interpreta di default come variabili quantitative.
Devo quindi creare, all’interno del data.frame importato, le variabili qualitative ZONA e
VARIETà, allo scopo di comunicare al software la natura qualitativa delle variabili originarie:
data_frutti$ZONA <- factor (data_frutti$zona)
data_frutti$VARIETà <- factor (data_frutti$varietà)
165
Eseguo poi l’attach() del del data.frame importato:
attach (data_frutti)
Visualizzo le statistiche di sintesi delle variabili ZONA, VARIETà e risposta:
summary (ZONA) # Capisco che ZONA è una variabile qualitativa,
perché il comando summary restituisce le frequenze assolute di
ogni modalità assunta dalla variabile stessa.
1
24
2
24
3
24
summary (VARIETà) # Capisco che VARITETà è una variabile
qualitativa, perché il comando summary restituisce le frequenze
assolute di ogni modalità assunta dalla variabile stessa.
1
18
2
18
3
18
4
18
summary (risposta) # Capisco che risposta è una variabile
quantitativa
continua,
perché
il
comando
summary(risposta)
fornisce il valore del minimo, del massimo, del primo e del terzo
quartile, della mediana e della media della variabile stessa.
Min.
5.000
1st Qu.
7.075
Median
9.200
Mean
9.457
3rd Qu.
12.100
Max.
14.100
Grafico un interaction plot:
interaction.plot (VARIETà, ZONA, risposta, fixed = TRUE, col = c
("red", "green", "blue", "black"))
166
Ho dunque a che fare con una variabile di risposta (risposta) quantitativa continua e due
variabili esplicative (ZONA e VARIETà) qualitative che interagiscono (:) tra loro. Lo
sperimentatore suppone che le due variabili esplicative e la loro interazione siano in relazione
causale con la variabile di risposta (ZONA, VARIETà, ZONA:VARIETà  risposta) e
quindi, per analizzarle, posso applicare il modello di analisi della varianza (ANOVA).
In particolare, avendo due variabili esplicative che interagiscono tra loro, applico il modello di
analisi della varianza (ANOVA) a due vie con repliche e interazione, con:
H0(VARIETà): 1 = 2 = 3 = 4 = 0 (gli effetti della variabile varietà sulla concentrazione media di
polveri sottili nei frutti sono uguali e nulli per tutte le quattro varietà),
H1(VARIETà): 1 ≠ 2 ≠ 3 ≠ 4 ≠ 0 (non tutti gli effetti sono uguali, almeno una varietà ha un effetto
diverso sulla concentrazione media di polveri sottili nei frutti);
e con:
H0(ZONA): 1 = 2 = 3 = 0 (gli effetti della variabile zona sulla concentrazione media di polveri
sottili nei frutti sono uguali e nulli per tutte le tre zone geografiche),
H1(ZONA): 1 ≠ 2 ≠ 3 ≠ 0 (non tutti gli effetti sono uguali, almeno una zona geografica ha un effetto
diverso sulla concentrazione media di polveri sottili nei frutti);
e con:
H0(VARIETà:ZONA): 11 = 12 = … = ij = 0 (gli effetti congiunti di varietà e zona sulla
concentrazione media di polveri sottili nei frutti sono uguali e nulli),
H1(VARIETà:ZONA): 11 ≠ 12 ≠ … ≠ ij ≠ 0 (gli effetti congiunti di varietà e zona sulla
concentrazione media di polveri sottili nei frutti sono diversi).
anova (lm(risposta ~ VARIETà + ZONA + VARIETà:ZONA))
Analysis of Variance Table
Response: risposta
Df Sum Sq Mean Sq F value
Pr(>F)
VARIETà
3 325.57 108.525 37.7431 7.828e-14
ZONA
2 31.51 15.753 5.4788 0.006525
VARIETà:ZONA 6 33.17
5.529 1.9228 0.091676
Residuals
60 172.52
2.875
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05
***
**
.
‘.’ 0.1 ‘ ’ 1
Il p-value relativo alla variabile VARIETà è pari a 7.828 ∙ 1014, cioè è < 0.05, per cui rifiuto
l’ipotesi nulla H0(VARIETà): 1 = 2 = 3 = 4 = 0 e posso affermare che le quattro varietà
considerate hanno effetti diversi sulla concentrazione media di polveri sottili nei frutti.
Il p-value relativo alla variabile ZONA è pari a 0.006525, cioè è < 0.05, per cui rifiuto l’ipotesi
nulla H0(ZONA): 1 = 2 = 3 = 0 e posso affermare che le tre zone considerate hanno effetti diversi
sulla concentrazione media di polveri sottili nei frutti.
Il p-value relativo all’interazione tra la variabile VARIETà e la variabile ZONA è pari a 0.091676,
cioè è > 0.05, per cui non rifiuto l’ipotesi nulla H0(VARIETà:ZONA): 11 = 12 = … = ij = 0 e non
posso affermare che le due variabili interagiscono nell’influenzare la concentrazione media di
polveri sottili nei frutti.
detach(data_frutti)
167
Esercizio 7 (Modello di regressione lineare semplice)
Importare in R il dataset data_lm.csv.
Lo sperimentatore ipotizza che tra le variabili colesterolo e glicemia esista una relazione
causale (colesterolo  glicemia).
Testare e quantificare tale relazione.
Soluzione:
Importo in R il dataset data_lm.csv, ne visualizzo un estratto, le dimensioni (numero di righe,
numero di colonne), le etichette delle variabili ed esguo l’attach():
data_lm <- read.csv2 (file.choose(), header = TRUE, sep = ";")
head (data_lm)
colesterolo
1
188.3131
2
242.2862
3
195.6349
4
196.6998
5
100.5295
6
207.8452
glicemia
88.58131
81.02835
123.40325
129.35414
86.12813
85.31602
dim (data_lm)
[1] 100
2
colnames (data_lm)
[1] "colesterolo" "glicemia"
attach (data_lm)
Visualizzo le statistiche di sintesi di entrambe le variabili:
summary (data_lm)
colesterolo
Min.
: 100.5
1st Qu.: 181.3
Median : 194.1
Mean
: 198.4
3rd Qu.: 218.3
Max.
: 262.6
glicemia
Min.
: 47.62
1st Qu.: 72.15
Median : 86.11
Mean
: 86.29
3rd Qu.: 102.15
Max.
: 129.35
Capisco che entrambe le variabili sono quantitative continue, perché il comando summary()
fornisce il valore del minimo, del massimo, del primo e del terzo quartile, della mediana e della
media delle variabili stesse.
168
Ho dunque a che fare con una variabile di risposta y (glicemia) quantitativa continua e una
variabile esplicativa x (colesterolo) anch’essa quantitativa continua. Lo sperimentatore
suppone che le due variabili siano in relazione causale (colesterolo  glicemia) e quindi,
per analizzarle, posso applicare il modello di regressione lineare semplice (y =  +  x + ), con:
H0:  = 0
H1:  ≠ 0
e con:
H0: colesterolo = 0
H1: colesterolo ≠ 0
m1 <- lm (glicemia ~ colesterolo)
summary (m1)
Call:
lm(formula = glicemia ~ colesterolo)
Residuals:
Min
1Q
-38.227 -14.540
Median
-0.782
3Q
15.653
Max
43.030
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 90.78290
13.86906
6.546 2.73e-09 ***
colesterolo -0.02267
0.06918 -0.328
0.744
--Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 20.12 on 98 degrees of freedom
Multiple R-squared: 0.001094, Adjusted R-squared: -0.009098
F-statistic: 0.1074 on 1 and 98 DF, p-value: 0.7438
Calcolo gli intervalli di confidenza dei coefficienti  e :
confint (m1)
(Intercept)
colesterolo
2.5 %
63.2601928
-0.1599524
97.5 %
118.3055975
0.1146145
Il p-value relativo alla stima dell’intercetta Intercept (cioè del coefficiente  dell’equazione
della regressione lineare semplice y =  + x + ) è pari a 2.73 ∙ 109, cioè < 0.05, per cui rifiuto
l’ipotesi nulla H0:  = 0 e posso affermare che nell’equazione del modello, il coefficiente  è
diverso da zero.
Il P-value relativo alla variabile colesterolo (cioè alla stima del coefficiente  dell’equazione
della regressione lineare semplice y =  + x + ) è pari a 0.744, cioè > 0.05, per cui non posso
rifiutare l’ipotesi nulla H0: colesterolo = 0. Posso concludere che le due variabili glicemia e
colesterolo non sono legate da una relazione lineare (livello di significatività considerato =
169
0.05): anche se all’aumentare di un’unità di colesterolo la glicemia decresce di – 0.03, tale
variazione non risulta significativamente diversa da zero (test a due code).
Verifico che siano rispettati i tre assunti necessari per l’applicazione del modello di regressione
lineare semplice:
1) normalità dei residui:
qqnorm (residuals(m1))
qualitativa (grafica).
;
qqline
shapiro.test (residuals(m1))
(residuals(m1))
#
Verifica
# Verifica quantitativa.
Shapiro-Wilk normality test
data: residuals(m1)
W = 0.9839, p-value = 0.2652
2) omoschedasticità dei residui:
install.packages ("lmtest") # Installo il pacchetto lmtest.
library (lmtest) # Carico il pacchetto appena installato.
bptest (glicemia ~ colesterolo) # Test di Breusch-Pagan, con H0:
gli errori sono omoschedastici.
studentized Breusch-Pagan test
data: glicemia ~ colesterolo
BP = 0.0119, df = 1, p-value = 0.9132
170
3) indipendenza dei residui:
dwtest (glicemia ~ colesterolo)
Durbin-Watson test
data: glicemia ~ colesterolo
DW = 2.1878, p-value = 0.8277
alternative hypothesis: true autocorrelation is greater than 0
I tre assunti sono rispettati: in tutti i tre test non si rifiutano le rispettive ipotesi nulle.
171
Esercizio 8 (Correlazione)
Consideriamo i dati utilizzati nell’esercizio 7.
Questa volta lo sperimentatore ipotizza che tra le variabili glicemia e colesterolo esista una
relazione simmetrica (glicemia  colesterolo).
Testare e quantificare tale relazione.
Soluzione:
La relazione simmetrica tra due variabili viene testata e quantificata mediante la correlazione.
Distinguiamo:
- la correlazione di Pearson (si applica a variabili quantitative continue normali),
- la correlazione di Spearman (si applica a variabili quantitative continue o qualitative ordinali
“ranghizzate”).
Correlazione di Pearson
Come dimostrato nell’esercizio 7, le variabili glicemia e colesterolo sono entrambe
quantitative continue.
Ho dunque a che fare con due variabili quantitative continue. Lo sperimentatore suppone che le due
variabili siano in relazione simmetrica (glicemia  colesterolo) e quindi, per analizzarle,
applico la correlazione di Pearson, con:
cor (glicemia,
Pearson.
colesterolo)
#
Ottengo
il
valore
del
rho
di
- 0.03308315
Diagnostica per la correlazione di Pearson:
shapiro.test (glicemia)
Shapiro-Wilk normality test
data: glicemia
W = 0.9842, p-value = 0.2779
shapiro.test (colesterolo)
Shapiro-Wilk normality test
data: colesterolo
W = 0.9799, p-value = 0.13
Entrambe le variabili risultano distribuite normalmente (p-values non significativi) e quindi è
corretto eseguire una correlazione di Pearson.
Applico un test di significatività alla correlazione di Pearson, con: H0:  = 0 e H1:  ≠ 0.
172
cor.test (glicemia, colesterolo, method = "pearson")
Pearson's product-moment correlation
data: glicemia and colesterolo
t = -0.3277, df = 98, p-value = 0.7438
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.2280196 0.1644033
sample estimates:
cor
-0.03308315
Il p-value risulta pari a 0.7438, cioè > 0.05, per cui non posso rifiutare l’ipotesi nulla H0:  = 0
(livello di significatività = 0.05). Posso concludere che la correlazione di Pearson non è
significativamente diversa da zero.
Correlazione di Spearman
Se la diagnostica della correlazione di Pearson non fosse andata a buon fine, cioè una o entrambe le
variabili considerate non fossero risultate normalmente distribuite, avrei dovuto applicare la
correlazione di Spearman:
cor (glicemia, colesterolo,
valore del rho di Spearman.
method
=
"spearman")
#
Ottengo
il
0.009144914
Applico un test di significatività alla correlazione di Spearman, con: H0:  = 0 e H1:  ≠ 0.
cor.test(glicemia, colesterolo, method = "spearman")
Spearman's rank correlation rho
data: glicemia and colesterolo
S = 165126, p-value = 0.928
alternative hypothesis: true rho is not equal to 0
sample estimates:
rho
0.009144914
Il p-value risulta pari a 0.928, cioè > 0.05, per cui non posso rifiutare l’ipotesi nulla H0:  = 0
(livello di significatività = 0.05). Posso concludere che la correlazione di Spearman non è
significativamente diversa da zero.
173