Sei sulla pagina 1di 53

Introduzione a R

Christian A. Mongeau Ospina


Corso di Statistica per l'Economia/Metodi statistici per la finanza,
Prof.ssa M. Barbieri, Roma Tre
Anno 2013/2014
Ultima modifica: 2013-10-10
R un linguaggio e ambiente di sviluppo per la statistica. Informazioni introduttive
possono essere trovate su wikipedia e in r-project.org/about.html.
Scopo di queste note quello di fornire un'introduzione a R. Si parte, quindi, assumendo
che la conoscenza di R sia nulla.
In questo documento le istruzioni in R saranno rappresentate nel seguente modo:
print("hello, world")
e i rispettivi risultati saranno riportati come:
## [1] "hello, world"
Negli esempi, oltre ai risultati dell'operazione sar presente un simbolo a inizio riga
segnalato da '##' che indica che ci che segue il risultato dell'operazione stessa.
Tutti gli esempi possono essere copiati ed eseguiti direttamente su R. Per tale motivo, il
prompt che compare su R (che solitamente > ) e che segnala la riga su cui si
scrivono le istruzioni, non verr riportato negli esempi.
Questo documento accompagnato anche da uno script in cui sono riportate solo le
istruzioni.
Chi volesse aiuto, oltre a conttattare me, pu chiedere una mano alla comunit italiana di
utenti di R (Rante) oppure rivolgersi direttamente alla mailing list della comunit
internazionale (R-help). Attenzione: chi si volesse scrivere a R-help deve tenere conto
che una mailing list in cui vengono inviati tanti messaggi al giorno; la mailing list del
Rante , invece, un luogo molto pi tranquillo e una risposta ad ogni dubbio (in italiano!)
non mancher di sicuro.

Page 1 of 53

Installazione
Windows
Istruzioni complete
Visitare il sito www.r-project.org e cliccare sul link CRAN che si trova sul menu a sinistra
(sotto la voce Download, Packages). Da quest'ultima pagina possibile selezionare un
mirror da cui scaricare R. Sotto la voce Italy possibile selezionare uno dei 3 mirror.
Supponendo di aver scelto Padova, dovremmo trovarci alla pagina cran.stat.unipd.it. Da
qui, cliccare sul primo link: Download R X.Y.Z for Windows (dove X.Y.Z il numero di
versione di R pi recente). Dopo aver eseguito il file, R dovrebbe trovarsi in una cartella
del tipo C:\Programmi\R\R-X.Y.Z\ (il percorso esatto dipende da dove si scelto di
installare il programma e dalla versione di R). Per avviarlo, cliccare su C:\Programmi\R\R
-X.Y.Z\bin\R.exe. Normalmente, durante l'installazione vengono messi un collegamento
nel menu Start di Windows e/o un'icona sul desktop, quindi si pu usare uno di questi
modi per avviare R pi velocemente.
Istruzioni veloci
Andare al link http://cran.stat.unipd.it/bin/windows/base/release.htm, eseguire il file che
sar scaricato, avviare R dal collegamento sul desktop e/o dal menu Start.

Linux/BSD
Il modo pi semplice di installare R su macchine Linux o BSD quello di passare
attraverso il package manager della propria distribuzione. Ad esempio, per quelle Debian
-based si dovr fare qualcosa tipo:
apt-get install r-base r-base-dev
Istruzioni pi dettagilate si trovano in:
http://rwiki.sciviews.org/doku.php?id=getting-started:installation:installation

Mac
http://cran.r-project.org/bin/macosx/

Prime operazioni con R


Una volta che R disponibile sul computer ed stato avviato, possibile cominciare a
farne conoscenza.

Page 2 of 53

Apertura, calcoli e chiusura


Quando si apre R ci si trova di fronte a un prompt indicato (di default) da > dove
possono essere scritte le istruzioni. Cominciamo a vedere semplici operazioni e il loro
risultato. Da notare che ogni riga che comincia col simbolo # un commento e verr
completamente ignorata da R.
# Semplici operatori matematici
1 + 2
## [1] 3
3*4
## [1] 12
6^2
## [1] 36
(1+2)*4-(5+3)^2
## [1] -52
# Operazioni tramite funzioni
sqrt(16)
## [1] 4
abs(-10)
## [1] 10
log(10) # In base e, mentre in base 10 sarebbe log10(10)
## [1] 2.303
cos(pi)
## [1] -1

Page 3 of 53

Negli esempi precedenti, oltre a comuni operazioni aritmetiche, sono riportate anche
alcune funzioni. In R, le funzioni sono scritte come nome(parametro) dove nome il
nome della funzione e parametro (racchiuso tra parentesi tonde) il parametro che viene
ad essa passato. Ad esempio, in sqrt(16) la funzione sqrt() e il parametro 16, mentre
in cos(pi) la funzione cos() e il parametro pi. In quest'ultimo caso, il parametro un
oggetto di R e rappresenta il valore del pi greco (3.141593). Funzioni pi complesse
avranno bisogno di pi parametri, ma questo verr visto successivamente.
Solitamente i risultati delle varie operazioni li si vuole conservare da qualche parte. A tal
fine, R consente si assegnare a vari oggetti l'output delle operazioni.
# Assegnare direttamente valori
a <- 8
a
## [1] 8
# Lo stesso risultato
a = 8
8 -> a
a
## [1] 8
# Assegnare il risultato di operazioni
a <- 1 + 2
a
## [1] 3
a <- 4 + sqrt(36)
# Pi istruzioni possono andare sulla stessa riga, separate
da punto e virgola
a <- 1 + 2 ; a
## [1] 3
Ci sono vari tipi di valori che possono essere assegnati alle variabili: scalari (interi,
numerici o complessi), alfanumerici (character) e logici.

Page 4 of 53

# Scalari (numerici {[interi, reali] o complessi})


