Il Realismo nella Finzione

Zettelkasten...


title: "Tutorial su R" output: learnr::tutorial runtime: shiny_prerendered

library(learnr)
knitr::opts_chunk$set(echo = FALSE)

R come calcolatrice

Un uso, molto limitante, di R è come calcolatrice: inserendo un'operazione nella console, ne potremo vedere il risultato. Ad esempio

2*3
cos(1)
34/22

Esercizio

Ora tocca a te

Scrivi il codice R per sommare 2 e 2:

Sintassi di base

Vogliamo fare qualcosa di più che non solamente usare R per fare da calcolatrice. Come prima cosa, vediamo com'è possibile assegnare un valore ad un oggetto: usiamo l'operatore di assegnamento <- (costituito da due caratteri < e -). Questo ci permette di assegnare il valore dell'oggetto a destra all'oggetto a sinistra:

cosa <- 7*3-2

Se ora vogliamo recuperare questo valore, possiamo farlo o digitando nel prompt cosa, oppure usando il comando print(cosa):

cosa
print(cosa)

L'oggetto così creato (se non esisteva già) viene aggiunto al workspace. Possiamo anche assegnare un nuovo valore ad esso.

Esercizio

Assegna ad un oggetto di nome ogg il risultato della radice quadrata (sqrt) del tuo giorno di nascita, visualizza tale valore e poi moltiplicalo per il tuo mese di nascita (codificato numericamente), assegnando il risultato sempre ad ogg.

Se vogliamo cancellare un oggetto che non ci occorre più, possiamo farlo mediante il comando rm() o remove():

rm(cosa)
#print(cosa) # restituisce errore, perché l'oggetto non esiste più

Vettori

Passiamo a vedere altri tipi di strutture dati in R: la prima è vector, ovverosia una n-upla ordinata di oggetti dello stesso tipo (ad esempio numeri o caratteri). Per costruire un vettore usiamo il comando c:

my_vector <- c(1,2,3,3,3,4,5,5)
print(my_vector)
my_characters <- c('a','a','v','1',2)
print(my_characters)

