-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path12-dataframe.Rmd
533 lines (370 loc) · 26.1 KB
/
12-dataframe.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
# Dataframe {#dataframe}
```{r settings, echo = FALSE}
knitr::opts_chunk$set(
echo = FALSE,
collapse=TRUE,
fig.align="center"
)
library(kableExtra)
```
I `dataframe` sono uno degli oggetti più utilizzati in R per rappresentare i propri dati. In modo analogo alle matrici, i `dataframe` sono una struttura **bidimensionale** dove i dati sono disposti secondo righe e colonne. Può essere utile pensare al dataframe esattamente come ad una normale tabella che si può creare in un foglio di calcolo (e.g., Excel) dove possiamo inserire i nostri dati. Dati in questo caso è volutamente generico poichè i dataframe, a differenza delle matrici, possono contenere nello stesso oggetto tipi diversi di dati (e.g., *nomi*, *date* e *numeri*).
La struttura di base di un dataframe è quindi la stessa di una matrice ma ci permette di includere diversi tipi di dati nello stesso oggetto come caratteri e valori numerici. Questo ci consente di raccogliere in un unico oggetto tutte le caratteristiche delle unità statistiche (variabili numeriche, categoriali, nominali etc.) che intendiamo successivamente analizzare. Un aspetto cruciale quindi è proprio quello che il dataframe è stato pensato per gestire dati complessi ed eterogenei come quelli che si trovano in un’analisi di dati reale. Se vi capiterà di utilizzare altri linguaggi di programmazione sopratutto mirati all'analisi dati (e.g., Matlab) noterete come vi mancherà un oggetto potente e intuitivo come il dataframe.
In genere in un dataframe le righe rappresentano le unità statitiche (ad esempio persone o osservazioni) e le colonne rappresentano variabili ovvero delle proprietà misurate su quelle unità statistiche. Esistono tuttavia due formati principali di dataframe a seconda del modo in cui vengono organizzati i dati. Abbiamo i dataframe in forma **wide** (oppure larga) oppure i dataframe in forma **long** (oppure lunga). Valutiamo la differenza tra i due formati ipotizzando dei dati dove per ogni soggetto abbiamo misuriamo l'età, il genere, e la risposta a tre item di un questionario.
#### Wide Dataframe {-}
Nel formato **wide**, ogni singola riga del dataframe rappresenta un soggetto e ogni sua risposta o variabile misurata sarà riportata in una diversa colonna. In Tabelle \@ref(tab:table-wide-db) vengono presentati i darti dell'esempio in un formato wide.
```{r table-wide-db}
data_wide<-data.frame(
Id=c("subj_1","subj_2","subj_3"),
age=c(21,23,19),
gender=c("F","M","F"),
item_1=c(2,1,1),
item_2=c(0,2,1),
item_3=c(2,0,1)
)
data_wide %>%
kable(align = "c",
caption = "Dataframe nel formato wong") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F)
```
Osserviamo come ogni soggetto si identificato da un codice riportato nella variabile *Id* e le risposte ai tre item siano riportate in tre diverse variabili *item_1*, *item_2* e *item_3*.
#### Long Dataframe {-}
Nel formato **long**, ogni singola riga rappresenta una singola osservazione. Quindi i dati di ogni soggetto saranno riportati su più righe e le variabili che non cambiano tra le osservazioni saranno ripetute. In Tabelle \@ref(tab:table-long-db) vengono presentati i darti dell'esempio in un formato lide.
```{r table-long-db}
data_long<-data.frame(Id=rep(c("subj_1","subj_2","subj_3"),each=3),
age=rep(c(21,23,19),each=3),
gender=rep(c("F","M","F"),each=3),
item=rep(1:3,3),
response=c(2,1,1,0,2,1,2,0,1))
data_long %>%
kable(align = "c",
caption = "Dataframe nel formato long") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = F)
```
Osserviamo come le risposte di ogni soggetto siano distribuite su più righe. Le caratterische che non variano vengono ripetute ad ogni riga (*Id*, *age* e *gender*) mentre le risposte agli item vengono registrate utilizzando due colonne *item*, ovvero il numero dell'item, e *response* l'effettiva risposta di quel partecipante a quello specifico item.
:::{.tip title="Long o Wide?" data-latex="[Long o Wide?]"}
I dati in forma long e wide hanno delle proprietà diverse sopratutto in riferimento all'utilizzo. La tipologia di dato e il risultato finale è esattamente lo stesso tuttavia alcuni software o alcuni pacchetti di R funzionano solo con dataset organizzati in un certo modo.
Non c'è quindi un formato corretto o sbagliato ma dipende dal tipo di analisi e dal software o pacchetto che si utilizza. Alcune operazioni o analisi richiedono il dataset in forma **long** altre in forma **wide**.
Il consiglio però è di abituarsi il più possibile a ragionare in forma **long** perchè la maggior parte dei moderni pacchetti per l'analisi dati e per la creazione di grafici richiedono i dati in questo formato. Ci sono comunque delle funzioni (più avanzate) per passare velocemente da un formato all'altro.
:::
Nota come nei precedenti esempi abbiamo utilizzato sia colonne che contengono valori numerici numeri sia colonne con caratteri. Questo non era chiaramente possibile con le matrici. Ricorda tuttavia che, come per le matrici, anche i dataframe richiedono che tutte le colonne (variabili) abbiano lo stesso numero di elementi.
Vedremo ora come creare dei dataframe in R e come compiere le comuni operazini di selezione. Infine descriveremo alcune semplici manipolazioni e operazioni con i dataframe. Come vedremo ci sono molte somiglianze nell'utilizzo dei dataframe e delle matrici. Quando necessario, si farà riferimento al capitolo precedente per far notare aspetti in comune e differenze tra queste due strutture di dati.
## Creazione di un dataframe
Il comando per creare un dataframe è `data.frame()`:
```{r, eval=FALSE, echo=TRUE}
nome_df <- data.frame(
variable1 = c(...),
variable2 = c(...),
...)
```
La creazione è leggermente diversa rispetto al caso delle matrici. Intuitivamente è facile immaginarla come l'unione di diverse colonne (dove una può contenere dei nomi, un'altra delle date e così via) piuttosto che un insieme di valori inseriti per riga o per colonna come per le matrici. Infatti per creare un `dataframe` è proprio necessario specificare le colonne una alla volta, indicando `nome_colonna = valori` all'interno del comando `data.frame()`. Vediamo un esempio in R,
```{r, echo = TRUE}
my_data <- data.frame(
Id = c(1:5),
names = c("Alice", "Bruno", "Carla", "Diego", "Elisa"),
gender = factor(c("F","M","F", "M", "F")),
age = c(22, 25, 23, 22, 24),
faculty = factor(c("Psicologia", "Ingegneria", "Medicina", "Lettere", "Psicologia"))
)
my_data
```
In questo caso abbiamo creato un ipotetico dataframe dove in ogni riga abbiamo un soggetto e ogni colonna rappresenta una data caratteristica del soggetto come il genere, l'età e così via.
:::{.tip title="ID" data-latex="[ID]"}
E' sempre consigliato definire una colonna (e.g., `Id`) in cui assegnnare un idenificativo univoco ad ogni soggetto. Questo ci permetto di poterlo indentificare senza correre il rischio di compiere errori. Ad esempio l'utlizzo del nome (o anche nome e cognome) potrebbe non essere indicato poichè più persone potrebbero avere lo stesso nome e non saremo quindi in grado di discriminare i due soggetti.
:::
:::{.warning title="stringsAsFactors" data-latex="[stringsAsFactors]"}
Una variabile di caratteri all'interno di un DataFrame è considerata di default come una semplice sequenza di caratteri. E' possibile specificare l'argomento `stringsAsFactors = TRUE` per ottenere che tutte le variabili di caratteri siano considerate come delle variabili catgoriali creando automaticamente dei fattori (vedi Capitolo \@ref(factor)).
Nota come il comportamento di default sia differente a seconda della versione di R. Versioni precedenti a R 4.0 avevano infatti come default `stringsAsFactors = TRUE` mentre dalla 4.0 in poi abbiamo `stringsAsFactors = FALSE`.
Presta quindi molta attenzione quando utilizzi codici e soluzioni scritte prima della versione 4.0.
:::
### Esercizi {-}
Esegui i seguenti esercizi ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-10-dataframe.R)):
1. Crea il dataframe `data_wide` riportato in Tabella \@ref(tab:table-wide-db)
2. Crea il dataframe `data_long` riportato in Tabella \@ref(tab:table-long-db)
## Selezione Elementi {#sel-df}
Per selezionare uno o pù valori da un dataframe è possibile, in modo analogo alle matrici, utilizzare gli indici di riga e di colonna all'interno delle parentesi quadre:
```{r, echo = TRUE, eval = FALSE}
nome_dataframe[<indice-riga>, <indice-colonna>]
```
Ricordiamo che l'ordine `[<indice-riga>, <indice-colonna>]` è prestabilito e deve essere rispettato affinché la selezione avvenga correttamente. Possiamo quindi eseguire diverse tipologie di selezioni a seconda delle necessità ussanto le stesse procedure viste per le matrici. Ad esempio, riprendeno il dataframe `my_data` creato precedentemente possiamo selezionare:
```{r}
my_data <- data.frame(
Id = c(1:10),
names = c("Alice", "Bruno", "Carla", "Diego", "Elisa", "Fabrizio", "Gloria", "Herman", "Irene", "Luca"),
gender = factor(c("F","M","F", "M", "F","M","F", "M", "F", "M")),
age = c(22, 25, 23, 22, 24, 35, 26, 20, 23, 22),
faculty = factor(c("Psicologia", "Ingegneria", "Medicina", "Lettere", "Psicologia", "Lettere", "Ingegneria", "Psicologia", "Statistica", "Ingegneria"))
)
```
```{r, echo = TRUE}
my_data
# Valore 3° riga e 2° colonna
my_data[3,4]
# Tutte le variabili della 1° e 3° riga
my_data[c(2,3), ]
# Tutti i valori della 5° variabile
my_data[ , 5]
# I valori della 2° e 4° variabile per la 3° e 5° riga
my_data[c(3,5), c(2,4)]
```
Tuttavia, nell'utilizzo dei dataframe è più comune indicare i nomi delle variabili e le condizioni logico relazionali per selezionare i valori di interesse.
#### Selezione Colonne con Nomi delle Variabili {-}
Una granade differenza tra le matrici ed i dataframe sta nel poter accedere alle colonne utilizzando l'operatore `$` ed indicando il loro nome attraverso la seguente sintassi:
```{r, echo = TRUE, eval = FALSE}
nome_dataframe$nome_variabile
```
In questo modo accediamo direttamente a quella specifica colonna senza utilizzare indici e parentesi quadre. Ad esempio:
```{r, echo = TRUE}
# Seleziono la variabile "names"
my_data$names
# Seleziono la variabile "gender"
my_data$faculty
```
In alternativa è possibile utilizzare la normale procedura di selezione tramite parentesi quadre indicando al cposto degli indici di colonna i nomi delle variabili desiderate. Questo ci permette di selezionare anche più variabili contemporaneamente, ad esempio:
```{r, echo = TRUE}
# Seleziono solo la variabile "names"
my_data[ , "names"]
# Seleziono la variabile "names", "gender" e "faculty"
my_data[, c("names", "gender", "faculty")]
```
Nota come i nomi delle variabili debbano essere forniti come delle stringhe.
#### Selezione Righe con Condizioni Logiche {-}
Avevamo visto precedentemete nel caso dei vettori e delle matrici come sia possibile costruire delle preposizioni logiche per selezionare solo i valori che rispettino una data condizione. Ora questa funzione si rivela particolarmente utile poichè ci permette di *interrogare* il nostro dataframe in modo semplice ed intuitivo. Utilizzando una condizione logica possiamo, infatti, *filtrare* le oservazioni che soddisfano una data condizione ed ottenere solo le informazioni di interesse.
Nella canonica sintassi `[<indice-riga>, <indice-colonna>]`, gli indici di riga vengono sostituiti con una condizione logica che ci permette di filtrare le righe e al posto degli indici di colonna vengono indicati i nomi delle variabili di interesse. Utilizzeremo quindi la seguente sintassi:
```{r, echo = TRUE, eval = FALSE}
nome_dataframe[<condizione_logica_righe>, <nomi_variabili>]
```
Vediamo ora degli esempi di selezione:
```{r, echo = TRUE}
# Tutti i dati di "Diego" (Id == 4)
my_data[my_data$Id == 4, ]
# Tutti i dai delle ragazze
my_data[my_data$gender == "F", ]
# Le facoltà dei soggeti con più di 24 anni
my_data[my_data$age > 24, c("age", "faculty")]
```
Nota come, nel definire una condizione logica utilizzano le variabili dello stesso dataframe, sia comunque necessario indicare sempre anche il nome del dataframe. Nel caso precendente avremmo ottenuto un errore indicando semplicemente `age > 24` poichè così indichiamo l'oggetto `age` (che non esiste) e non la variabile `age` contenuta in `my_data`.
```{r, echo = TRUE, error = TRUE}
my_data[age > 24, c("age", "faculty")]
```
In modo analogo a quanto visto con i vettori, utlizzando la condizione `my_data$age > 24` otteniamo un vettore di valori `TRUE` e `FALSE` a seconda che la condizione sia rispettata o meno.
Utilizzando gli operatori logici **AND**(`&`) **OR**(`|`) e **NOT**(`!`) possiamo combinare più operazioni logiche insieme per ottenere indicizzazioni più complesse, ma sempre intuitive dal punto di vista della scrittura. Ad esempio, per selezionare "I soggetti tra i 20 e i 25 anni iscrittti a psicologia " eseguiremo:
```{r, echo = TRUE}
my_data[my_data$age >= 20 & my_data$age <=25 & my_data$faculty == "Psicologia", ]
```
Utilizzando questo metodo di indicizzazione possiamo apprezzare la vera potenza dei dataframe. Abbiamo, infatti, un metodo molto semplice ed intuitivo per lavorare con strutture di dati complesse formate da diverse tipologie di dati.
:::{.design title="Output Selezione" data-latex="[Output Selezione]"}
Due aspetti importanti riguardanti il risultato di una selezione sono la tipologia di ouput ottenuto e come salvarla.
#### Tiplogia Output {-}
In modo analogo alle matrici, i comandi di selezione non restituiscono sempre la stessa tipologia di oggetto. Infatti, quando selezioniamo una singola variabile otteniamo come risultato un vettore mentre selezionando due o più variabili oteniamo un dataframe.
```{r, echo = TRUE}
# Singola variabile
class(my_data$age)
# Più variabili
class(my_data[ , c("names", "age")])
```
#### Salvare Selezione {-}
Come per tutte le altre tipologie di oggetti, le operazioni di selezione non modificano l'oggetto iniziale. Pertanto è necessario salvare il risultato della selezione se si desidera mantenere le modifiche. In questo caso, è cosigliabile creare un nuovo oggetto e non sovrascrivere l'oggetto iniziale poichè non ci permetterebbe di compiere nuove selezioni od operazioni su tutti i dati iniziali. E' buona norma quindi mantenere sempre un dataframe con la versione dei dati originali.
:::
### Utilizzi Avanzati Selezione
Vediamo ora alcuni utilizzi avanzati della selezione di elementi di un dataframe.
#### Modificare gli Elementi {-}
In modo analogo agli altri oggetti, possiamo modificare dei valori selezionando il vecchio valore della matrice e utilizzo la funzione `<-` (o `=`) per assegnare il nuovo valore.
```{r, echo = TRUE}
my_data[1:5, ]
# Sostituisco il nome "Diego" con "Davide"
my_data[4, "names"] <- "Davide"
my_data[1:5]
```
#### Eliminare Righe o Colonne {-}
In modo analogo agli altri oggetti, per **eliminare** delle righe (o delle colonne) da un dataframe, è necessario indicare all'interno delle parentesi quadre gli indici di riga (o di colonna) che si intende eliminare, preceduti dall'operatore `-` (*meno*). Nel caso di più righe (o colone) è possibile indicare il meno solo prima del comando `c()`.
```{r, echo = TRUE}
# Elimino le variabili "gender" e "age"
my_data[ , c("gender", "age")]
# Elimino le prime 5 osservazioni
my_data[-c(1:5), ]
# Elimino le prime 5 osservazioni e la variabile "names"
my_data[-c(1:5), -3]
```
E' possibile anche escludere (ed eliminare in un certo senso) delle informazioni usando gli operatori logici in gli operatori **NOT**(`!`) e diverso da (`!=`):
```{r, echo = T}
# Seleziono tutto tranne gli studenti di psicologia
# Modo 1 (valuto disuguaglianza)
my_data[my_data$faculty != "Psicologia", ]
# Modo 1 (nego l'uguaglianza)
my_data[!my_data$faculty == "Psicologia", ]
```
Nota come l'operazione di eliminazione sia comunque un'operazione di selezione. Pertanto è necessario salvare il risultato ottenuto se si desidera mantenere le modifiche.
:::{.warning title="Attenzione ad Eliminare" data-latex="[Attenzione ad Esliminare]"}
L'utilizzo dell'operatore `-` è sempre in qualche modo pericoloso, sopratutto se l'oggetto che viene creato (o sovrascritto) viene poi utilizzato in altre operazioni. Eliminare delle informazioni, tranne quando è veramente necessario, non è mai una buona cosa. Se dovete selezionare una parte dei dati è sempre meglio creare un nuovo dataframe (o un nuovo oggetto in generale) e mantendere una versione di quello originale sempre disponibile.
:::
### Esercizi {-}
Facendo riferimento ai dataframe `data_long` e `data_wide` precedentemente creati, esegui i seguenti esercizi ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-10-dataframe.R)):
1. Utilizzando gli **indici numerici** di riga e di colonna seleziona i dati del soggetto `subj_2` riguardanti le variabili `item` e `response` dal DataFrame `data_long`.
2. Compi la stessa selezione dell'esercizio precedente usando però questa volta una condizione logica per gli indici di riga e indicando direttamente il nome delle variabili per gli indici di colonna.
3. Considerando il DataFrame `data_wide` seleziona le variabili `Id` e `gender` dei soggetti che hanno risposto 1 alla variabile `item_1`.
4. Considerando il DataFrame `data_long` seleziona solamente i dati riguardanti le ragazze con etè superiore ai 20 anni.
5. Elimina dal DataFrame `data_long` le osservazioni riguardanti il soggetto `subj_2` e la variabile `"gender"`.
## Funzioni ed Operazioni
Vediamo ora alcune funzioni frequentemente usate e le comuni operazioni eseguite con i dataframe (vedi Tabella \@ref(tab:table-df-functions)).
```{r table-df-functions}
names_function <- c("Numero di osservazioni del dataframe",
"Numero di variabili del dataframe",
"Nomi delle colonne del dataframe",
"Nomi delle righe del dataframe",
"Aggiungi una nuova variabile al dataframe (deve avere lo stesso numero di righe)",
"Aggiungi delle osservazioni (i nuovi dati devono essere coerenti con la struttura del dataframe)",
"Prime righe del dataframe",
"Ultime righe del dataframe",
"Struttura del dataframe",
"Summary del dataframe")
formula_names <-c("nrow", "ncol", "colnames", "rownames", "head", "tail", "str", "summary")
if (knitr::is_html_output()) {
df_operators <- data.frame(formula = c(
sprintf("%s(nome_df)", formula_names[1:4]),
"nome_df <-<br> cbind(nome_df, dati) <br> nome_df$nome_var <-<br> dati",
"nome_df <- rbind(nome_df, dati)",
sprintf("%s(nome_df)", formula_names[5:8])),
name = names_function)
escape = FALSE
}
if (knitr::is_latex_output()) {
df_operators <- data.frame(formula = c(
sprintf("\\texttt{%s(nome\\_df)}", formula_names[1:4]),
"\\texttt{nome\\_df <- cbind(nome\\_df, dati)} \\\\ \\texttt{nome\\_df\\$nome\\_var <- dati}",
"\\texttt{nome\\_df <- rbind(nome\\_df, dati)}",
sprintf("\\texttt{%s(nome\\_df)}", formula_names[5:8])),
name = names_function)
escape = FALSE
}
kableExtra::kable(df_operators, col.names = c("Funzione", "Descrizione"),
escape = escape, caption = "Funzioni e operazioni con dataframe") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = F,
latex_options = c("hold_position"))
```
Descriviamo ora nel dettaglio alcuni particolari utilizzi, considrando come esempio una versione ridotta del dataframe `my_data` precedentemente creata.
```{r, echo = TRUE}
data_short <- my_data[1:5, ]
data_short
```
### Attributi di un Dataframe
Abbiamo visto nel Capitolo \@ref(attributes) che gli oggetti in R possiedono quelli che sono definiti *attributi* ovvero delle utili informazioni riguardanti l'oggetto stesso, una sorta di *metadata*. Vediamo ora, in modo analogo alle matrici, come valutare la dimensione di un dataframe e i nomi delle righe e delle colonne.
#### Dimensione {-}
Ricordiamo che un dataframe è un oggetto **bidimensionale** formato da righe e colonne. Per ottenere il numero di righe e di colonne di un dataframe, possiamo usare rispettivamente i comandi `nrow()` e `ncol()`.
```{r, echo = TRUE}
# Numero di righe
nrow(my_data)
# Numero di colonne
ncol(my_data)
```
In alternativa, come per le matrici, è possibile usare la funzione `dim()`che restituisce un vettore con due valori dove il primo rappresenta il numero di righe e il secondo il numero di colonne.
#### Nomi Righe e Colonne {-}
In modo simile alle matrici, è possibile accedere ai nomi delle righe e delle colonne utilizzando rispettivamente le funzioni `rownames()` e `colnames()`. Di default il dataframe richiede dei nomi solo alle colonne mentre il alle righe viene assegnato un nome in accordo con l'indice di riga. Tuttavia, è possibile anche nominare le righe con valori arbitrari sebbene sia una funzione raramente utilizzata.
```{r, echo = TRUE}
# Controllo i nomi attuali
rownames(data_short)
colnames(data_short)
```
Per impostare i nomi di righe e/o colonne, sarà quindi necessario assegnare a `rownames(nome_dataframe)` e `colnames(nome_dataframe)` un vettore di caratteri della stessa lunghezza della dimensione che stiamo rinominando.
```{r, echo=TRUE}
# Assegnamo i nomi alle righe
rownames(data_short) <- paste0("Subj_", 1:nrow(data_short))
# Assegno i nomi alle colonne
colnames(data_short) <- c("Id", "Nome", "Genere", "Eta", "Facolta")
data_short
```
Infine, nota come la funzione `names()` nel caso dei dataframe sia analoga alla funzione `colnames()` e sia possibile usare il vaore `NULL` per eliminare ad esempio i nomi delle righe.
```{r, echo = TRUE}
names(data_short)
rownames(data_short) <- NULL
data_short
```
### Unire Dataframe
In modo analogo alle matrici è possibile unire più dataframe utilizzando le funzioni `cbind()` e `rbind()` per cui valgono gli stesssi accorgimenti riguardanti la dimensione rispettivamente di righe e colonne. Tuttavia, nel caso dei dataframe è possibile creare una nuova colonna anche utilizzando l'operatore `$`. Descriviamo ora in modo accurato i differenti utilizzi.
#### `dataframe$name <- new_var` {-}
Con la scrittura `dataframe$name <- new_var` aggiungiamo al dataframe in oggetto una nuova colonna chiamata `name` che prende i valori all'interno di `new_var`. Sarà necessario che la nuova variabile abbia lo stesso numero di valori delle righe del dataframe.
```{r, echo = T}
# Aggiungiamo la colonna "media"
data_short$Media <- c(27.5, 23.6, 28.3, 29.2, 24.8)
# Equivalente a
media_voti <- c(27.5, 23.6, 28.3, 29.2, 24.8)
data_short$Media <- media_voti
data_short
```
#### `cbind()` {-}
Con la funzione `cbind()` possiamo aggiungere una o più variabili al nostro dataframe. Nota come a differenza dell'utilizzo dell'operatore `$,`usando `cbind()` il risultato non venga automaticamente salvato ma sia necessario assegnare l'operazione ad un nuovo oggetto `dataframe <- cbind(dataframe, new_var)`. In quest'ultimo caso il nome della colonna sarà `new_var`. Se vogliamo anche rinominare la colonna possiamo usare la sintassi `cbind(dataframe, "nome" = new_var)` oppure chiamare l'oggetto direttamente con il nome desiderato:
```{r, echo = TRUE}
# aggiungo la variabile Numero_esami
numero_esami <- c(12, 14, 13, 10, 8)
cbind(data_short, numero_esami) # senza specificare il nome
cbind(data_short, "N_esami" = numero_esami) # specificando anche il nome
```
Anche in questo caso sarà necessario che le nuove variabili abbia lo stesso numero di valori delle righe del dataframe.
#### `rbind()` {-}
Leggermente più complessa (e inusuale) è l'aggiunta di righe ad un dataframe. Al contrario della matrice che di base non aveva nomi per le colonne e solo numeri o stringhe come tipologia di dato, per combinare per riga due dataframe dobbiamo avere la stessa struttura. Ovvero:
* Lo stesso numero di colonne (come per le matrici)
* Lo stesso nome delle colonne
```{r, error = T, echo = T}
data_short
# Nuovo dataset con le stesse colonne ma diverso nome
new_row <- data.frame(
Id = 6,
Nome = "Marta",
Sex = "F", # Sex invece di Genere
Eta = 44,
Facolta = "Filosofia",
Media = 28.7
)
new_row
rbind(data_short, new_row) # Errore
# Nuovo dataset con le stesse colonne con il nome corretto
new_row <- data.frame(
Id = 6,
Nome = "Marta",
Genere = "F",
Eta = 44,
Facolta = "Filosofia",
Media = 28.7
)
rbind(data_short, new_row)
```
Anche in questo caso sarà necessario salvare il risultato ottenuto per mantenere i cambiamenti.
### Informazioni Dataframe
Vediamo infine alcune funzioni molto comuni usate per ottenere informazioni riassuntive riguardo ai dati contenuti in un dataframe:
- `head()` (o `tail()`) ci permete di visualizzare le prime (o le ulitme righe del nostro dataframe)
```{r, echo = TRUE}
head(my_data)
```
- `str()` ci permete di valutare la struttura del dataset ottenendo utili informazini quali in numero di osservazioni, il numero di variabili e la ipologia di variabili
```{r, echo = TRUE}
str(my_data)
```
- `summary()` ci permete avere delle informazioni riassuntive delle variabili a seconda della loro tipologia
```{r, echo = TRUE}
summary(my_data)
```
### Esercizi {-}
Facendo riferimento ai dataframe `data_long` e `data_wide` ([soluzioni](https://github.com/psicostat/Introduction2R/blob/master/exercises/chapter-10-dataframe.R)):
1. Aggiungi sia al DataFrame `data_wide` che `data_long` la variabile numerica `"memory_pre"`.
```{r}
data.frame(Id=c("subj_1","subj_2","subj_3"),
memory_pre=c(3,2,1))
```
2. Aggiungi sia al DataFrame `data_wide` che `data_long` la variabile categoriale `"gruppo"`.
```{r}
data.frame(Id=c("subj_1","subj_2","subj_3"),
gruppo=c("trattamento","trattemento","controllo"))
```
3. Aggiungi al DataFrame `data_wide` i dati del soggetto `subj_4` e `subj_5`.
```{r}
data.frame(Id=c("subj_4","subj_5"),
age=c(25,22),
gender=c("F","M"),
item_1=c(1,1),
item_2=c(0,1),
item_3=c(2,0),
memory_pre=c(1,3),
gruppo=c("trattemento","controllo"))
```
4. Considerando il DataFrame `datawide` calcola la variabile `"memory_post"` data dalla somma degli item.
5. Considerando il DataFrame `data_wide` cambia i nomi delle variabili `item_1`, `item_2` e `item_3` rispettivamente in `problem_1`, `problem_2` e `problem_3`.