a <- 10
b <- 15.53 # Da notare il punto per indicare il separatore
decimale
x <- 3.51+1.2i
# Alfanumerici
d <- 'Ciao'
e <- 'ciao'
# Logici
f <- TRUE
g <- FALSE
h <- F
i <- T
Le stringhe alfanumeriche vanno racchiuse, indifferentemente, tra apici (a='test') oppure
virgolette (a=test).
Da notare 2 cose per i valori logici:
1. non devono essere racchiusi tra apici/virgolette (a differenza delle stringhe);
2. possono essere abbreviati con la prima lettera (ad es., a=FALSE lo stesso di
a=F).
I valori logici sono molto importanti in un ambito diverso dalla pura assegnazione, ossia
all'interno di test di condizioni. Di questo se ne discuter brevemente in seguito. Per ora
basta dire che con i valori logici si possono effettuare operazioni booleane ossia
operazioni che usano solo due valori che sono vero (TRUE) e falso (FALSE). Gli
operatori base dell'algebra booleana sono: NOT (negazione, restiruisce l'opposto del
valore logico a cui applicata; indicata in R con !), AND (congiunzione, restituisce vero
solo se entrambi i valori sono veri; indicata con &) e OR (disgiunzione, restiruisce vero
se c' almeno un valore vero; indicata con |).
# Negazione
!TRUE
## [1] FALSE
!FALSE
## [1] TRUE
# Congiunzione (o prodotto logico)
TRUE & FALSE
## [1] FALSE
TRUE & TRUE
## [1] TRUE

Page 5 of 53

FALSE & FALSE


## [1] FALSE
# Disgiunzione (o somma logica)
TRUE | FALSE
## [1] TRUE
TRUE | TRUE
## [1] TRUE
FALSE | FALSE
## [1] FALSE
Una cosa importante in R che il linguaggio case-sensitive, ossia fa distinzione fra
maiuscola e minuscola. Ad esempio, le due variabili con valori alfanumerici create sopra
sono diverse perch nella prima c' scritto Ciao (notare l'iniziale maiuscola) mentre nella
seconda ciao (l'iniziale minuscola). Questo vale non solo per il valore assegnato alle
variabili, ma anche per il nome stesso degli oggetti. Ad esempio, le seguenti sono 2
variabili che, sebbene all'inizio abbiano lo stesso valore, sono diverse:
a <- "ciao"
A <- "ciao"
a
## [1] "ciao"
A
## [1] "ciao"
a <- 10
a
## [1] 10
A
## [1] "ciao"

Page 6 of 53

L'ultimo esempio, inoltre, consente di dire che, a differenza di altri linguaggi, le variabili
non sono strettamente tipizzate: possibile cambiare il tipo di dato (scalare,
alfanumerico, logico) che la variabile stessa ha.
Per sapere la natura di un oggetto in R si pu usare la funzione mode() e volendo
sapere se un oggetto ha una natura specifica o meno si pu usare una delle funzioni
is.MODO() dove MODO sar, ad esempio, numeric, character, logical e cos via.
# Per sapere la natura degli oggetti
mode(a)
## [1] "numeric"
mode(e)
## [1] "character"
mode(g)
## [1] "logical"
# Per ottenere TRUE o FALSE in relazione alla natura di un
oggetto
is.numeric(a)
## [1] TRUE
is.character(a)
## [1] FALSE
is.logical(g)
## [1] TRUE
Volendo si pu anche cambiare il tipo di rappresentazione che R d agli oggetti, ossia
imporre che un determinato oggetto abbia un modo piuttosto che un altro. Ad esempio,
trattare un numero come una stringa alfanumerica o viceversa. da notare che a volte il
cambiamento possibile, mentre in altre si producono risultati indesiderati.
# Per sapere la natura degli oggetti
mode(a)
## [1] "numeric"

Page 7 of 53

mode(e)
## [1] "character"
mode(g)
## [1] "logical"
# Per ottenere TRUE o FALSE in relazione alla natura di un
oggetto
is.numeric(a)
## [1] TRUE
is.character(a)
## [1] FALSE
is.logical(g)
## [1] TRUE
Nel penultimo esempio (conversione character a numeric) dato che d non era un
numero, allora R non gli ha potuto dare la natura di numeric e quindi ha generato un NA
che significa Not Available dando il corrispodente Warning. Qui bisogna stare attenti,
perch all'interno di uno script questo Warning non ne blocca la sua esecuzione e quindi
si potrebbero ottenere risultati strani. Nell'ultimo esempio (da character a numeric),
invece, tutto andato a posto perch, sebbene a fosse in quel caso una stringa
alfanumerica pari a '10', R la pu traformare senza perdita di informazione in un 10
numerico.
Finora sono stati creati vari oggetti. Che fine fanno? Sono conservati nel workspace. Per
vedere gli oggetti presenti nel workspace si pu usare:
# Per controllare quali sono gli oggetti presenti nel
"workspace"
ls()

Page 8 of 53

## [1] "a"
"altezza"

## [4] "animale_domestico"
"arr"

## [7] "b"
"corso"

## [10] "csv_int"
"d"

## [13] "df"
"eserc"

## [16] "f"
"h"

## [19] "i"
"lis"

## [22] "mat1"
"mat3"

## [25] "mat4"
"mat6"

## [28] "mat7"
"prof"

## [31] "q1"
"sesso"

## [34] "test"
"test2"

## [37] "test3"
"test5"

## [40] "v"
"w"

## [43] "x"

"A"
"annoacc"
"bmi"
"csv_ita"
"e"
"g"
"laurea"
"mat2"
"mat5"
"peso"
"q2"
"test1"
"test4"
"vec"
"X"

Di oggetti nel workspace se ne possono creare a piacere. Allo stesso modo essi possono
essere rimossi:
# Rimuovere oggetti
rm(x) # 1 per volta
rm(h,i,A) # 3 in una volta sola.
#######################
# Per rimuoverli tutti:
# rm(list=ls())
#######################
Vediamo se sono stati cancellati veramente:
# Per controllare quali sono gli oggetti presenti nel
"workspace"
ls()

Page 9 of 53

## [1] "a"
"animale_domestico"
## [4] "annoacc"
"b"

## [7] "bmi"
"csv_int"

## [10] "csv_ita"
"df"

## [13] "e"
"f"

## [16] "g"
"lis"

## [19] "mat1"
"mat3"

## [22] "mat4"
"mat6"

## [25] "mat7"
"prof"

## [28] "q1"
"sesso"

## [31] "test"
"test2"

## [34] "test3"
"test5"

## [37] "v"
"w"

## [40] "X"

"altezza"
"arr"
"corso"
"d"
"eserc"
"laurea"
"mat2"
"mat5"
"peso"
"q2"
"test1"
"test4"
"vec"

Volendo fare una pausa per riprendere il lavoro in un secondo momento si possono
usare le funzioni savehistory() e save.image() che consentiranno di salvare,
rispettivamente, la storia delle istruzioni digitate (a proposito: usando le freccie su e
gi si naviga nella storia) e l'immagine del workspace; infine digitando q() si esce.
Prima, per, dove vengono salvati i file? Nella cartella di lavoro (meglio conosciuta
come working directory). Per conoscere la working directory, bisogna usare la funzione
getwd(), per cambiarla si usa setwd() e per vederne i contenuti dir().
# Conoscere e dichiarare la "working directory" e conoscere
il suo contenuto
getwd()
setwd('DIRECTORY') # XXX
dir()
Nell'esempio bisogna scrivere a posto di 'DIRECTORY' il percorso della cartella che si
vuole usare, ad esempio, volendola impostare a S:\Disco\Utente\nome-della-cartella\,
si deve digitare:
setwd('S:/Disco/Utente/nome-della-cartella/')
In Windows il separatore del percorso \, mentre quando viene specificato in R deve
essere usato o /, come fatto sopra, oppure un doppio \ some segue
setwd('S:\\Disco\\Utente\\nome-della-cartella\\')

Page 10 of 53

In R possibile abbreviare la digitazione dei comandi e dei nomi dei file usando il tasto
<Tab> della tastiera. Ad esempio, invece di scrivere per esteso nome-della-cartella si
possono digitare le prime lettere seguite da <Tab> come nom<Tab> (se il nome
unico, allora comparir direttamente, mentre se c' un'altra cartella che inizia per nom R
lo far presente).
Una volta conosciuta (o impostata) la working directory, si sa dove saranno scritti i file e,
quindi, possono essere salvati per riprenderli successivamente.
savehistory("interruzione.txt")
save.image("interruzione.RData")
q()
Nell'ultimo esempio, si visto che la funzione q() stata invocata senza parametri,
mentre le due precedenti (save.image() e savehistory()) lo sono state con un parametro
(dato dal nome del file che si voleva scrivere). In R, molte funzioni possono essere
invocate senza parametri dato che hanno valori di default oppure chiederanno all'utente
cosa fare. Nel caso della funzione q() R ci chiede cosa fare, mentre se avessimo digitato
q('yes') R sarebbe stato chiuso immediatamente, ma prima avrebbe invocato le funzioni
save.image() e savehistory() che, non avendo usato parametri, avrebbero salvato i
rispettivi file con dei nomi di default: .RData e .Rhistory.

IMPORTANTE AI FINI DELL'ESAME


Quando farete l'esame, vi verr chiesto di fare degli esercizi con R e di riportare i risultati
sui fogli che vi verranno messi a disposizione. Oltre a questo, vi verr chiesto di salvere i
risultati delle vostre operazioni e le istruzioni digitate in un file di testo. Questo si pu fare
anche attraverso dei menu:
File > Salva su file
Nella seguente schermata si vede da dove si raggiunge questa voce.

Page 11 of 53

(Nell'immagine si vede in inglese File > Save to File, ma se si ha la versione in


italiano, il menu quello visto poco sopra.)

Aiuto!
Due funzioni da memorizzare (ad ogni costo) sono help() e help.search() che servono
(ed anche evidente) ad ottenere aiuto. Con help() si chiede ad R di dirci che cosa o
fa un oggetto e come lo si usa, mentre con help.search() R cerca all'interno di tutta la
sua documentazione la stringa che gli si passa come parametro. L'uso che si fa di queste
funzioni , sostanzialmente, quello di cercare la documentazione di una funzione tramite
help(FUNZIONE) (dove FUNZIONE il nome (senza parentesi) di una funzione, ad
esempio getwd) e di cercare tra la documentazione una funzione di cui non si conosce il
nome, ma si sa cosa fa (o dovrebbe fare) con help.search('STRINGA') (dove
'STRINGA' (da notare che tra apici/virgolette) una parola legata al funzionamento
della funzione che si cerca, ad esempio help.search('directory') perch magari si vuole
una funzione che crei una cartella).

Page 12 of 53

# Ottenere aiuto
help(getwd)
# Oppure pi semplicemente (non sono necessarie
virgolette/apici)
?getwd
# Cercando una parola
help.search('directory')
# Oppure pi semplicemente
??directory
# Per raffinare i risultati usare una parola o frase pi
specifica
??'working directory'
Come si vede sopra, le due funzioni hanno delle abbreviazioni: ? (un segno interrogativo)
per help() e ?? (due segni interrogativi) per help.search(). Nel caso di ?? non sono
necessari apici/virgolette per parole singole, anche se quando la parola speciale (ad
ese. if, while, ecc.) queste devono essere messe. Per evitare i problemi relativi alle
parole speciali meglio, quindi, meglio mettere sempre gli apici/virgolette con ?? (dato
anche che se la stringa contiene spazi bisogna comunque metterle).

Riprendere il lavoro
Riaprendo R, interroghiamolo sul valore della working directory e, se necessario,
cambiamola in quella in cui abbiamo ci sono i nostri file (aiuto: usare getwd() ed
eventualmente setwd()).
Per caricare la storia e il workspace salvato in precedenza si usano due funzioni che
hanno come parametro il nome del rispettivo file
loadhistory('interruzione.txt')
load('interruzione.Rdata')
Se tutto andato bene, si dovrebbero vedere gli oggetti creati in precedenza
# Per controllare quali sono gli oggetti presenti nel
"workspace"
ls()

Page 13 of 53

## [1] "a"
"animale_domestico"
## [4] "annoacc"
"b"

## [7] "bmi"
"csv_int"

## [10] "csv_ita"
"df"

## [13] "e"
"f"

## [16] "g"
"lis"

## [19] "mat1"
"mat3"

## [22] "mat4"
"mat6"

