###################################################### ################ CORSO LIVELLAMENTO R ################ ################# seconda lezione #################### ###################################################### ######### BOOLEANI: TRUE e FALSE x <- c(4, 8, 15, 16, 23, 42) x[3] >= x[2] # il primo elemento e' maggiore del secondo? x[3] < sum(x[1:2]) # il primo elemento e' minore del secondo? x[2] == x[5]-20 # il primo elemento e' uguale al secondo? x[2] != x[5]-20 # il primo elemento e' diverso dal secondo? # Quali elementi di x sono (strettamente) maggiori della loro media? x > mean(x) # Questi elementi TRUE/FALSE possono essere salvati in un oggetto! booleani <- x > mean(x) str(booleani) tt <- TRUE ttt <- T ff <- FALSE fff <- F sum(booleani) # considera i FALSE come 0 ed i TRUE come 1 mean(booleani) ###### OPERATORI LOGICI: # AND (&): Restituisce TRUE quando tutti gli argomenti sono TRUE T & T T & T & T # ESERCIZIO 1: Utilizzare l'operatore & per verificare se il terzo elemento di # x appartiene all'intervallo (7, 12] # OR (|): Restituisce TRUE se almeno uno degli argomenti e' TRUE T | F F | F | T # ESERCIZIO 2: Verificare se almeno una delle seguenti due condizioni e' verificata: # - il quinto elemento di x appartiene all'intervallo [17, 34) # - il quinto elemento di x appartiene all'intervallo (-infinito, 4) ((x[5] < 34) & (x[5] >= 17)) | (x[5] < 4) # NOT (!): Inverte il valore logico (i TRUE diventano FALSE e viceversa) !T !F !(5 > 9) sum(booleani) # considera i FALSE come 0 ed i TRUE come 1 sum(!booleani) ###### Doppi operatori: (x > 10) & (x != 15) (x > 10) && (x != 15) # Il doppio operatore agisce soltanto sui primi elementi dei vettori. ###### Funzioni sui booleani: # Funzione all: Restituisce TRUE quando TUTTI gli argomenti (booleani) sono TRUE help(all) n <- x < 10 all(n) all(x < 10) all(x<100) all(x) # Funzione any: Restituisce TRUE quando almeno un argomento e' TRUE help(any) n <- x < 10 any(n) any(x < 10) all(x<1) any(x<1) any(x) ################################################################################################### ####### Valori Mancanti, Valori Non Numerici e Valori 'Nulli' NA # Not Available (Valore Mancante) NaN # Not a Number (Valore non Numerico) NULL # Oggetto 'nullo' Inf # Infinito 0/0 5/0 Inf/Inf length(x) class(x) x[7] x[c(2,4,9)] y_null <- NULL length(y_null) class(y_null) # Un oggetto NULL non ha lunghezza e non ha una vera e propria classe # Un NA non viene (giustamente) codificato come 0: un'operazione che coinvolge # un NA (dato mancante) genera un NA: y <- 5 + NA y class(y) length(y) x.na <- c(x, NA, NaN) x.na sum(x) sum(x.na) sum(x.na, na.rm = T) # na.rm ci chiede "se trovo un NA devo rimuoverlo?". Qui gli stiamo # dicendo di si, ma di default e' no. # Molte delle funzioni base di R prevedono l'argomento na.rm mean(x.na, na.rm=T) sd(x.na, na.rm=T) # Almeno un elemento e' NA? anyNA(x.na) # Quali elementi di x.na sono NA? is.na(x.na) # Quali sono le posizioni degli elementi NA? which(is.na(x.na)) # which e' una funzione che riceve un argomento (vettore o array) e # restituisce la posizione degli argomenti TRUE help(which) x == 15 | x > 40 which(x == 15 | x > 40) ####################################### ########### Matrici e Array ########### ####################################### m <- matrix(NA, nrow=2, ncol=3) # Crea una matrice 2x3 con elementi missing m #### Oppure crearla con gli elementi corretti: ## Modo 1: m.row <- matrix(data=c(4,8,15,16,23,42), byrow = T, ncol=3, nrow=2) m.row m.col <- matrix(data=c(4,8,15,16,23,42), byrow = F, ncol=3, nrow=2) m.col m.row == m.col all(m.row == m.col) ## Modo 2: m1 <- cbind(c(4,16), c(8, 23), c(15, 42)) m1 m2 <- rbind(c(4,8,15), c(16,23,42)) m2 all(m1 == m2) class(m) is.matrix(m) is.array(m) # Le matrici vengono considerate come un caso particolare di array a due dimensioni length(m) # Quanti elementi ha la matrice? dim(m) # Quante righe e colonne ha la matrice? dim(m)[2] ncol(m) # Quante colonne ha la matrice? nrow(m) # Quante righe ha la matrice? ###### Estrarre elementi da una matrice: m[1,] # Tutta la prima riga m[,2] # Tutta la seconda colonna m[2,3] # Elemento in posizione (2,3) m[3,2] # Elemento in posizione (3,2).. ops ### In questo modo possiamo anche riempire una matrice "vuota" creata in precedenza: m <- matrix(NA, nrow=2, ncol=3) m m[1,] <- c(4, 8, 15) m[2,] <- c(16, 23, 42) m ###### Operazioni sulle matrici. A <- matrix(data=c(0,1,4,5,7,6,2,1,7), ncol=3, nrow=3) A B <- matrix(data=c(5,1,0,2,3,7,4,2,3), ncol=3, nrow=3) B B.rid <- B[,-2] B.rid t(A) # Matrice Trasposta # Funzione diag(): a seconda dell'argomento, svolge un compito diverso: help(diag) diag(A) # Se l'argomento e' una matrice, restituisce la diagonale principale diag(B) diag(B.rid) diag(4) # Se l'argomento e' un intero k, restituisce la matrice identita' di ordine k diag(A) <- c(4,5,-1) # Cambia la diagonale principale diag(A) # Somma A B A+B A+B.rid ###### Prodotto: # Il prodotto tra matrici visto nei corsi di Algebra e Analisi matematica # si può effettuare tra due matrici A e B tali che il numero di colonne di A # e' uguale al numero di righe della matrice B. dim(A) dim(B) dim(B.rid) A*B A*B.rid # ATTENZIONE! # Il prodotto derivante dall'operatore moltiplicazione * NON porta al # classico prodotto matriciale, bensì ad un prodotto elemento per elemento (element-wise) # Il prodotto matriciale "classico" si ottiene con l'operatore %*%: A %*% B A%*%B.rid det(B) # Determinante di una matrice eigen(B) # Autovalori ed autovettori autov <- eigen(B) autov$values autov$vectors eigen(B)$values str(autov) solve(A) # Matrice inversa A %*% solve(A) round(A %*% solve(A), 8) # La funzione solve() e' utile anche per risolvere sistemi lineari: # x + 2y = 3 # -x - 4y = 4 Coeff <- matrix(c(1, 2, -1, -4), ncol=2, nrow=2, byrow=T) Coeff termini.noti <- c(3,4) solve(Coeff, termini.noti) # Verifichiamo: 10 + 2*(-3.5) -10 -4*(-3.5) # ESERCIZIO 3: X <- cbind(rep(1,5), c(2,3,1,1,4), c(4,9,1,1,16)) y <- c(10,2,1,2,20) # E' noto che la stima dei minimi quadrati dei coefficienti b del seguente modello # y = b0 + b1*X1 + b2*X2 # e' data da b=(X'X)^(-1)X'y. Determinare la stima dei m.q. per b con i dati forniti: # Altre operazioni (statistiche) sulle matrici A mean(A) colMeans(A) # Media condizionate: calcola la media di ogni colonna rowMeans(B) # Medie condizionate: calcola la media di ogni riga colSums(A) # calcola la somma di ogni colonna rowSums(A) # calcola la somma di ogni riga # Piu' in generale: funzione apply() help(apply) apply( A, # Nome della su cui applicare la funzione 1, # 1 = applica la funzione ad ogni riga, 2 = applica la funzione ad ogni colonna sum # Funzione da applicare. Sono accettate alcune funzioni base (sum, mean, sd,...). # Piu' avanti vedremo un caso molto piu' generale (e molto piu' utile) ) ######### ARRAY # Un array e' una sorta di matrice con piu' di due dimensioni. # Ad esempio, la seguente istruzione crea un array con dimensioni (4,3,2), # il quale puo' essere pensato come una "collezione" di 2 matrici di dimensione (4,3) x.array <- array(data=1:24, dim=c(4,3,2)) x.array # Una matrice e' quindi un caso particolare di array, la cui ultima dimensione # ha lunghezza pari a 1: y <- array(data=1:6, dim=c(2,3,1)) y x.array[,,2] # tutte le righe e tutte le colonne della seconda "fila" x.array[2,,] # elementi che stanno nella seconda riga, tutte le colonne e tutte le file x.array[,1,] # elementi che stanno nella prima colonna, tutte le righe e tutte le file x.array[1,3,]# tutti gli elementi che stanno in prima riga e terza colonna, indipendenemente dalla fila x.array[1,2,1]# elemento in prima riga, seconda colonna, prima fila. # La matrice, cosi' come un vettore, e' vincolata ad avere elementi tutti della # stessa tipologia: cbind(c("NE","FF"), c(4, 3)) ############ Data Frame # Un data frame l'oggetto basilare di R piu' vicino ad un "dataset". # Ossia, si tratta si un insieme di colonne (variabili) che non devono # essere necessariamente dello stesso tipo df<- data.frame(variabile1=c("NE","FF"), var2=c(4, 3)) str(df) genere <- c("F", "M", "M", "M", "F", "M") eta <- c(4,8,15,16,23,42) sig <- c(0,0,0,2,12,18) df <- data.frame(genere=as.factor(genere), eta=eta, sigarette=sig) df names(df) str(df) # Notare la tipologia di "genere". # R ha un suo modo di trattare quelle che in statistica vengono chiamate "variabili qualitative". # genere e' un fattore che presenta due livelli (modalita'): M e F. # Alcune funzioni statistiche hanno un modo specifico di trattare i fattori. # Proviamo ad accedere alla variabile sigarette: sigarette # Errore: l'oggetto "sigarette" non e' presente nell'environment! # Per accedere alle variabili di un dataframe e' possibile utilizzare l'operatore dollaro $ df$sigarette # Possiamo forzare una matrice ad essere un dataframe: cbind(c("NE","FF"), c(4, 3)) df_prova <- as.data.frame(cbind(c("NE","FF"), c(4, 3))) #Attenzione alla tipologia delle variabili ottenute in questo modo! str(df_prova) # Forzando la matrice ad essere un data.frame abbiamo ottenutodei nomi delle variabili sono generici colnames(df_prova) <- c("Var_quali", "Var_quanti") str(df_prova) # 2: quella che doveva essere una variabile numerica e' stata trattata come character df_prova$Var_quanti <- as.numeric(df_prova$Var_quanti) str(df_prova) ###### Liste # Una lista e' un oggetto che 'racchiude' tanti altri oggetti al suo interno, # anche di diverso tipo lista1 <- list(num=4, var=sig, dataframe=df, mat <- A, array=x.array) lista1 str(lista1) # Come accedere agli elementi di una lista: lista1$dataframe lista1[[3]] lista1[3] str(lista1[[3]]) str(lista1[3]) # Perche' dovremmo complicarci la vita usando due coppie di parentesi quadre, # se con una sola coppia di parentesi otteniamo lo stesso risultato?? str(lista1[[4]]) str(lista1[4]) det(lista1[[4]]) det(lista1[4]) lista2 <- list(num=4, var=sig, dataframe=df, mat = A, array=x.array) str(lista2) # Importiamo la nostra prima libreria/pacchetto: library(faraway) help(gala) data("gala") gala is.data.frame(gala) names(gala) str(gala) summary(gala) # summary non restituisce la varianza!! Sfruttiamo la funzione apply: apply(gala, 2, var) # Non abbiamo ancora sfruttato al massimo la potenzialita' di apply. # per farlo dobbiamo aspettare di imparare a creare delle nostre funzioni. apply(gala, 2, sd) # Per scaricare un pacchetto: install.packages("FlexDir") # Oppure con l'apposita procedura guidata nella Scheda "Packages" in RStudio