Introduzione e analisi dei dati in R
Cinzia Viroli
Dipartimento di Scienze Statistiche
Università di Bologna
[email protected]
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
1
0. Premessa
R è uno dei software statistici più utilizzati dalla comunità scientifica. La sua grande diffusione nasce dal
fatto che si tratta di un ambiente di tipo open source ovvero disponibile gratuitamente sotto i vincoli della
GPL (General Public Licence) per diversi sistemi operativi. Si tratta di un ambiente molto versatile e
potente che permette di gestire basi di dati, di effettuare analisi statistiche e di produrre grafici di alto
livello. Inoltre esso rappresenta un vero e proprio linguaggio di programmazione orientato ad oggetti che
consente l'uso di strutture condizionali e cicliche, nonché di funzioni create dall'utente. Per informazioni
sull'installazione del programma:
http://cran.r-project.org/
Queste semplici note rappresentano uno schema molto sintetico e non esaustivo degli argomenti trattati a
lezione. Per maggiori dettagli sull'uso di R si faccia riferimento al volume:
A first course in Statistical programming with R, Braun and Murdoch, Cambridge University Press, 2008
(in inglese)
oppure ai tanti manuali gratuiti scaricabili dal sito di R http://cran.r-project.org sotto la voce Contributed
Documentation.
1. Introduzione al linguaggio R
R è un linguaggio di programmazione ad oggetti. I possibili oggetti sono vettori, matrici, liste, basi di dati
(dataframe), funzioni ecc. Sia in windows che in linux non esiste una interfaccia grafica al programma.
Quando si apre R per la prima volta appare una semplice finestra bianca (chiamata console) con un
cursore che indica la posizione in cui inserire un qualche comando. L'area di lavoro iniziale di R
(chiamata workspace) è vuota. Per verificarlo si digiti:
> ls()
oppure
> objects()
Se si costruisce un semplice oggetto di nome pluto a cui si assegna il valore 3:
> pluto=3
l'area di lavoro ora conterrà il nuovo oggetto.
Si immagini ora di lavorare in R e alla fine della sessione di lavoro si vogliano salvare gli oggetti
costruiti. Occorre quindi salvare il workspace in una determinata directory di lavoro. Alcuni comandi
utili:
> getwd() per conoscere la directory di lavoro
> setwd(“directory”) per impostare la directory di lavoro
> save.image(“nome.RData”) per salvare il workspace
> load(“nome.RData”) per caricare il workspace
> savehistory(“nome”) e loadhistory(“nome”) per salvare
l'elenco dei comandi digitati nella console.
e
caricare
Per uscire da R: q()
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
2
1.1 Lavorare con gli oggetti
> x=2+(3-4*5)/2 #costruisci un oggetto
> x #guardalo
[1] -6.5
> x-2 #...utilizzalo
[1] -8.5
> x=5 #...sovrascrivilo
> y=2.5 #crea un altro oggetto
> x/y #fai qualsiasi operazione con gli oggetti
[1] 2
Il simbolo # è il commento e viene ignorato dall’ambiente.
1.1 Operatori logici
> 2*2==4
[1] TRUE
> 2*3==4
[1] FALSE
> 2*2>=4
[1] TRUE
> 2*3>4
[1] TRUE
> 2*3>=4
[1] TRUE
> 2*3!=4
[1] TRUE
1.2 Vettori
> x=c(2,5,9.5,-3) #costruisci un vettore
> x[2] #seleziona il suo secondo elemento
[1] 5
> x[c(2,4)] #seleziona i suoi elementi nella posizione 2 e 4
[1] 5 -3
> x[x>0] #seleziona i sui elementi positivi
[1] 2.0 5.0 9.5
> x[x>0]-1
[1] 1.0 4.0 8.5
> x[x>0][2]
[1] 5
> x=1:10
> x
[1] 1 2 3 4 5 6 7 8 9 10
> x1=seq(1,1000, length=10) #vettore da 1 a 1000 di ampiezza 10
> x1
[1] 1 112 223 334 445 556 667 778 889 1000
> x2=rep(2,times=10) #ripeti 2 10 volte
> x2
[1] 2 2 2 2 2 2 2 2 2 2
> rep(c(1,3),times=4) #ripeti (1,3) 4 volte
[1] 1 3 1 3 1 3 1 3
> rep(c(1,9),c(3,1)) #ripeti (1,9) 3 e 1 volta rispettivamente
[1] 1 1 1 9
> length(c(x,x1,x2,3))
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
3
[1] 31
1.3 Matrici
> x=matrix(1:10,ncol=5) #costruisci una matrice
> x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
> xx=t(x) #trasponila
> x[,1] #seleziona la prima colonna
[1] 1 2
> x[2,] #seleziona la seconda riga
[1] 2 4 6 8 10
> x[3,2] #seleziona l’elemento [3,2]
Error: subscript out of bounds
> x[2,3] #...e quello [2,3]
[1] 6
> x[,4:5] #seleziona solo le colonne 4 e 5
[,1] [,2]
[1,] 7 9
[2,] 8 10
> x[,-c(2,4)] #seleziona le colonne 1, 3 e 5
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
> cbind(1:2,c(1,-2),c(0,9)) #dispone per colonne
[,1] [,2] [,3]
[1,] 1 1 0
[2,] 2 -2 9
> rbind(1:4,c(0,5,-4,6)) #dispone per righe
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 0 5 -4 6
> diag(x[,4:5]) #estrae la diagonale principale
[1] 7 10
> D=diag(1:3) #costruisce una matrice diagonale
> A=matrix(0,3,3) # crea una matrice di zeri
> A=edit(A) # inserisci dei valori nella matrice
1.4 Dataframe
> X=data.frame(a=1:4, sesso=c("M","F","F","M")) #crea un dataframe
#con una variabile ‘quantitativa’ e una ‘qualitativa’.
> X
a sesso
1 1 M
2 2 F
3 3 F
4 4 M
> dim(X)
[1] 4 2
> X$eta=c(2.5,3,5,6.2) #aggiungi una variabile
> X
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
4
a
1
2
3
4
sesso eta
1 M 2.5
2 F 3.0
3 F 5.0
4 M 6.2
> X[X$sesso=="M","eta"] #guarda eta per i maschi
[1] 2.5 6.2
> X$sesso[X$eta<=3] #guarda sesso per cui eta<=3
1.4 Array
> a=array(1:24,c(3,4,2)) #crea un array
> a #guardalo
1.4 Liste
> lista=list(oggetto1=a,oggetto2=X) #crea una lista
> lista$oggetto2 #guarda un oggetto della lista
Esercizio
Calcolare la media aritmetica e la varianza
1 n
(xi − x )2
s2 =
∑
n − 1 i=1
delle vendite di un certo quotidiano di un edicolante in una settimana:
lunedì
martedì
mercoledì
giovedì
venerdì
sabato
50
84
44
43
40
65
2. Le funzioni
In R esistono tantissime funzioni diverse. Ad esempio
mean()
summary()
sum()
var()
Altre possono essere costruite e caricate. Per fare questo è comodo utilizzare un editor. In linux esistono
diverse possibilità fra cui KATE e Emacs Speack Statistics (ESS).
Proviamo a costruire la funzione che calcola la varianza.
varianza=function(vettore)
{
numobs=length(vettore)
varianza=sum((vettore-mean(vettore))^2)
varianza=varianza/(numobs-1)
return(varianza)
}
Una volta che la funzione è stata scritta su un editor per compilarla e quindi renderla disponibile in R si
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
5
può procedere in due modi: o con copia ed incolla, oppure occorre salvarla in un file chiamato ad esempio
“varianza.R” e digitare nella console:
source(“varianza.R”)
Si può costruire anche una funzione che riporti in uscita più oggetti attraverso le liste. Vogliamo costruire
una funzione che restituisca in output media e varianza:
media.var=function(vettore)
{
numobs=length(vettore)
media=mean(vettore)
varianza=sum((vettore-media)^2)
varianza=varianza/(numobs-1)
return(list(media=media,var=varianza))
}
Oppure si può costruire una funzione che prenda in entrata più oggetti. Ad esempio dato un certo capitale
e un certo tasso di interesse mensile si vuole calcolare il montante dopo 6 mesi (capitalizzazione
semplice) M=C(1+6i):
calcola.montante=function(capitale,interesse,mesi=6)
{
montante=capitale*(1+interesse*mesi)
return(montante)
}
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
6
3. La programmazione in R
Il ciclo for:
for (name in vector) {commands}
Esempio: i numeri di Fibonacci
Calcolare i primi 12 numeri di Fibonacci.
Fibonacci=rep(0,12)
Fibonacci[1]=1
Fibonacci[2]=1
for (i in 3:12) Fibonacci[i]=Fibonacci[i-2]+Fibonacci[i-1]
La condizione if:
if (condition) {commands when TRUE}
if (condition) {commands when TRUE} else {commands when FALSE}
Esempio: il crivello di Eratostene
Il crivello di Eratostene è un antico procedimento per il calcolo delle tabelle di numeri primi fino a un
certo numero n prefissato. Il procedimento è il seguente: si scrivono tutti i naturali a partire da 2 fino n
in un elenco detto setaccio. Poi si cancellano (setacciano) tutti i multipli del primo numero del setaccio
(escluso lui stesso). Si prosegue così fino ad arrivare in fondo. I numeri che restano sono i numeri primi
minori od uguali a n. Si può dimostrare che il procedimento di setacciatura per ricercare i primi fino ad
un certo numero n cessa sempre quando si supera la radice quadrata di n.
Eratostene=function(n)
{
if (n>=2) {
sieve=seq(2,n)
primi=c()
for (i in seq(2,n)) {
if (any(sieve==i)) {
primi=c(primi,i)
sieve=c(sieve[(sieve %% i) !=0],i)
}
}
return(primi)
} else { stop(“Il valore di n deve essere almeno 2”) }
}
L'istruzione while:
while (condition) {statements}
L'istruzione repeat:
repeat {statements}
if (condition) break
Esempio: il metodo di Newton per trovare le radici di una funzione
Si tratta di un algoritmo per determinare le radici di una funzione
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
7
f(x)=0
sulla base dell'approssimazione di Taylor. Se f'(x) è la derivata prima di f(x) allora l'algoritmo consiste
nell'iterare
(x0 scelta iniziale)
xn=xn-1
–
f(xn-1)/f'(xn-1)
sino a convergenza.
Esempio
Si applichi l’algoritmo di Newton per determinare le radici della funzione f ( x) = x 3 + 2 x 2 − 7
### Newton con while###
newton.1=function(x0,tolerance=0.000001)
{
x=x0
f=x^3+2*x^2-7
while (abs(f)>tolerance) {
f.prime=3*x^2+4*x
x=x-(f/f.prime)
f=x^3+2*x^2-7
}
return(x)
}
### Newton con repeat###
newton.2=function(x0,tolerance=0.000001)
{
x=x0
repeat {
f=x^3+2*x^2-7
if (abs(f) < tolerance) break
f.prime=3*x^2+4*x
x=x-(f/f.prime)
}
return(x)
}
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
8
4. Simulazione
4.1 Generazione di numeri casuali
Generazione di numeri pseudo-casuali
Esistono diversi modi per generare una sequenza di numeri nell’intervallo [0,1] che ha tutte le
caratteristiche di una sequenza casuale (ma non lo è perciò la si definisce pseudo-casuale). Un algoritmo
molto semplice è il seguente. Si fissi un numero intero m e un numero intero b<m, non uno fra i divisori
di m. Si scelga un valore di partenza indicato con x0 chiamato seed. Per generare una sequenza di numeri
pseudo-casuali (u1,u2,…,un) si può procedere come segue:
x1 = b x0 mod m
u1 = x1/m
dove u1 è il primo numero pseudo-casuale. Il secondo lo si ottiene come:
x2 = b x1 mod m
u2 = x2/m
e così via.
Esempio
Costruire il programma che generi una sequenza di numeri casuali dati un seme (seed) e i valori per b ed
m. Eseguire il programma con m=7 e b=3.
genera.random=function(n,seme=1,m=100000,b=trunc(sqrt(m)))
{
num.casuali=rep(0,n)
for (i in 1:n) {seme=(b*seme)%%m
num.casuali[i]=seme/m
}
return(num.casuali)
}
Cosa succede se b è un divisore di m? Quale problema si può riscontrare quando m è un numero non
elevato?
Generazione di numeri (pseudo-)casuali da una uniforme
runif(n,min=a,max=b)
Esempio
Generare 1000 osservazioni da due variabili aleatorie X1 e X2 distribuite secondo una uniforme in [0,1].
Farne uno scatterplot. Sono indipendenti? Costruirne poi la variabile somma e la variabile differenza e
farne uno scatterplot. Misurare la correlazione fra le due coppie di variabili.
set.seed(1) ## per fissare un punto di partenza comune
x1=runif(1000)
x2=runif(1000)
plot(x1~x2)
S=x1+x2
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
9
D=x1-x2
plot(S~D)
cor(x1,x2)
cor(S,D)
Generazione di numeri casuali da una bernoulli
Una variabile aleatoria di Bernoulli ha due esiti possibili con probabilità rispettivamente p e (1-p).
Esempio
Una prova di esame consiste di 20 domande alle quali la mia preparazione mi consente di rispondere
correttamente con una probabilità del 20%. Generare uno fra i possibili risultati all'esame.
risposte=runif(20)
risposte.corrette=(risposte<0.2)
table(risposte.corrette)
pie(table(risposte.corrette),col=c("red","green"))
La variabile aleatoria binomiale
La somma X di n prove indipendenti di Bernoulli ciascuna con probabilità p è la variabile binomiale. X
rappresenta il numero di successi in n prove.
dbinom(x,size,prob) # calcola la probabilità di avere “x” successi in
# “size” prove ciascuna con probabilità “prob”
pbinom(x,size,prob) # calcola la probabilità di avere al massimo “x”
# successi ovvero P(X≤x)
rbinom(n,size,prob) # genera n variabili binomiali
Esempio
Quale è la probabilità che in 100 lanci di una moneta non truccata si ottengano esattamente 50 teste e 50
croci? Sorprendentemente questa probabilità è alquanto bassa:
dbinom(50,100,0.5)
[1] 0.07958924
E in 20 lanci quale è la probabilità di ottenere 10 teste e 10 croci? Costruire il grafico che associa ad ogni
possibile numero di teste in 20 lanci la sua probabilità.
x=0:20
prob=rep(0,21)
for (i in 1:21) prob[i]=dbinom(x[i],20,0.5)
barplot(prob,names.arg=x)
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
10
Esempio
Si sa che in un processo industriale il 10% delle tubi prodotte da una vecchia macchina risultano difettose.
Si sa inoltre che vengono prodotti 15 tubi ogni ora. Si definisce un processo fuori controllo quando più di
4 tubi escono difettosi ogni ora. Simulare il numero di pezzi difettosi prodotti ogni ora nell'arco di 24 ore
e contare i processi fuori controllo.
pezzi.dif=rbinom(24,15,0.1)
sum(pezzi.dif>4)
La variabile aleatoria normale
La variabile aleatoria normale è caratterizzata da due parametri: la media e la standard deviation.
dnorm(x,mean,sd) # calcola la densità di probabilità
pnorm(x,mean,sd) # calcola P(X≤x) chiamata funzione di ripartizione
rnorm(n,mean,sd) # genera n variabili normali
qnorm(p,mean,sd) # restituisce il valore di ascissa (quantile) in
# corrispondenza del valore dell'integrale p
Esempio
Simulare 10000 realizzazioni da una distribuzione normale con media 50 e deviazione standard 5.2 e
costruirne l'istogramma.
x=rnorm(10000,50,5.2)
hist(x,probability=TRUE)
lines(density(x))
Esempio
Calcolare la probabilità che le realizzazioni di una variabile aleatoria 'standardizzata' (ovvero con media
zero e standard deviation 1) siano comprese nell'intervallo [-1.946, 1.946].
## Primo modo ##
prob=pnorm(-1.946)
1-2*prob ## in virtù della simmetria della distribuzione
## Secondo modo ##
n=10000000
x=rnorm(n)
compresi=(x>-1.946 & x<1.946)
sum(compresi)/n
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
11
4.2 Integrazione di Monte Carlo
Le realizzazioni dalle varie leggi distributive possono essere utilizzate per approssimare gli integrali del
tipo:
∫
b
a
g (u )du
Siano u1,u2,…,un n realizzazioni indipendenti da variabili aleatorie uniformi nell’intervallo [a,b]. Allora
per la definizione di valore atteso di una variabile aleatoria si sa
E [g (u )] = ∫ g (u )
b
a
1
du
b−a
da cui, per la legge dei grandi numeri
∫
b
a
1 n 
g (u )du = E [g (u )](b − a ) ≅  ∑ u i (b − a )
 n i =1 