## [25] "mat7"
"prof"

## [28] "q1"
"sesso"

## [31] "test"
"test2"

## [34] "test3"
"test5"

## [37] "v"
"w"

## [40] "X"

"altezza"
"arr"
"corso"
"d"
"eserc"
"laurea"
"mat2"
"mat5"
"peso"
"q2"
"test1"
"test4"
"vec"

anche possibile salvare solo un singolo oggetto, oppure solo alcuni, invece che tutto il
contenuto del workspace. Volendo salvare solo 2 oggetti, ad esempio b e d, l'istruzione
da dare :
# Salviamo solo 'b' e 'd'
save(b, d, file='oggetti.RData')
Da notare come, rispetto a prima, la funzione solo save() e non save.image().

Oggetti pi complessi
Finora gli oggetti visti contengono solo un valore. Oggetti pi complessi sono i vettori, le
matrici, gli array, i data.frame e le liste.

Vettori, matrici e array


Questi oggetti possono essere solo di un certo tipo; si possono, cio, avere o tutti valori
numerici o tutti alfanumerici o tutti logici, ecc. all'interno di un vettore/matrice/array.
Vettori
I vettori si possono creare con la funzione c().

Page 14 of 53

vec <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)


# Per valori ordinati ci sono scorciatoie ...
vec <- seq(1, 10)
vec <- 1:10
# In tutti e 3 i casi indicati sopra il risultato lo
stesso
vec
##

[1]

9 10

# Indicando l'argomento 'by' saltiamo numeri


seq(1, 10, by=2)
## [1] 1 3 5 7 9
# Si pu anche avere un ordinamento decrescente
seq(10, 1)
##

[1] 10

0 -1 -2 -3 -4 -5 -6

4:-6
##

[1]

# I vettori non sono solo numerici!


c('valore 1', 'val2', 'valore3')
## [1] "valore 1" "val2"

"valore3"

c(TRUE, FALSE, FALSE)


## [1]

TRUE FALSE FALSE

# Per creare vettori senza assegnare valori


v <- c()
v <- vector()
# Se si vuole dichiarare esplicitamente la natura di dati
che dovr contenere
v <- vector(mode='character') # oppure 'numeric', 'logical',
ecc.

Page 15 of 53

Nell'esempio sopra si visto come ci sia una funzione, seq() che consente di generare
un vettore con un insieme ordinato si elementi, eventualmente indicando la distanza tra
un numero e l'altro con l'argomento by. Se la sequenza semplice, nel senso che non
bisogna specificare un by, si pu usare la sintassi che prevede due punti tra il numero
iniziale e il numero finale.
ESERCIZIO 1: C' una funzione che consente di creare un vettore con un numero a
piacere di valori replicati (ad esempio, c(100, 100, 100, 100, 100) oppure c(1, 2, 1, 2, 1,
2)). Qual ? Per arrivare alla risposta conviene pensare a come si chiede aiuto a R.
(Suggerimento: pensare a cosa si vuole fare in inglese; se non si trova al primo colpo,
pensare a un sinonimo.)
Alcune utili operazioni che si possono fare (anche) sui vettori sono: length() (lunghezza
del vettore), sum() e prod() (rispettivamente sommatoria e produttoria degli elementi),
max() e min() (massimo e minimo), ecc.
length(vec)
## [1] 10
sum(vec)
## [1] 55
prod(vec)
## [1] 3628800
min(vec)
## [1] 1
max(vec)
## [1] 10
Tra vettori si possono fare varie operazioni. Vediamo qualche esempio.
# Calcoliamo il 20% di ogni elemento di un vettore
w <- c(100, 200, 150)
0.2*w
## [1] 20 40 30

Page 16 of 53

# Somma (simile per sottrazione, moltiplicazione, divisione)


tra elementi
q1 <- c(1, 2, 3)
q2 <- c(4, 5, 6)
q1+q2
## [1] 5 7 9
# Anche tra vettori logici
c(T,T,F,F) & c(T,F,T,F)
## [1]

TRUE FALSE FALSE FALSE

c(T,T,F,F) | c(T,F,T,F)
## [1]

TRUE

TRUE

TRUE FALSE

# Prodotto scalare
q1 %*% q2
##
[,1]
## [1,]
32
# Calcoliamo l'indice di massa corporea (o 'body mass
index' (BMI))
altezza <- c(1.75, 1.80, 1.65, 1.90, 1.74, 1.91)
peso <- c(60, 72, 57, 90, 95, 72)
bmi <- peso/altezza^2
bmi
## [1] 19.59 22.22 20.94 24.93 31.38 19.74
# Cosa succede se non abbiamo incluso un dato in uno dei
vettori?
peso <- c(60, 72, 57, 90, 95) # notare che manca il 72
bmi <- peso/altezza^2
## Warning: longer object length is not a multiple of
shorter object length
bmi # l'ha calcolato lo stesso *riciclando* il primo
elemento
## [1] 19.59 22.22 20.94 24.93 31.38 16.45

Page 17 of 53

peso <- c(60, 72, 57, 90, 95, NA) # meglio specificare che
il dato manca
bmi <- peso/altezza^2
bmi
## [1] 19.59 22.22 20.94 24.93 31.38

NA

molto importante notare che c' stato un warning sopra quando si provato a fare
un'operazione tra vettori di lunghezza diversa: R comunque andato avanti, ma s'
lamentato. Il modo in cui il programma ha continuato le operazioni attraverso
un'operazione detta riciclaggio che consiste nel riutilizzare gli elementi dell'oggetto la cui
dimensione inferiore in modo che la dimensione di tutti gli oggetti coinvolti sia la stessa.
Sembra complicato, ma semplice: se si vede che cosa successo nell'esempio,
quando R arrivato all'ultimo soggetto (quando non era stato ancora esplicitato che il
dato era NA) dato che la dimensione del vettore 'peso' era inferiore a quella del vettore
'altezza' ha preso di nuovo il primo elemento di 'peso' mettendolo a posto di quello che
doveva essere il valore del peso all'ultima posizione del vettore 'altezza' facendo in
modo, quindi, che i 2 vettori avessere la stessa dimensione. Questo comportamento pu
essere una bella fonte di guai, quindi bisogna prestare particolare attenzione.
Dei vettori si possono selezionare alcuni elementi in base ai loro indici o a condizioni
logiche indicando gli elementi/condizioni all'interno di parentesi quadre dopo il nome del
vettore. Nel caso di selezione tramite condizioni logiche, l'importante ricordarsi che ci
devono essere tanti valori TRUE/FALSE quanti sono gli elementi che si vogliono
segliere/escludere e che possono essere usati gli operatori dell'algebra booleana: ogni
volta che c' un TRUE R restituir il numero dell'elemento corrispondente.
# Il peso del primo e terzo soggetto
peso[c(1,3)]
## [1] 60 57
# Il peso di tutti tranne il primo...
peso[-1]
## [1] 72 57 90 95 NA
# ... e di tutti tranne il secondo e il quarto
peso[-c(2,4)]
## [1] 60 57 95 NA
# Il peso di tutti i soggetti per cui si ha il dato
(escludendo, cio, NA)
peso[!is.na(peso)]
## [1] 60 72 57 90 95

Page 18 of 53

# Come sopra, ma solo se il peso superiore a 70


peso[!is.na(peso) & peso>70]
## [1] 72 90 95
# Possono essere usati altri vettori, a patto che la
lunghezza sia la stessa
peso[!is.na(peso) & altezza>1.80]
## [1] 90
ESERCIZIO 2: Che cosa bisogna fare per trovare il peso dei soggetti per cui si ha il dato,
ma solo se maggiore di 70 chili? (Suggerimento: rileggere quello che stato detto
appena prima degli esempi qui sopra, soprattutto quello che riguarda l'algebra booleana.)
Matrici
Le matrici sono definite come oggetti bidimensionali che hanno un certo numero di righe
e colonne (il vettore un caso particolare di matrice, avendo solo 1 colonna). Per creare
una matrice si possono concatenare 2 o pi vettori attraverso, rispettivamente, le funzioni
cbind() e rbind(), oppure tramite la funzione matrix(). Per sapere la dimensione della
matrice si usa la funzione dim() (non length() che usata per vettori); anche qui con la
funzione mode() (come con gli scalari e i vettori) si pu vedere che tipo di dato contiene
l'oggetto.
mat1 <- cbind(altezza, peso)
mat1
##
##
##
##
##
##
##

[1,]
[2,]
[3,]
[4,]
[5,]
[6,]

altezza peso
1.75
60
1.80
72
1.65
57
1.90
90
1.74
95
1.91
NA

dim(mat1)
## [1] 6 2
ncol(mat1)
## [1] 2
nrow(mat1)

Page 19 of 53

## [1] 6
mode(mat1)
## [1] "numeric"
mat2 <- rbind(altezza, peso)
mat2
##
[,1] [,2] [,3] [,4] [,5] [,6]
## altezza 1.75 1.8 1.65 1.9 1.74 1.91
## peso
60.00 72.0 57.00 90.0 95.00
NA
dim(mat2)
## [1] 2 6
mat3 <- matrix()
mat3
##
[,1]
## [1,]
NA
mat3 <- matrix(1, ncol=3, nrow=4)
dim(mat3)
## [1] 4 3
mat3 <- matrix(1:9, ncol=3, nrow=3)
mat3
##
[,1] [,2] [,3]
## [1,]
1
4
7
## [2,]
2
5
8
## [3,]
3
6
9
# Estrarre la diagonale principale da una matrice ...
diag(mat3)
## [1] 1 5 9

Page 20 of 53

# ... oppure creare matrici diagonali (s, diag() ha due


usi)
diag(1, 3) # matrice identit 3x3
##
[,1] [,2] [,3]
## [1,]
1
0
0
## [2,]
0
1
0
## [3,]
0
0
1
diag(1:4, 4)
##
##
##
##
##