Notate che in my_characters il '2' finale viene salvato come stringa di caratteri (per mantenere l'uniformità di tipi).

Per ogni oggetto sono definiti i due attributi mode e length. Il secondo ci dice la "lunghezza" dell'oggetto:

length(my_vector)
length(77)
length('a')
length('aba')

Per quanto riguarda il modo (simile, ma non coincidente con il tipo), possiamo vederlo con il comando mode(x). In realtà possiamo andare a controllare questo tipo di attributo in altro modo:

is.numeric(my_vector)
is.character(my_characters)
is.integer(my_vector) #non un modo, ma un tipo

Osserviamo che i numeri, anche interi, di default non sono salvati come tali (cioè integer), ma come floating point (tipo double).

In modo analogo possiamo anche controllare se un oggetto è o meno un vettore:

is.vector(my_characters)
is.vector(2)
is.matrix(my_vector)

Quindi un vettore non è considerato da R una matrice.

Esercizio

Prima di continuare, prova a fare qualche esperimento con i vettori, definendone uno oltre a quello assegnato e controllando la lunghezza di entrambi e, ad esempio, se sono di tipo double o di tipo character

  my_new_vector <- c(1,2,c(1,1,2,2),78)

Matrici

Nella sezione precedente abbiamo visto che un vettore non è una matrice, per R. Andiamo allora a vedere qualche esempio di matrice.

  M <- matrix(1:15, nrow=3, byrow=TRUE)
  M_1 <- matrix(1:15, nrow=3) # andiamo a riempire la matrice in un altro modo
  M
  M_1
  length(M)

La lunghezza di una matrice ci dice quanti elementi ha, ma non ci aiuta a scoprire la forma della matrice stessa. Per conoscerne le dimensioni, possiamo usare il comando dim().

  dim(M_1)
  y <- dim(M)
  y
  is.vector(y)

La dimensione di una matrice è un vettore.

Altre funzioni utili quando si ha a che fare con una matrice sono: nrow e ncol:

nrow(M)
ncol(M)
nrow(y)
NROW(M_1)
NCOL(M)
NROW(y)
NCOL(y)

Osserviamo che tali funzioni non operano sui vettori, ma le funzioni NROW e NCOL lo fanno (e nel modo che ci aspettiamo). Osserviamo anche che questo ci suggerisce che R distingue tra maiuscole e minuscole (case sensitive).

Esercizio

Prova ora a creare una matrice a partire dai due vettori numerici assegnati

  x <- c(1,2,2,1,3,4,4,3,66,99,89,76)
  v <- c(9,0,-23,11)
  X <- matrix()
  V <- matrix()

Operazioni con matrici e vettori

Possiamo sommare vettori, purché abbiano la medesima lunghezza (o uno abbia lunghezza multipla di quella dell'altro). Possiamo moltiplicarli per uno scalare e possiamo moltiplicarli tra loro (sotto le stesse condizioni della somma). Cosa otteniamo in quest'ultimo caso?

x_1 <- 1:10
x_2 <- rep(c(1,2),5)
x_1
x_2
x_1+x_2
2*x_1
x_3 <- c(-1,1,-2,2,3)
x_1-x_3
x_1*x_2

Facendo il prodotto di due vettori quello che abbiamo è il prodotto elemento per elemento.

E per le matrici?

X_1 <- matrix(x_1,ncol = 2)
X_2 <- matrix(x_2, nrow=2)
X_1
X_2
# X_1+X_2 # non funziona! non hanno la stessa forma
X_1+t(X_2) # trasposta di X_2
X_1+ c(1,2)

Anche per le matrici vale il discorso visto prima che si possono sommare oggetti "più piccoli", ma la cui lunghezza divida la lunghezza della matrice.

Se moltiplichiamo due matrici, otteniamo il prodotto componente per componente, se vogliamo fare il prodotto di matrici dobbiamo usare %*%:

X_1*t(X_2)
3*X_2
X_1%*%X_2
X_2%*%X_1

Ricordiamo che la moltiplicazione tra matrici si può fare solo se le dimensioni soddisfano certe condizioni e che non è commutativa.

Possiamo anche fare la moltiplicazione matriciale tra una matrice e un vettore (che in questo caso viene considerato come una matrice a una sola colonna). Il risultato è una matrice. Siccome in questo caso si tratta di una matrice colonna, possiamo usare il comando drop per farla considerare come un vettore a R.

y <- X_1%*%c(4,5)
y
is.matrix(y)
y_vect <- drop(y)
y_vect
is.vector(y_vect)
rm(list = ls())

Prima di passare oltre proviamo a mettere in pratica quanto visto.

Esercizio

Definisci una matrice M_1 2x3 contenente i numeri pari da 2 a 12. Definisci una seconda matrice M_2 3x3 non identicamente nulla e un vettore v costituito dagli elementi 3,pi,-9. Moltiplica matricialmente M_2 per M_1 (o la sua trasposta). Somma e moltiplica M_1 per v. Scrivi infine una matrice V 4x1 che abbia come elementi 0 e gli elementi del vettore v, stampala e poi salvala come vettore v_new.

Elementi di un vettore o di una matrice

Come facciamo ad accedere ad un particolare elemento o a un sottoinsieme di elementi di un vettore o di una matrice?

M_1 <- 2*matrix(1:6, nrow=2)
v_new <- c(0,3,pi,-9)

Dobbiamo usare l'operatore []. Per i vettori funziona nel modo seguente:

v_new[1]
v_new[c(1,2,3)]

Per le matrici, invece, dobbiamo considerare che hanno due dimensioni, quindi useremo lo stesso operatore, ma con una sintassi leggermente diversa:

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

Osserviamo che, quando il risultato della selezione degli elementi poteva essere interpretato come un vettore, R ci ha restituito un vettore (e non una matrice). Se volessimo avere una matrice, dovremmo chiamare l'operatore [] con un ulteriore argomento drop=FALSE:

M_1[,2, drop=FALSE]

Esercizi

Nella matrice seguente metti assegna agli elementi sulla diagonale maggiore il corrispondente numero di riga, a quelli sulla diagonale minore l'opposto del numero di colonna.

M <- matrix(-10,2,2)

Questo esercizio è un po' più difficile, ma magari anche più divertente. Costruisci la matrice 8x8 X con i numeri da 1 a 64 disposti riga per riga. Immagina ora che si tratti di una scacchiera, con la casella in alto a sinistra bianca. Ora metti degli 0 in tutte le caselle bianche, usando (in modo furbo) l'operatore [].

X[c(TRUE,FALSE)] # cosa fa questa selezione?

Altre strutture dati

Che fare qualora volessimo avere un vettore che contenga oggetti di vario tipo (ad esempio un altro vettore) come elementi? Per questo la struttura dati in R è list.

l <- list ('a',2)
l
str(l)

Il comando str ci dà qualche informazione in più sulla struttura della nostra lista. Notiamo che in questo caso il 2 non è stato forzato a stringa (come nel caso del vettore).

Ma con le liste possiamo fare molto di più!

l <- list(lettera='x', vettore=v_new, X=M_1)
str(l)
length(l)
l

E se vogliamo accedere ad elementi della lista? Possiamo farlo in vari modi:

l[1]
l[[1]]
l$X
l[["X"]]
l["X"]

Possiamo accedere per posizione (nella lista), oppure per nome. Notiamo anche la differenza tra [] e [[]]: nel primo caso ci restituisce una (sotto)lista, nel secondo caso ci restituisce l'elemento (che può essere di vari tipi).

Esercizio

Definisci una lista che abbia come elementi: una lista di due elementi, di nomi x e y, un vettore numerico, una matrice. Come puoi accedere a y? Come puoi accedere a un elemento a tua scelta della matrice?

l <- list(lista= ,numeri= , matrice= )