Esempio
Approssimare l’integrale
5
∫ sin( x)dx (vero valore –0.7)
2
u=runif(10000,2,5)
mean(sin(u))*(5-2)
Esempio
Approssimare l’integrale doppio
10
7
∫ ∫ sin( x − y)dxdy
3
1
u=runif(10000,1,7)
v=runif(10000,3,10)
mean(sin(u-v))*(10-3)*(7-1)
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
12
5. Alcuni elementi di algebra lineare
Prendiamo una matrice quadrata A:
A=matrix(c(1,2,1.5,0.5),2,2)
Alcune proprietà:
det(A)
# calcola il determinante di A
dim(A)
# restituisce le dimensioni della matrice
diag(A) # restituisce gli elementi sulla diagonale principale di A
sum(diag(A)) # calcola la traccia di A
t(A)
# restituisce la trasposta di A
diag(diag(A)) # restituisce una matrice diagonale con gli elementi
della diagonale principale di A
eigen(A)
# calcola autovalori e autovettori di A
solve(A)
# calcola l’inversa della matrice
Prendiamo 2 matrici con le stesse dimensioni:
A=matrix(c(1,2,1.5,0.5),2,2)
B=matrix(c(0.3,1,1,-0.5),2,2)
A+B
A*B
A%*%B
# somma gli elementi delle due matrici
# moltiplica a due a due fra gli elementi delle due matrici
# fa il prodotto matriciale
Esempio
La funzione solve(A,b) restituisce la soluzione del sistema lineare Ax=b. Determinare x tale che H3
x=b con b=[1 2 3]T e H3 la matrice di Hilbert di ordine 3:
H3=1/cbind(seq(1,3),seq(2,4),seq(3,5))
b=c(1,2,3)
x=solve(H3,b)
Esempio
Trovare la scomposizione di Choleski e la scomposizione in valori singolari della matrice di Hilbert di
ordine 3.
H3.chol=chol(H3)
t(H3.chol)%*%H3.chol
H3.svd=svd(H3)
H3.svd$u%*%diag(H3.svd$d)%*%t(H3.svd$v)
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
13
6. Ottimizzazione numerica
6.1 Il metodo golden search
E’ un algoritmo numerico piuttosto semplice per trovare il minimo (supposto unico) di una funzione in
una sola variabile in un intervallo [a,b] con a<b. Consideriamo per esempio la seguente funzione
f ( x ) = x − 3 .5 + ( x − 2 ) 2
nell’intervallo [0,5]. Per visualizzare il grafico di questa funzione si può procedere in questo modo:
f=function(x) {abs(x-3.5)+(x-2)^2}
curve(f,from=1,to=5)
L’algoritmo funziona in questo modo:
1. Si parte dall’intervallo [a,b]
2. Si restringe l’intervallo in modo iterativo in [a’,b’] in modo che esso continui a contenere al suo
interno il punto di minimo
3. Ci si arresta quando b’-a’ è piccolo abbastanza e una buona approssimazione del punto di minimo
è la media dei due estremi.
Nel passo 2 dell’algoritmo si calcolano x1 e x2 interni all’intervallo di partenza ma tali che x1 < x2. Poiché
abbiamo ipotizzato esserci un unico minimo se succede f(x1)> f(x2) significa che il minimo è contenuto
nel nuovo intervallo [x1,b]; altrimenti se f(x1)< f(x2) significa che il minimo è contenuto nel nuovo
intervallo [a,x2]. Si procede iterativamente.
golden=function(f,a,b,tol=0.0000001)
{
c=100
x1=a+(b-a)/100
x2=b-(b-a)/100
f1=f(x1)
f2=f(x2)
while ( abs(b-a)>tol) if (f1>f2) {a=x1 ## b rimane b
x1=a+(b-a)/100
x2=b-(b-a)/100
f1=f(x1)
f2=f(x2)
} else {b=x2 #a rimane a
x1=a+(b-a)/100
x2=b-(b-a)/100
f1=f(x1)
f2=f(x2)}
return((a+b)/2)}
Esempio
Trovare il punto di minimo della funzione f ( x) = x − 3 + sin( x) − x − 2 . E se volessi individuarne il punto di
massimo?
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
14
6.2 Il metodo di Newton-Raphson
Se per la funzione da minimizzare esistono e si possono calcolare le prime due derivate, si può applicare
l’algoritmo di Newton-Raphson che è molto più veloce del metodo precedente. Si basa sul metodo di
Newton per trovare le radici di una funzione il cui criterio era:
(x0 scelta iniziale)
xn=xn-1 – f(xn-1)/f’(xn-1)
e si sfrutta il fatto che trovare il minimo (o il massimo) di una funzione equivale a trovare le radici della
sua derivata prima. Per questa ragione l’algoritmo di Newton-Raphson consiste nell’iterare:
(x0 scelta iniziale)
xn=xn-1 – f’(xn-1)/f ’’(xn-1)
Esempio
Trovare il punto di minimo della funzione f ( x) = e − x + x 4 .
f=function(x) exp(-x)+x^4
curve(f,from=-1,to=2)
fprime=function(x) –exp(-x)+4*x^3
fprimeprime=function(x) exp(-x) +12*x^2
### Newton con while###
newton=function(x0,fprime,fprimeprime,tolerance=0.00001)
{
x=x0
while (abs(fprime(x))>tolerance) x=x-(fprime(x)/fprimeprime(x))
return(x)
}
6.3 Altri algoritmi
In R sono implementati i maggiori algoritmi di ottimizzazione numerica nella funzione optim che prende
come argomenti principali il valore di partenza e la funzione da ottimizzare. In automatico la funzione
optim calcola le derivate qualora servano.
help(optim) ## per vedere altre opzioni
optim(0,f)
La funzione optim è in grado di individuare il minimo di funzioni di più variabili.
Esempio
Trovare il punto di minimo della funzione f (a, b) = (a − 1) + b + 3 sin( a) − 2a cos(b) .
f=function(x) (x[1]-1)+x[2]+3*sin(x[1])-2*x[1]*cos(x[2])
optim(c(1,1),f)
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
15
7. Analisi di un caso di studio: Who survived the Sinking of the Titanic?
7.1 Descrizione dei dati
On April 14th, 1912, at 11.40 p.m., the Titanic, sailing from Southampton to New York, struck an iceberg
and started to take on water. At 2.20 a.m. she sank; of the 2228 passengers and crew on board, only 705
survived. Data on Titanic passengers have been collected by many researchers. Primary references are the
Encyclopedia Titanica at
www.encyclopedia-titanica.org
For 1309 passengers, these data record whether or not a particular passenger survived, along with the
age, gender, ticket class, and the number of family members accompanying each passenger.
The list of variables is described in the table:
Name
Labels
pclass
survived
Survived
name
Name
sex
Levels
NAs
1= First class
2= Second class
3= Third class
0
0=died; 1=survived
0
0
female; male
0
age
Age (years)
263
sibsp
Number of Siblings/Spouses Aboard
0
parch
Number of Parents/Children Aboard
0
ticket
Ticket Number
0
fare
Passenger Fare (british pounds)
1
cabin
0
C=Cherbourg
Q=Queenstown
S=Southampton
embarked
boat
body
2
0
Body Identification Number
home.dest Home/Destination
1188
0
Per caricare questi dati si deve preventivamente copiare il file in formato txt sulla cartella di lavoro in cui
la console di R lavora. Se non si è sicuri del percorso esatto lo si può visualizzare digitando nella console:
getwd(). Se i dati si trovano nella directory di lavoro e il file si chiama titanic.txt per caricarlo nella
workspace si utilizza il comando:
dati=read.table("titanic.txt",header=TRUE)
dove il comando opzionale header specifica se nella prima riga del file ci sono le etichette. Di default
questo valore è impostato su FALSE. R non legge solo file di tipo txt ma anche file di excel, in formato
csv e in generale i files provenienti da più comuni programmi scientifici. Si noti che, analogamente al
comando read.table, esiste il comando write.table per scrivere su un file un oggetto contenuto
nella workspace. Esempio: write.table(dati,"titanic.bis.txt")
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
16
Per avere alcune informazioni sul dati visualizzare la dimensione e la struttura dei dati si può procedere
così:
dim(dati) #restituisce il numero di righe e di colonne
is.data.frame(dati) #restituisce vero se dati è un data.frame
class(dati) #indica il tipo di oggetto
dati[1:10,] #visualizza le informazioni sulle prime 10 persone
7.2 Sistemare i dati in modo che le variabili qualitative siano fattori
La classe fattore è una particolare modalità di R di trattare quelle, che in statistica, sono le variabili
qualitativi. Ad esempio: Maschio/Femmina, 1° classe/2° classe/3°classe ecc. Si tratta di modalità ripetute
nell’insieme dei casi.
Queste variabili potrebbero essere del tipo “character” ma è preferibile attribuire loro la classe factor
poiché questo consente di fare eventuali elaborazioni statistiche. Le modalità sono chiamate livelli del
fattore e ad ogni livello corrisponde internamente ad R un codice numerico. Infatti ad esempio vediamo
cosa succede se applichiamo il comando summary all’età, alla classe e al sesso:
is.double(dati$age)
summary(dati$age) ## calcola alcune statistiche descrittive
is.factor(dati$pclass)
is.double(dati$pclass)
summary(dati$age)
is.factor(dati$sex)
summary(dati$sex)
Non ha senso calcolare la media e le altre statistiche per la classe! Si può fare solamente un semplice
conteggio del numero dei casi: ecco perché è opportuno convertirla in fattore. Per far si che R riconosca la
classe come una variabile qualitativa occorre digitare:
dati$pclass=as.factor(dati$pclass)
In generale possiamo controllare come sono state importate le classi di ciascuna colonna del dataset
attraverso il comando:
str(dati) #elenca il nome e il tipo di colonne
e procedere ad una opportuna sistemazione dei dati in modo che:
pclass deve essere un fattore;
name deve essere un carattere;
ticket deve essere un carattere;
cabin deve essere un carattere;
body deve essere un carattere;
home destination deve essere un carattere;
dati$pclass=as.factor(dati$pclass)
dati$name=as.character(dati$name)
dati$ticket=as.character(dati$ticket)
dati$cabin=as.character(dati$cabin)
dati$body=as.character(dati$body)
dati$home=as.character(dati$home)
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
17
7.3 Calcolare alcune statistiche descrittive per le variabili del dataset.
Il comando summary può essere ora applicato a tutto il dataset: summary(dati)
Da un punto di vista grafico, il commando plot funziona anche per fattori; si digiti per esempio:
plot(dati$pclass)
Si voglia per esempio osservare l’età media separatamente per classe, oppure per sesso.
Innanzitutto occorre osservare che mean(dati$age) non restituisce la media in quanto ci sono 263
valori mancanti codificati in R con NA. In caso di valori mancanti occorre aggiungere al comando un
argomento opzionale:
mean(dati$age,na.rm=TRUE)
hist(dati$age) #per avere una idea grafica della distribuzione dell’età
var(dati$age,na.rm=TRUE)
# restituisce la varianza
sd(dati$age,na.rm=TRUE)
# restituisce lo scarto quadratico medio
min(dati$age,na.rm=TRUE)
# restituisce il minimo
max(dati$age,na.rm=TRUE)
# restituisce il massimo
median(dati$age,na.rm=TRUE)# restituisce la mediana
Se si vuole la media dell’età separatamente per classe si deve utilizzare il comando:
by(dati$age,dati$pclass,mean,na.rm=TRUE)
by(dati$age,dati$pclass,summary)
plot(dati$age~dati$pclass) # grafico chiamato boxplot
7.4 Notare che esistono molti passeggeri con più di 3 figli o parenti. Creare 2 nuovi variabili che
contengano le classi: 1,2,3, and “più di 3”.
Le nuove variabili saranno fattori. Si può procedere in questo modo:
sibsp2=dati$sibsp
parch2=dati$parch
sibsp2[dati$sibsp>3]=4
parch2[dati$parch>3]=4
dati$sibsp2=as.factor(sibsp2)
dati$parch2=as.factor(parch2)
7.5 Creare una nuova variabile per l’età suddivisa nelle classi: [0-21), [21-28), [28-39), [39,80].
age2=dati$age
age2[dati$age<21]=1
age2[dati$age>=21 & dati$age < 28]=2
age2[dati$age>=28 & dati$age < 39]=3
age2[dati$age>=39]=4
dati$age2=as.factor(age2)
7.6 Calcolare la proporzione di sopravvissuti per intervallo di età, classe e sesso.
by(dati$survived,dati$age2,mean)
by(dati$survived,dati$pclass,mean)
by(dati$survived,dati$sex,mean)
Questo consente di rispondere a una domanda del tipo: D1: “quale è stata la frazione dei sopravvissuti
fra i maschi?”.
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
18
Un altro tipo di domanda poteva essere: D2: “quale è stata la frazione dei maschi fra i sopravvissuti?”
E ancora D3: “quale è stata la frazione dei maschi sopravvissuti fra il totale dei passeggeri”?
Sono 3 tipi di domande diverse a cui si risponde con informazioni diverse. Costruiamo innanzitutto una
tabella doppia:
tabella=table(dati$survived,dati$sex)
barplot(tabella,beside=TRUE,legend=TRUE,col=c("violet","seagreen"))
Il grafico mette in luce come il numero di donne sopravvissute sia più alto di quello dei maschi
(attenzione si tratta di valore assoluti e non di percentuali).
Il comando prop.table calcola le frequenze relative di una tabella a partire dalla tabella contente le
frequenze assolute.
D1:
D2:
D3:
prop.table(tabella,2) # 19.09%
prop.table(tabella,1) # 32.20%
prop.table(tabella)
# 12.29%
7.7 Indicare se la probabilità di sopravvivenza è influenzata da ciascuna delle seguenti caratteristiche:
classe, età, sesso.
A questa domanda si ricorre effettuando il test del Chi quadrato che verifica l’ipotesi nulla che i due
caratteri via via considerati siano fra loro indipendenti.
chisq.test(table(dati$survived,dati$pclass))
chisq.test(with(dati, table(survived,pclass))) # equivalente al precedente
chisq.test(with(dati, table(survived,age2)))
chisq.test(with(dati, table(survived,sex)))
I risultati mettono in luce che il sesso e la classe hanno avuto una influenza significativa sulla probabilità
di sopravvivenza.
Cinzia Viroli, Dipartimento di Scienze Statistiche, [email protected]
19