[1,]
[2,]
[3,]
[4,]

[,1] [,2] [,3] [,4]


1
0
0
0
0
2
0
0
0
0
3
0
0
0
0
4

# Se solo 1 dimensione specificata R cerca di riempire


l'oggetto...
mat3 <- matrix(rep(c(TRUE, FALSE), 6), ncol=3)
mat3 <- matrix(rep(c("valore1", "valore2"), 6), ncol=3)
mode(mat3)
## [1] "character"
mat3
##
##
##
##
##

[1,]
[2,]
[3,]
[4,]

[,1]
"valore1"
"valore2"
"valore1"
"valore2"

[,2]
"valore1"
"valore2"
"valore1"
"valore2"

[,3]

"valore1"
"valore2"
"valore1"
"valore2"

# ... anche quando la lunghezza dei dati non (sotto)multiplo della dimensione
mat3 <- matrix(rep(c("valore1", "valore2"), 10), ncol=3) #
warning, comunque
## Warning: data length [20] is not a sub-multiple or
multiple of the number
## of rows [7]
mat3

Page 21 of 53

##
##
##
##
##
##
##
##

[1,]
[2,]
[3,]
[4,]
[5,]
[6,]
[7,]

[,1]
"valore1"
"valore2"
"valore1"
"valore2"
"valore1"
"valore2"
"valore1"

[,2]
"valore2"
"valore1"
"valore2"
"valore1"
"valore2"
"valore1"
"valore2"

[,3]

"valore1"
"valore2"
"valore1"
"valore2"
"valore1"
"valore2"
"valore1"

Le operazioni che possono essere applicate alle matrici possono essere intese come
operazioni che operano sui singoli elementi della matrice oppure come vere operazioni
matriciali (dove si sfrutta, cio, la struttura a matrice).
# Va bene abbreviare ncol con nc e nrow con nr
mat4 <- matrix(1:4, nc=2, nr=2)
mat4
##
[,1] [,2]
## [1,]
1
3
## [2,]
2
4
# Si pu omettere una dimensione quando superfluo farlo
mat5 <- matrix(5:8, nr=2)
mat5
##
[,1] [,2]
## [1,]
5
7
## [2,]
6
8
mat6 <- rbind(mat5, c(11,14))
mat6
##
[,1] [,2]
## [1,]
5
7
## [2,]
6
8
## [3,]
11
14
mat7 <- cbind(c(-20,16,-1), mat6)
mat7
##
[,1] [,2] [,3]
## [1,] -20
5
7
## [2,]
16
6
8
## [3,]
-1
11
14
# Alcune operazioni sui singoli elementi
2*mat4

Page 22 of 53

##
[,1] [,2]
## [1,]
2
6
## [2,]
4
8
mat5^2
##
[,1] [,2]
## [1,]
25
49
## [2,]
36
64
sum(mat4)
## [1] 10
max(mat5)
## [1] 8
# Operazioni matriciali (in senso stretto)
mat4 + mat5 # OK, perche hanno la stessa dimensione (2x2)
##
[,1] [,2]
## [1,]
6
10
## [2,]
8
12
mat4 %*% t(mat6) # bisogna trasporla in modo che 2x2 * 2x3
##
[,1] [,2] [,3]
## [1,]
26
30
53
## [2,]
38
44
78
# Trasposta, determinante e inversa
X <- matrix(0:3, nc=2)
X
##
[,1] [,2]
## [1,]
0
2
## [2,]
1
3
t(X)
##
[,1] [,2]
## [1,]
0
1
## [2,]
2
3

Page 23 of 53

det(X)
## [1] -2
solve(X) # guardare l'help di "solve"; in questo caso d
l'inversa di X
##
[,1] [,2]
## [1,] -1.5
1
## [2,] 0.5
0
Il modo in cui si possono indicare elementi da una matrice simile a quanto visto per i
vettori, ma bisogna tenere conto che in questo caso le dimensioni sono due. Inoltre, non
indicando alcun vincolo per una delle due dimensioni significa che verranno considerati
tutti gli indici associati a quella dimensione.
# Considerando tutte le colonne (ossia vincolando per riga)
mat7[2,]
## [1] 16

mat7[c(1,3),]
##
[,1] [,2] [,3]
## [1,] -20
5
7
## [2,]
-1
11
14
mat7[-1,]
##
[,1] [,2] [,3]
## [1,]
16
6
8
## [2,]
-1
11
14
# Considerando tutte le righe (ossia vincolando per colonna)
mat7[,3]
## [1]

8 14

mat7[,c(3,1)] # da notare che stata scelta prima la


colonna 3 e poi la 1

Page 24 of 53

##
[,1] [,2]
## [1,]
7 -20
## [2,]
8
16
## [3,]
14
-1
mat7[,3]
## [1]

8 14

# Vincolando sia per riga che per colonna


mat7[1:2, c(1,3)]
##
[,1] [,2]
## [1,] -20
7
## [2,]
16
8
mat7[-3, -2] # lo stesso risultato di prima
##
[,1] [,2]
## [1,] -20
7
## [2,]
16
8
Array
Gli array sono una generalizzazione della matrice a una terza dimensione. Ossia, mentre
la matrice ha due dimensioni, l'array ne ha una terza (immaginarsi un numero di matrici
una a fianco all'altra).
La creazione di array con un contenuto e una dimensione definiti si ottiene passando alla
funzione array() i suoi elementi e la dimensione.
arr <- array(1:24, dim = c(4,3,2)) # gli elementi sono 4x3x2
= 24
# Riciclaggio
array(1:23, dim = c(4,3,2)) # notare che l'1 compare per
primo e per ultimo!

Page 25 of 53

##
##
##
##
##
##
##
##
##
##
##
##
##
##
##

, , 1

[,1] [,2] [,3]


[1,]
1
5
9
[2,]
2
6
10
[3,]
3
7
11
[4,]
4
8
12

, , 2

[,1] [,2] [,3]


[1,]
13
17
21
[2,]
14
18
22
[3,]
15
19
23
[4,]
16
20
1

Come si vede, anche in questo caso bisogna fare attenzione al meccanismo del
riciclaggio: nell'ultimo esempio sono stati indicati 23 valori per un array che ne dovrebbe
contenere 24, quindi R ha usato il primo elemento, l'ha replicato e l'ha messo a posto di
quello che non era stato indicato (l'ultimo).
Le operazioni sugli array seguono una logica simile a quella matriciale.
Pure per gli array possibile indicare sotto-elementi esplicitando le dimensioni che
devono essere selezionate. Ricordare che non indicare una dimensione equivale a
scegliere tutti gli indici di quella dimensione.
arr[1:2,,]
##
##
##
##
##
##
##
##
##
##
##

, , 1

[,1] [,2] [,3]


[1,]
1
5
9
[2,]
2
6
10

, , 2

[,1] [,2] [,3]


[1,]
13
17
21
[2,]
14
18
22

arr[,c(1,3),]

Page 26 of 53

##
##
##
##
##
##
##
##
##
##
##
##
##
##
##

, , 1

[,1] [,2]
[1,]
1
9
[2,]
2
10
[3,]
3
11
[4,]
4
12

, , 2

[,1] [,2]
[1,]
13
21
[2,]
14
22
[3,]
15
23
[4,]
16
24

arr[,,-1]
##
##
##
##
##

[1,]
[2,]
[3,]
[4,]

[,1] [,2] [,3]


13
17
21
14
18
22
15
19
23
16
20
24

arr[1:2,2:3,1]
##
[,1] [,2]
## [1,]
5
9
## [2,]
6
10

Data.frame
I data.frame sono oggetti simili alle matrici, ma mentre queste ultime possono contenere
valori di un solo tipo (ad esempio solo numeri, oppure solo stringhe) i data.frame
possono avere oggetti di varia natura.
Per creare un data.frame si possono usare altri oggetti e concatenarli in colonne usando
la funzione data.frame() come si faceva con cbind(), ossia passando come parametri le
matrici o colonne da concatenare. Il modo di far riferimento a elementi specifici del
data.frame uguale a quello delle matrici, tuttavia nel caso della scelta di colonne si pu
usare un solo indice (invece di [,i] dove i una generica colonna). In realt ci sono altri
metodi, ma verranno illustrati nel paragrafo Elementi di
vettori/matrici/array/data.frame/liste. Anche il comportamento di operazioni su
data.frame generalmente simile a quanto accade con le matrici.
sesso <- c('F', 'M', 'F', 'M', 'F', 'M') # 'F' st per
Femmina, non per FALSE
laurea <- c(TRUE, F, T, FALSE, FALSE, F)
df <- data.frame(altezza, peso, sesso, laurea)
df

Page 27 of 53

##
##
##
##
##
##
##

1
2
3
4
5
6

altezza peso sesso laurea


1.75
60
F
TRUE
1.80
72
M FALSE
1.65
57
F
TRUE
1.90
90
M FALSE
1.74
95
F FALSE
1.91
NA
M FALSE

df <- data.frame(alto=altezza, peso, gender=sesso,


titolo=laurea)
df
##
##
##
##
##
##
##

1
2
3
4
5
6

alto peso gender titolo


1.75
60
F
TRUE
1.80
72
M FALSE
1.65
57
F
TRUE
1.90
90
M FALSE
1.74
95
F FALSE
1.91
NA
M FALSE

df[1] # il vettore delle altezze


##
##
##
##
##
##
##

1
2
3
4
5
6

alto
1.75
1.80
1.65
1.90
1.74
1.91

df[2] # il vettore dei pesi


##
##
##
##
##
##
##

1
2
3
4
5
6

peso
60
72
57
90
95
NA

df[3,1] # l'altezza del terzo soggetto


## [1] 1.65
df[2,3] # il sesso del secondo soggetto
## [1] M
## Levels: F M

Page 28 of 53

dim(df)
## [1] 6 4
ncol(df)
## [1] 4
nrow(df)
## [1] 6
# Pi comunemente dai data.frame si estrae cos (vedere pi
avanti):
df$peso
## [1] 60 72 57 90 95 NA
df[[2]]
## [1] 60 72 57 90 95 NA
Come si vede nel primo esempio, una volta che alcuni oggetti sono stati concatenati R
assegna un nome alla colonna dove i vari vettori sono andati a finire. D'altra parte, e si
vede nel secondo esempio, i nomi possono essere scelti a piacere avendo la
precauzione di indicare ad R i nomi delle colonne: data.frame(NOME1=vettore1,
NOME2=vettore2) dar ai vettori 1 e 2, rispettivamente, i nomi NOME1 e NOME2.

