Il dataframe è la struttura più “complessa”, utile e potente di R. Da un punto di vista intuitivo è un foglio excel mentre da un punto di vista di R è una tipologia di lista con alcune caratteristiche/restrizioni
ogni elemento della lista è un vettore con un nome associato (aka una colonna)
ogni lista/colonna deve avere lo stesso numero di elementi
di conseguenza ogni riga ha lo stesso numero di elementi (struttura rettangolare)
Creazione
Nella maggior parte dei casi vi capiterà d’importare più che creare dei dataframe, ma è importante prima capire come funzionano e come crearli/manipolarli. Si creano attraverso il comando data.frame
# Creo un dataframe con 3 colonne my_df =data.frame( col1 =1:4, col2 = letters[1:4],col3 =rnorm(n =4, mean =0, sd =1)) my_df
col1 col2 col3
1 1 a -1.55643426
2 2 b -0.03366128
3 3 c 1.13593425
4 4 d 1.44699611
Attributi
Il dataframe ha sia gli attributi della lista ovvero i names ma anche gli attributi della matrice ovvero le dimensioni (righe e colonne)
Come per le altre strutture che abbiamo visto, possiamo utlizzare le funzioni names() , dim(), nrow(), ncol()… per ottenere informazioni sulle caratteristiche del dataframe. La funzione più utile è str() poichè ci restituisce una veloce overview della struttura del dataframe: dimensioni, tipi di variabili,…
str(iris) # iris è un dataset presente di default in R (?iris)
my_df[[1]] # estraggo la prima colonna del data.frame
[1] 1 2 3 4
my_df[1,1] # estraggo il primo elemento della prima colonna del data.frame
[1] 1
che il simbolo del dollaro $
my_df$col1 # estraggo la prima colonna del data.frame
[1] 1 2 3 4
my_df$col1[1] # estraggo il primo elemento della prima colonna del data.frame
[1] 1
Indicizzazione - Operatori relazionali
Una delle operazioni più comuni che dovrete affrontare sarà sicuramente quella di estrarre/valutare un sottoinsieme di valori presenti nel vostro dataset:
my_df
col1 col2 col3
1 1 a -1.55643426
2 2 b -0.03366128
3 3 c 1.13593425
4 4 d 1.44699611
# includo solo le righe in cui alla colonna1 i valori sono maggiori di 2my_df[my_df$col1 >2, ]
col1 col2 col3
3 3 c 1.135934
4 4 d 1.446996
my_df[my_df[1] >2, ]
col1 col2 col3
3 3 c 1.135934
4 4 d 1.446996
Esempi
col1 col2 col3
1 1 a -1.55643426
2 2 b -0.03366128
3 3 c 1.13593425
4 4 d 1.44699611
my_df[my_df$col1 >2& my_df$col1 <4, ]
col1 col2 col3
3 3 c 1.135934
my_df[my_df$col1==2, 2]
[1] "b"
my_df[my_df$col1==2, "col2"]
[1] "b"
Indicizzazione
Ci sono anche dei modi alternativi e più compatti di indicizzare. Ad esempio usando la funzione subset():
subset(iris, subset = Species =="setosa"& Petal.Length >1.7)
La maggiorparte delle volte vi troverete ad accedere alle variabili tramite l’operatore $. Questo comando può essere utilizzato anche per creare una nuova variabile…
# creo una variablie che è la somma di Length e Widthiris$somma = iris$Sepal.Length + iris$Sepal.Widthstr(iris)
Si applicano gli stessi concetti che abbiamo visto per i vettori, potete quindi sia creare che modificare variabili.
my_df =data.frame(num =1:4, let = letters[1:4])my_df
num let
1 1 a
2 2 b
3 3 c
4 4 d
# Modfico la variabile num aggiungendo 1my_df$num = my_df$num+1# Creo una terza variabile composta dalla varibile num e letmy_df$both =paste(my_df$num,my_df$let, sep ="_") # ?pastestr(my_df)
'data.frame': 4 obs. of 3 variables:
$ num : num 2 3 4 5
$ let : chr "a" "b" "c" "d"
$ both: chr "2_a" "3_b" "4_c" "5_d"
Combinare Dataframes
Essendo simili a delle matrici, i dataframe si possono combinare tra loro attraverso le funzioni rbind():
# primo dataframestr(my_df)
'data.frame': 4 obs. of 3 variables:
$ num : num 2 3 4 5
$ let : chr "a" "b" "c" "d"
$ both: chr "2_a" "3_b" "4_c" "5_d"
# creo un secondo dataframemy_df2 =data.frame(num =4:7, lett = letters[1:4], both =paste(4:7,letters[1:4], sep ="_"))str(my_df2)
'data.frame': 4 obs. of 3 variables:
$ num : int 4 5 6 7
$ lett: chr "a" "b" "c" "d"
$ both: chr "4_a" "5_b" "6_c" "7_d"
Unisco i due dataframes
I dataframes devono avere lo stesso numero di colonne
I nomi delle colonne devono essere identici
my_df3 =rbind(my_df,my_df2)
Error in `match.names()`:
! names do not match previous names
str(my_df)
'data.frame': 4 obs. of 3 variables:
$ num : num 2 3 4 5
$ let : chr "a" "b" "c" "d"
$ both: chr "2_a" "3_b" "4_c" "5_d"
str(my_df2)
'data.frame': 4 obs. of 3 variables:
$ num : int 4 5 6 7
$ lett: chr "a" "b" "c" "d"
$ both: chr "4_a" "5_b" "6_c" "7_d"
Sistemo i nomi
names(my_df2)
[1] "num" "lett" "both"
names(my_df)
[1] "num" "let" "both"
# voglio che i names di my_df2 corrispondano ai names di my_dfnames(my_df2) =names(my_df)my_df3 =rbind(my_df,my_df2) str(my_df3)
'data.frame': 8 obs. of 3 variables:
$ num : num 2 3 4 5 4 5 6 7
$ let : chr "a" "b" "c" "d" ...
$ both: chr "2_a" "3_b" "4_c" "5_d" ...
Potrebbe anche capitarvi di dover raccogliere differenti tipi di dato dallo stesso partecipante, e successivamente combinare le informazioni raccolte…
Dataframe contente i tempi di reazione:
df_rt =data.frame(subj =factor(rep(c("caio","tizio"),each =400)),cond =factor(rep(c("easy","hard"), each =200, times =2)),rt =c(rlnorm(n =400, meanlog =-1, sdlog = .25), rlnorm(n =400, meanlog =-.7, sdlog =.3)))# equivalente a creare prima le variabili come vettore e poi inserirle in un dfsubj =factor(rep(c("caio","tizio"),each =400))cond =factor(rep(c("easy","hard"),each =200, times =2))rt =c(rlnorm(n =400, meanlog =-1, sdlog = .25), rlnorm(n =400, meanlog =-.7, sdlog =.3))df_rt =data.frame(subj, cond, rt)
Dataframe contente l’età:
df_age =data.frame(subj =factor(c("caio","tizio")), age =c(20,3))
str(df_rt) # struttura dataframe tempi di reazione
library(dplyr) # carico il pacchetto dplyrdf_all_2 =left_join(x = df_rt, y = df_age, by =c("subj")) # esistono anche right_join; full_join str(df_all_2)
E’ possibile utilizzare le funzione table() sia per calcolare le frequenze che per computare delle tabelle di contigenze, per esempio per vedere quanti trial ho per ogni soggetto.
# tengo solo rt compresi tra .200 e 1.5 secondi# quindi le righe che rispettano questa condizionedf_rt_clean = df_rt[df_rt$rt > .25& df_rt$rt <1.5, ] # quanti trial x ogni soggettotable(df_rt$subj)
caio tizio
400 400
table(df_rt_clean$subj)
caio tizio
378 396
# quanti trial x ogni soggetto x condizionetable(df_rt_clean$subj, df_rt_clean$cond)
easy hard
caio 187 191
tizio 196 200
Esportazione e importazione dati
In R è possibile importare dati in molti formati differenti, più comunemente vi troverete ad importare dati .csv oppure .xlsx.
Qui per esempio, esporto i dataframe in due formati differenti…
library(readr) # carico il pacchetto readrlibrary(writexl) # carico il pacchetto writexlwrite.csv(df_rt, file ="DATA/df_rt.csv",row.names =FALSE)write_xlsx(df_age, path ="DATA/df_age.xlsx")
Importo
library(readxl) # carico il pacchetto readxldf_rt_impo =read_csv("DATA/df_rt.csv") #utilizza il pacchetto readrdf_age_impo =read_xlsx("DATA/df_age.xlsx")
Il dataframe viene importato come tibble ed in questo caso le variabili factor sono state importate come character. Questo è modificabile o in importazione ( ?read_csv ):