Liste
Le liste sono oggetti pi elastici, in quanto possono avere al loro interno elementi
eterogenei sia per la loro natura (numeri, stringhe, logici), sia per la loro struttura (vettori,
matrici, data.frame, ecc.). Questa struttura permette molta flessibilit, ma impone anche
una notazione particolare per l'indicazione di oggetti/elementi: nell'esempio successivo si
vedono le basi, mentre nel paragrafo successivo si daranno pi chiarimenti.
# 3 vettori: char (n=2), numeric (n=10), logical (n=3)
lis <- list( c("char 1", "char 2"), 1:9, c(F, TRUE, FALSE),
matrix(4:1, nc=2) )
lis

Page 29 of 53

##
##
##
##
##
##
##
##
##
##
##
##
##

[[1]]
[1] "char 1" "char 2"

[[2]]
[1] 1 2 3 4 5 6 7 8 9

[[3]]
[1] FALSE TRUE FALSE

[[4]]
[,1] [,2]
[1,]
4
2
[2,]
3
1

dim(lis) # non ha una propria "dimensione"


## NULL
# Si possono asseggnare nomi agli oggetti interni
lis <- list( c("char 1", "char 2"), numeri=-2:4, c(F, TRUE,
FALSE), matrice=matrix(4:1, nc=2) )
# Se si usano singole parentesi si avr una lista...
lis[2]
## $numeri
## [1] -2 -1

# ... mentre con parentesi doppie restituisce l'elemento


passato
lis[[1]] # il primo elemento, che un vettore
## [1] "char 1" "char 2"
lis[[1]][3] # *prima* si estrae l'oggetto, poi si indicizza
l'elemento
## [1] NA
lis[[4]] # il quarto elemento, che una matrice
##
[,1] [,2]
## [1,]
4
2
## [2,]
3
1
lis[[4]][2,1] # seconda riga e prima colonna della matrice

Page 30 of 53

## [1] 3

attach
Usare la notazione col dollaro per far riferimento a un oggetto di un data.frame o lista
elegante, nel senso che si sa sempre di chi figlio quell'oggetto. Ad esempio, df$peso
mi dice subito che faccio riferimento al peso nel data.frame df. D'altra parte, potrebbe
essere utile risparmiarsi un po' di digitazione evitando di dover sempre dire qual il
data.frame che si sta considerando. R consente di fare ci tramite la funzione attach().
# Per facilit di lettura i comandi possono andare su pi
righe
animale_domestico <- data.frame(
italiano=c("gatto", "cane", "coniglio"),
esperanto=c("kato", "hundo", "kuniklo"))
animale_domestico$esperanto
## [1] kato
hundo
kuniklo
## Levels: hundo kato kuniklo
esperanto # qui ci d un errore perch non esiste a s
## [1] kato
hundo
kuniklo
## Levels: hundo kato kuniklo
attach(animale_domestico)

Page 31 of 53

## The following object is masked


(position 3):
##
##
esperanto, italiano
## The following object is masked
(position 4):
##
##
esperanto, italiano
## The following object is masked
(position 5):
##
##
esperanto, italiano
## The following object is masked
(position 6):
##
##
esperanto, italiano
## The following object is masked
(position 7):
##
##
esperanto, italiano
## The following object is masked
(position 8):
##
##
esperanto, italiano
## The following object is masked
(position 9):
##
##
esperanto, italiano
## The following object is masked
(position 10):
##
##
esperanto, italiano
## The following object is masked
(position 11):
##
##
esperanto, italiano
## The following object is masked
(position 12):
##
##
esperanto, italiano
## The following object is masked
(position 13):
##
##
esperanto, italiano
## The following object is masked
(position 14):
##
##
esperanto, italiano
## The following object is masked
(position 15):
##
##
esperanto, italiano
## The following object is masked
(position 16):
##
##
esperanto, italiano
## The following object is masked
(position 17):
##
##
esperanto, italiano

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

Page 32 of 53

## The following object is masked


(position 18):
##
##
esperanto, italiano
## The following object is masked
(position 19):
##
##
esperanto, italiano
## The following object is masked
(position 20):
##
##
esperanto, italiano
## The following object is masked
(position 21):
##
##
esperanto, italiano

from animale_domestico

from animale_domestico

from animale_domestico

from animale_domestico

ls() # come prima, non esiste a s


## [1] "a"
"animale_domestico"
## [4] "annoacc"
"b"

## [7] "bmi"
"csv_int"

## [10] "csv_ita"
"df"

## [13] "e"
"f"

## [16] "g"
"lis"

## [19] "mat1"
"mat3"

## [22] "mat4"
"mat6"

## [25] "mat7"
"prof"

## [28] "q1"
"sesso"

## [31] "test"
"test2"

## [34] "test3"
"test5"

## [37] "v"
"w"

## [40] "X"

"altezza"
"arr"
"corso"
"d"
"eserc"
"laurea"
"mat2"
"mat5"
"peso"
"q2"
"test1"
"test4"
"vec"

esperanto # ma dato che si usato attach() lo trova dentro


animale_domestico
## [1] kato
hundo
kuniklo
## Levels: hundo kato kuniklo

Page 33 of 53

esperanto[italiano=='gatto'] # come si dice gatto in


esperanto
## [1] kato
## Levels: hundo kato kuniklo

# apply

Elementi di vettori/matrici/array/data.frame/liste
Vettori, matrici, array
Prima si visto come si indicano elementi di vari oggetti. Il modo di farlo per vettori,
matrici e array a questo punto dovrebbe essere abbastanza chiaro. Per comodit, gli
esempi gi visti vengono ripresentati di seguito.
# Il peso del primo e terzo soggetto
peso[c(1,3)]
## [1] 60 57
# Il peso di tutti tranne il primo...
peso[-1]
## [1] 72 57 90 95 NA
# ... e di tutti tranne il secondo e il quarto
peso[-c(2,4)]
## [1] 60 57 95 NA
# Il peso di tutti i soggetti per cui si ha il dato
(escludendo, cio, NA)
peso[!is.na(peso)]
## [1] 60 72 57 90 95
# Come sopra, ma solo se il peso superiore a 70
peso[!is.na(peso) & peso>70]
## [1] 72 90 95

Page 34 of 53

# Possono essere usati altri vettori, a patto che la


lunghezza sia la stessa
peso[!is.na(peso) & altezza>1.80]
## [1] 90
# Considerando tutte le colonne (ossia vincolando per riga)
mat7[2,]
## [1] 16

mat7[c(1,3),]
##
[,1] [,2] [,3]
## [1,] -20
5
7
## [2,]
-1
11
14
mat7[-1,]
##
[,1] [,2] [,3]
## [1,]
16
6
8
## [2,]
-1
11
14
# Considerando tutte le righe (ossia vincolando per colonna)
mat7[,3]
## [1]

8 14

mat7[,c(3,1)] # da notare che stata scelta prima la


colonna 3 e poi la 1
##
[,1] [,2]
## [1,]
7 -20
## [2,]
8
16
## [3,]
14
-1
mat7[,3]
## [1]

8 14

# Vincolando sia per riga che per colonna


mat7[1:2, c(1,3)]

Page 35 of 53

##
[,1] [,2]
## [1,] -20
7
## [2,]
16
8
mat7[-3, -2] # lo stesso risultato di prima
##
[,1] [,2]
## [1,] -20
7
## [2,]
16
8
arr[1:2,,]
##
##
##
##
##
##
##
##
##
##
##

, , 1

[,1] [,2] [,3]


[1,]
1
5
9
[2,]
2
6
10

, , 2

[,1] [,2] [,3]


[1,]
13
17
21
[2,]
14
18
22

arr[,c(1,3),]
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##

, , 1

[,1] [,2]
[1,]
1
9
[2,]
2
10
[3,]
3
11
[4,]
4
12

, , 2

[,1] [,2]
[1,]
13
21
[2,]
14
22
[3,]
15
23
[4,]
16
24

arr[,,-1]
##
##
##
##
##

[1,]
[2,]
[3,]
[4,]

[,1] [,2] [,3]


13
17
21
14
18
22
15
19
23
16
20
24

Page 36 of 53

arr[1:2,2:3,1]
##
[,1] [,2]
## [1,]
5
9
## [2,]
6
10
La cosa importante da ricordare che ci sono due diversi modi per far riferimento ad
elementi dentro vettori/matrici/array. Facendo riferimento a un vettore (l'estensione a
matrici e array facile, basta considerare le altre dimensioni) si pu:
1. indicare esplicitamente i numeri degli elementi che ci interessano {ad esempio,
vettore[2] {solo il secondo elemento}, vettore[2:5] {il secondo, terzo, quarto e
quinto}, vettore[c(2,5)] {il secondo e il quinto}} ricordando che se si mette un meno
davanti significa tutti tranne quello/i indicato/i {ad esempio, vettore[-2] {tutti tranne il
secondo}, vettore[-2:5] {tutti tranne il secondo, terzo, quarto e quinto}};
2. usare un'espressione logica che sceglier tutti gli elementi per cui vale TRUE {ad
esempio, vettore[vettore>=0] {solo i valori positivi}, vettore[!is.na(vettore)] {solo i
valori non NA, infatti la funzione is.na() indica quali elementi sono NA, ma essendo
negata {!} indica, appunto, i valori presenti}}.
Nell'ultimo caso bene tener presente che l'espressione logica usata dentro le parentesi
quadre deve avere la stessa lunghezza del vettore a cui si sta facendo riferimento: negli
esempi si fatto qualcosa del tipo vettore[vettore>0] e funziona perch l'espressione
vettore>0 ha la stessa lunghezza di vettore essendo calcolata sul vettore stesso; nulla
toglie (e anzi capita spesso) che si possano usare altri vettori, ma come detto, devono
avere la stessa lunghezza (se vettore1 e vettore2 hanno, ad esempio, 5 elementi
entrambi, allora si potr fare vettore1[vettore2>0] dato che l'espressione in parentesi
sar (supponendo che solo il primo e l'ultimo elemento siano positivi) TRUE, FALSE,
FALSE, FALSE, TRUE che ha lunghezza 5, appunto la stessa di vettore1).
data.frame e liste
Quando sono stati presentati i data.frame e le liste si sono visti solo alcuni dei modi in cui
gli oggetti al loro interno ed i loro elementi possono essere indicati. Tuttavia, in alcuni
casi pu essere meglio/conveniente usare altre notazioni. Anzi, si useranno pi spesso.
Per i data.frame, oltre a indicare gli oggetti usando una convenzione uguale a quella
delle matrici (ossia gli elementi all'interno di singole parentesi quadre), si possono
indicare impiegando le doppie parentesi quadre oppure usando un dollaro seguito dal
nome della variabile. Si vedano gli esempi riportati sotto.
df <- data.frame(alto=altezza, peso, gender=sesso,
titolo=laurea)
# Singole parentesi (viste prima)
df[1]

Page 37 of 53

##
##
##
##
##
##
##

1
2
3
4
5
6

alto
1.75
1.80
1.65
1.90
1.74
1.91

df[,1]
## [1] 1.75 1.80 1.65 1.90 1.74 1.91
df[2,]
##
alto peso gender titolo
## 2 1.8
72
M FALSE
df[2,1]
## [1] 1.8
#### Si useranno pi spesso o le "doppie parentesi" o il
"dollaro" ####
# Doppie parentesi (*non* funzionano df[[,3]] o df[[1,]])
df[[1]]
## [1] 1.75 1.80 1.65 1.90 1.74 1.91
df[[2,1]]
## [1] 1.8
# Con nome della colonna
df$alto
## [1] 1.75 1.80 1.65 1.90 1.74 1.91
df$alto[2] # l'altezza del secondo soggetto
## [1] 1.8

Page 38 of 53

# **ATTENZIONE** a questi (leggere il testo)


df$alto[df$alto>=1.80] # l'altezza solo per quelli pi alti
di 1.80
## [1] 1.80 1.90 1.91
df$gender[df$alto>=1.80] # il sesso per altezza>=1.80
## [1] M M M
## Levels: F M
df[[2]][df$alto>=1.80] # il peso per quelli pi alti di 1.80
## [1] 72 90 NA
df$laurea[df$gender=='F'] # la laurea per le femmine
## NULL
Negli ultimi 4 esempi stato usato il metodo di estrazione di elementi tramite valori logici.
Com'era stato detto, si pu impiegare un vettore logico da inserire come indicatore di
elementi da estrarre: ad esempio, vettore[vettore>=0] seleziona gli elementi positivi. In
effetti, una volta che un vettore estratto da un dataframe , appunto, un semplice
vettore e ad esso possono essere applicate le regole viste sopra.
ESERCIZIO 3: Estrarre (con un singolo comando) dal data.frame df l'altezza e il titolo dei
maschi per cui il peso presente (ossia non NA). (Suggerimento: bisogner usare anche
l'algebra booleana.)
Riguardo alle liste, in realt, non c' molto da aggiungere a quanto era stato visto prima.
Bisogna solo fare attenzione al fatto che quando si usano le singole parentesi ci che si
estrae a sua volta una lista, mentre con le doppie parentesi si estrae l'oggetto originario
dentro la lista (ad es., vettore, matrice, ecc.). Inoltre, anche con le liste possibile fare
riferimento ai nomi degli oggetti in esse contenuti tramite il dollaro.
lis <- list( c("char 1", "char 2"), numeri=-2:4, c(F, TRUE,
FALSE), matrice=matrix(4:1, nc=2) )
# Con singola parentesi: il risultato una lista
lis[1]
## [[1]]
## [1] "char 1" "char 2"
# Con doppie parentesi: il risultato l'oggetto originario
all'interno della lista...
lis[[1]]

Page 39 of 53

## [1] "char 1" "char 2"


lis[[2]]
## [1] -2 -1

lis[[4]]
##
[,1] [,2]
## [1,]
4
2
## [2,]
3
1
# ... da cui possibile estrarre gli elementi in maniera
coerente col tipo di oggetto
lis[[1]][2]
## [1] "char 2"
lis[[2]][c(1,3)]
## [1] -2

lis[[2]][lis[[2]]>0]
## [1] 1 2 3 4
lis[[4]][1,]
## [1] 4 2
# Si pu anche qui usare il dollaro
lis$numeri
## [1] -2 -1

lis$numeri[lis$numeri>0]
## [1] 1 2 3 4
lis$matrice

Page 40 of 53

##
[,1] [,2]
## [1,]
4
2
## [2,]
3
1
lis$matrice[2,1]
## [1] 3
lis$matrice[,2]
## [1] 2 1
ESERCIZIO 4: estrarre l'elemento della prima colonna della matrice all'interno della lista
lis che alla stessa posizione in cui si trova la stringa char 1 all'interno del vettore
all'interno della lista. (Suggerimento: questo relativamente difficile, quindi non bisogna
disperare; il valore da estrarre 4, che ha indice [1,1] nella matrice, e per farlo
bisogner applicare un po' di regole di estrazione insieme alla solita algebra booleana.)

matrice, array, data.frame, lista, ecc.?


Per sapere qual la struttura di un oggetto, ossia se esso , ad esempio, una matrice o
un data.frame, si pu usare una funzione generica o una specifica. La funzione generica
class() che restiruir come risultato una stringa che dice qual la struttura dell'oggetto
(ad es. matrix). Le funzioni specifiche hanno la forma di is.STRUTTURA() dove
STRUTTURA uno tra matrix, array, data.frame, list, ecc.
C', inoltre, la funzione str() che d una diversa rappresentazione della struttura
dell'oggetto. Mentre con class() ci che si ottiene la sua classe, con str() si ottiene una
visuale pi ampia della struttura dell'oggetto dato che informa circa le dimensioni, il tipo
di dati e i dati stessi (o una parte di essi).
class(mat1)
## [1] "matrix"
class(arr)
## [1] "array"
class(df)
## [1] "data.frame"
class(lis)

Page 41 of 53

## [1] "list"
is.matrix(mat1)
## [1] TRUE
is.matrix(arr)
## [1] FALSE
is.data.frame(arr)
## [1] FALSE
is.data.frame(df)
## [1] TRUE
str(arr)
##

int [1:4, 1:3, 1:2] 1 2 3 4 5 6 7 8 9 10 ...

str(mat1)
## num [1:6, 1:2] 1.75 1.8 1.65 1.9 1.74 1.91 60 72 57
90 ...
## - attr(*, "dimnames")=List of 2
##
..$ : NULL
##
..$ : chr [1:2] "altezza" "peso"
str(df)
## 'data.frame':
6 obs. of 4 variables:
## $ alto : num 1.75 1.8 1.65 1.9 1.74 1.91
## $ peso : num 60 72 57 90 95 NA
## $ gender: Factor w/ 2 levels "F","M": 1 2 1 2 1 2
## $ titolo: logi TRUE FALSE TRUE FALSE FALSE FALSE
str(lis)

Page 42 of 53

## List of 4
## $
:
## $ numeri :
## $
:
## $ matrice:

chr [1:2] "char 1" "char 2"


int [1:7] -2 -1 0 1 2 3 4
logi [1:3] FALSE TRUE FALSE
int [1:2, 1:2] 4 3 2 1

Convertire oggetti in un'altra natura/struttura


A volte pu capitare di avere un oggetto con un certo tipo di dati o con una certa struttura
e volerli convertire ad un altro tipo o struttura. Un esempio della prima situazione quello
di trasformare valori alfanumerici in valori numerici, mentre un esempio della seconda
di convertire data.frame in matrici. Le possibilit sono molte e di seguito vengono
presentati alcuni esempi concreti. (Le funzioni che fanno questo genere di cose
cominciano tutte per as.)
test <- cbind(1.2:3.2, rep("hello", 3), c(T, F, F))
mode(test)
## [1] "character"
class(test)
## [1] "matrix"
# Cambi di natura degli elementi
test1 <- as.numeric(test[,1])
test1
## [1] 1.2 2.2 3.2
mode(test1)
## [1] "numeric"
class(test1)
## [1] "numeric"
test2 <- as.integer(test[,1])
test2
## [1] 1 2 3

Page 43 of 53

mode(test2)
## [1] "numeric"
class(test2)
## [1] "integer"
test3 <- as.character(test1)
test3
## [1] "1.2" "2.2" "3.2"
mode(test3)
## [1] "character"
class(test3)
## [1] "character"
test4 <- as.logical(test[,3])
test4
## [1]

TRUE FALSE FALSE

mode(test4)
## [1] "logical"
class(test4)
## [1] "logical"
test5 <- c(4, 99, "lettere")
test5
## [1] "4"

"99"

"lettere"

Page 44 of 53

mode(test5)
## [1] "character"
as.numeric(test5) # qui viene prodotto un NA per coercizione
## Warning: NAs introduced by coercion
## [1]

4 99 NA

as.numeric(test[,3]) # anche qui


## Warning: NAs introduced by coercion
## [1] NA NA NA
as.numeric(as.logical(test[,3])) # qui OK
## [1] 1 0 0
Negli ultimi esempi (as.numeric(test5) e as.numeric(test[,3])) R ha fatto presente che ci
sono stati dei punti critici attraverso dei warning. In effetti, si cercato di trasformare in
numero cose che numeri non potevano essere trafrormate. Nel primo caso, insieme ai
due numeri c'era anche la stringa "lettere: R ha fatto quello che poteva convertendo le
stringhe 4 e 99 in numeri, mentre con lettere non ha trovato una trasformazione
soffisfacente e quindi si arreso e ha generato un NA per coercizione. Cosa simile
succede col secondo esempio: Le stringhe FALSE e TRUE non le ha potute
trasformare in numeri e quindi ha generato NA. Da notare in quest'ultimo caso una cosa
particolare: solitamente nell'algebra booleana a TRUE corrisponde 1 e a FALSE 0.
Perch, allora, R ha generato NA per coercizione? Perch quando gli sono stati passati i
TRUE e FALSE questi erano in realt stringhe (infatti erano fra virgolette) e non TRUE
e FALSE (senza virgolette) che, in questo caso, sono valori speciali essendo logici. In
effetti, una volta che nell'ultima riga le stringhe TRUE e FALSE sono state trasformate
in logici TRUE e FALSE R ha giustamente capito che erano, appunto, logici e li ha
trasformati in 1 e 0.
# Usiamo un data.frame creato in precedenza
str(df)
## 'data.frame':
6 obs. of 4 variables:
## $ alto : num 1.75 1.8 1.65 1.9 1.74 1.91
## $ peso : num 60 72 57 90 95 NA
## $ gender: Factor w/ 2 levels "F","M": 1 2 1 2 1 2
## $ titolo: logi TRUE FALSE TRUE FALSE FALSE FALSE

Page 45 of 53

class(df[,c(1,2)])
## [1] "data.frame"
x <- as.matrix(df[,c(1,2)])
class(x)
## [1] "matrix"
class(cbind(altezza, peso, bmi))
## [1] "matrix"
x <- as.data.frame(cbind(altezza, peso, bmi))
class(x)
## [1] "data.frame"

Ordinamenti
Per ordinare i dati in maniera crescente/decrescente si usa le funzioni sort(), rev() e
order(). Mentre le prime due riportano i valori dopo l'ordinamento, order() restituisce gli
indici in cui i vari elementi dovrebbero comparire una volta che sono stati ordinati. Forse
pi facile da capire vedendo gli esempi.
# Riprendiamo il data.frame df
str(df)
## 'data.frame':
6 obs. of 4 variables:
## $ alto : num 1.75 1.8 1.65 1.9 1.74 1.91
## $ peso : num 60 72 57 90 95 NA
## $ gender: Factor w/ 2 levels "F","M": 1 2 1 2 1 2
## $ titolo: logi TRUE FALSE TRUE FALSE FALSE FALSE
# L'ordinamento di default crescente
sort(df$alto)
## [1] 1.65 1.74 1.75 1.80 1.90 1.91
sort(df$peso)
## [1] 57 60 72 90 95

Page 46 of 53

sort(df$gender)
## [1] F F F M M M
## Levels: F M
sort(df$titolo)
## [1] FALSE FALSE FALSE FALSE

TRUE

TRUE

# Si puo aggingere un parametro per rendere l'ordinamento


decrescente ...
sort(df$alto, decreasing=TRUE)
## [1] 1.91 1.90 1.80 1.75 1.74 1.65
sort(df$gender, dec=T)
## [1] M M M F F F
## Levels: F M
# ... ma si poteva ottenere lo stesso risultato con "rev()"
rev(df$alto)
## [1] 1.91 1.74 1.90 1.65 1.80 1.75
rev(df$gender)
## [1] M F M F M F
## Levels: F M
# Order d gli indici in cui l'elemento dovrebbe trovarsi
order(df$alto)
## [1] 3 5 1 2 4 6
order(df$peso)
## [1] 3 1 2 4 5 6
order(df$peso, decreasing=T)

Page 47 of 53

## [1] 5 4 2 1 3 6
# Un risultato simile a "sort()" pu essere ottenuto con
"order()" ( solo dimostrativo!)
df$peso[order(df$peso)]
## [1] 57 60 72 90 95 NA
# Il trattamento degli NA in "sort()" configurabile
sort(df$peso, na.last=TRUE)
## [1] 57 60 72 90 95 NA
sort(df$peso, na.last=FALSE)
## [1] NA 57 60 72 90 95
# "order()" pu anche essere usato per ordinare per diverse
variabili
order(df$gender, df$alto)
## [1] 3 5 1 2 4 6
# I risultati di "order()" possono essere usati per ordinare
altri oggetti
df[order(df$alto),]
##
##
##
##
##
##
##

3
5
1
2
4
6

alto peso gender titolo


1.65
57
F
TRUE
1.74
95
F FALSE
1.75
60
F
TRUE
1.80
72
M FALSE
1.90
90
M FALSE
1.91
NA
M FALSE

df[order(df$gender, df$alto),]
##
##
##
##
##
##
##

3
5
1
2
4
6

alto peso gender titolo


1.65
57
F
TRUE
1.74
95
F FALSE
1.75
60
F
TRUE
1.80
72
M FALSE
1.90
90
M FALSE
1.91
NA
M FALSE

Page 48 of 53

Lettura di dati
Il metodo standard per caricare dati esterni in R quello di passare tramite CSV. I CSV
(che sta per comma-separated values) sono semplici file di testo che separano i campi
(colonne/variabili) attraverso un carattere specifico che solitamente nei paesi dove si usa
il punto come separatore decimale (ad esempio, 1,234.5) sono le virgole (da cui il nome),
mentre nei paesi dove i decimali sono indicati da una virgola (ad esempio, come in Italia,
1.234,5) il punto e virgola.
Un file CSV con 6 osservazioni e 4 variabili (le colonne sono 5: la prima e l'identificativo
del soggetto e le rimanenti 4 le variabili) pu essere dato da uno dei due modi:
Impostazioni internazionali (file di esempio: csv_int.csv)
soggetto, altezza, peso, et, sesso
1,
1.75,
70, 25,
Fem
2,
1.84,
79, 30,
Mas
3,
1.60,
50, 23,
Fem
4,
1.71,
66, 29,
Fem
5,
1.90,
99, 28,
Mas
6,
1.72,
80, 20,
Mas
impostazioni italiane (file di esempio: csv_ita.csv)
soggetto; altezza; peso; et; sesso
1;
1,85;
79; 28;
Mas
2;
1,64;
71; 31;
Fem
3;
1,80;
90; 26;
Fem
4;
1,75;
69; 30;
Fem
5;
1,91;
95; 38;
Mas
6;
1,72;
80; 20;
Mas
I file CSV possono essere creati da programmi tipo Excel (Microsoft), Calc
(OpenOffice/LibreOffice), ecc. Inoltre, molti database on-line distribuiscono i dati in
questo formato.
Per la lettura del primo tipo di file tramite R si usa la funzione read.csv(), mentre per la
lettura del secondo tipo di file si usa la funzione read.csv2(). Dato che molto probabile
che si abbiano le imporstazioni italiane nel proprio computer, allora bisogner usare la
seconda opzione, ma si deve anche sapere che necessario usare la prima nel caso di
file CSV formattati secondo l'opzione internazionale. Ad ogni modo, a parte il nome, il
funzionamento delle due funzioni identico ed indicato di seguito.
# Lettura del CSV "internazionale"
csv_int <- read.csv("csv_int.csv")
str(csv_int)

Page 49 of 53

## 'data.frame':
6 obs. of 5 variables:
## $ soggetto: int 1 2 3 4 5 6
## $ altezza : num 1.75 1.84 1.6 1.71 1.9 1.72
## $ peso
: int 70 79 50 66 99 80
## $ eta
: int 25 30 23 29 28 20
## $ sesso
: Factor w/ 2 levels "Fem","Mas": 1 2 1 1 2 2
csv_int
##
##
##
##
##
##
##

1
2
3
4
5
6

soggetto altezza peso eta sesso


1
1.75
70 25
Fem
2
1.84
79 30
Mas
3
1.60
50 23
Fem
4
1.71
66 29
Fem
5
1.90
99 28
Mas
6
1.72
80 20
Mas

# Lettura del CSV "italiano"


csv_ita <- read.csv2("csv_ita.csv") # da notare: csv2
str(csv_ita)
## 'data.frame':
6 obs. of 5 variables:
## $ soggetto: int 1 2 3 4 5 6
## $ altezza : num 1.85 1.64 1.8 1.75 1.91 1.72
## $ peso
: int 79 71 90 69 95 80
## $ et .
: int 28 31 26 30 38 20
## $ sesso
: Factor w/ 2 levels "Fem","Mas": 2 1 1 1 2 2
csv_ita
##
##
##
##
##
##
##

1
2
3
4
5
6

soggetto altezza peso et . sesso


1
1.85
79
28
Mas
2
1.64
71
31
Fem
3
1.80
90
26
Fem
4
1.75
69
30
Fem
5
1.91
95
38
Mas
6
1.72
80
20
Mas

Come si deve sapere se si deve usare read.csv() o read.csv2()? Bisogna sapere il CSV
cosa usa come separatore di campo: o la virgola (quindi read.csv()) e il punto e virgola
(quindi read.csv2()). Comunque, sempre bene fare una chiamata a str() subito dopo
aver letto i dati, in modo da vedere se la struttura di quanto appena letto coerente
con quanto ci si aspetta.
Ci sono poi metodi meno standard di leggere i dati che vanno dalla lettura di file delimitati
da tabulazione o da altro carattere specifico fino alla lettura di file excel. Quest'ultima non
verr illustrata ora in quanto si ha bisogno di una libreria, il che implica che prima
bisogna installarla, caricarla, cose che saranno spiegate successivamente. Per la
lettura di file delimitati da altri caratteri speciali, si pu usare la funzione read.delim() e
read.delim2() in maniera simile a, rispettivamente, read.csv() e read.csv2(). Di default
read.delim() e read.delim2() leggono dati delimitati da tabulazione, anche se possibile

Page 50 of 53

impiegare altri caratteri di separazione tramite il parametro sep=X dove X sar il


carattere separatore. Se poi si hanno esigenze particolari, si pu usare la funzione
read.table() di cui le precedenti funzioni sono casi particolari.
Le funzioni read.csv() e read.delim(), da una parte, e read.csv2() e read.delim2(),
dall'altra, non sono solo diverse perch le prime usano il carattere , come separatore e
le seconde usano invece ;, ma anche perch leggono i numeri in maniera diversa: il
numero 2 mila virgola 3 per le prime 2,000.2 mentre per le seconde 2.000,3 (e questo
dipende dalle impostazioni della lingua). Da notare che R, comunque, lavora
internamente con le impostazioni internazionali per l'indicazione dei decimali. Cio,
quando in R si vede 2.305 da intendersi come due virgola trecento cinque e non
duemila trecento cinque. In effetti questo era gi stato visto nel data.frame che stato
creato quando stato letto il CSV italiano (csv_ita.csv): ad esempio, il peso del primo
soggetto nel file CSV 1,80, ma una volta che R l'ha caricato l'ha convertito nel suo
formato 1.80.
# Lettura del CSV "internazionale"
csv_int <- read.csv("csv_int.csv")
str(csv_int)
## 'data.frame':
6 obs. of 5 variables:
## $ soggetto: int 1 2 3 4 5 6
## $ altezza : num 1.75 1.84 1.6 1.71 1.9 1.72
## $ peso
: int 70 79 50 66 99 80
## $ eta
: int 25 30 23 29 28 20
## $ sesso
: Factor w/ 2 levels "Fem","Mas": 1 2 1 1 2 2
csv_int
##
##
##
##
##
##
##

1
2
3
4
5
6

soggetto altezza peso eta sesso


1
1.75
70 25
Fem
2
1.84
79 30
Mas
3
1.60
50 23
Fem
4
1.71
66 29
Fem
5
1.90
99 28
Mas
6
1.72
80 20
Mas

# Lettura del CSV "italiano"


csv_ita <- read.csv2("csv_ita.csv") # da notare: csv2
str(csv_ita)
## 'data.frame':
6 obs. of 5 variables:
## $ soggetto: int 1 2 3 4 5 6
## $ altezza : num 1.85 1.64 1.8 1.75 1.91 1.72
## $ peso
: int 79 71 90 69 95 80
## $ et .
: int 28 31 26 30 38 20
## $ sesso
: Factor w/ 2 levels "Fem","Mas": 2 1 1 1 2 2
csv_ita

Page 51 of 53

##
##
##
##
##
##
##

1
2
3
4
5
6

soggetto altezza peso et . sesso


1
1.85
79
28
Mas
2
1.64
71
31
Fem
3
1.80
90
26
Fem
4
1.75
69
30
Fem
5
1.91
95
38
Mas
6
1.72
80
20
Mas

Scrittura di dati
I CSV sono anche questa volta lo standard. In effetti, i file CSV sono leggibili da quasi
tutti i programmi di calcolo, quindi non stupisce perch siano cos usati. Per scrivere dei
dati in CSV si usa una delle due funzioni write.csv() o write.csv2(). La differenza tra le
due dovrebbe essere chiara: la prima scrive CSV che usano le virgole come separatori di
campo (impostazioni internazionali) e la seconda CSV con punto e virgola come
separatore (impostazioni italiane). Anche in questo c' una funzione pi generica che
write.table() (non ci sono invece funzioni corrispondenti a read.delim() e read.delim2(),
ma bisogna passare attraverso write.table() usando appropriati parametri).
# Scrittura del CSV "internazionale"
write.csv(csv_int, file="mio_csv_int.csv")
# Scrittura del CSV "italiano"
write.csv2(csv_ita, file="mio_csv_ita.csv")

Soluzioni
Esercizio 1: Che funzione genera un vettore di
elementi ripetuti?
rep(100, 5)
## [1] 100 100 100 100 100
rep(c(1, 2), 3)
## [1] 1 2 1 2 1 2
La parola da cercare era 'replicate' (replicare). L'aiuto viene con: ??replicate. Una parola
che poteva venire in mente 'repeat'. Questa una parola speciale quindi facendo ??
repeat R aspetta altro input. In questo caso si sarebbe dovuto
scrivere ??'repeat' (comunque, repeat non ci serviva).
Da notare che ci che ripetuto il primo argomento. Nel primo esempio c'era solo un
numero, mentre nel secondo c'era un vettore che stato ripetuto il numero indicato di
volte.

Page 52 of 53

Esercizio 2: Trovare i soggetti che hanno un


peso maggiore di 70 e non NA
peso[!is.na(peso) & peso>70]
## [1] 72 90 95

Esercizio 3: Estrarre altezza e laurea dei


maschi di cui si ha il peso
df[df$gender=='M' & !is.na(df$peso), c(1,4)]
##
alto titolo
## 2 1.8 FALSE
## 4 1.9 FALSE

Esercizio 4: Estrarre l'elemento di una matrice


in una lista per una certa posizione di un altro
elemento
lis$matrice[,1][lis[[1]]=='char 1']
## [1] 4

Page 53 of 53

Potrebbero piacerti anche