Capita spesso di dover convertire i dati dal formato long (chiamato anche "long-form", il cui significato sarà chiaro tra poco) al formato wide e viceversa. I dati del mondo reale arrivano nei formati più disparati, ma molte funzioni di R sono pensate per un formato specifico.
Per esempio, lme4::lmer() per i modelli lineari misti e ggplot2::ggplot() per la visualizzazione sono progettate per il long-form. Altre funzioni, come mosaicplot(), sono invece pensate per il wide-form. Questo significa che devi convertire il formato per fare analisi o visualizzazioni, a meno che i dati non siano già nel formato giusto.
In R esistono diverse opzioni per la conversione di formato, ma quando si inizia possono risultare abbastanza confuse.
In questo tutorial vedrai come capire la meccanica della conversione dei dati tra long-form e wide-form. Esplorerai i seguenti argomenti:
Approfondirai cos’è il formato long.
Poi conoscerai il formato wide.
Ripasserai le differenze tra i due formati;
Vedrai quali passaggi servono per passare da un formato all’altro.
Infine, metterai tutto in pratica con R. Imparerai a passare da un formato long a un formato wide con le funzioni melt() e dcast().
I dati
Tabella 01
name
gender
year2011
year2012
year2013
year2014
year2015
Jackson Smith
M
74.69
84.99
91.73
105.11
111.04
Sophia Johnson
F
NA
NA
NA
NA
75.89
Emma Williams
F
NA
NA
75.74
86.50
91.50
Aiden Jones
M
NA
NA
NA
71.89
81.42
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
Lucas Davis
M
70.60
83.78
94.17
100.03
106.35
Olivia Miller
F
64.78
80.76
87.30
97.13
103.80
Ava Wilson
F
88.77
96.45
104.72
112.84
NA
Questa tabella mostra l’altezza di alcuni bebè in una piccola area locale. Le altezze sono state misurate dal 2011 al 2015. Come forse sai già, NA significa ‘Not Available’. Dalla posizione degli NA puoi dedurre l’età dei bebè, ma l’età esatta non è disponibile dalla tabella. La tabella sembra ben organizzata, ma per chi vuole studiare la crescita dei bebè c’è un problema: l’informazione importante non è il momento assoluto in cui un bebè è stato misurato, bensì l’età che aveva al momento della misurazione. Riusciresti a inserire questa informazione nella tabella? Qui sotto vedi un modo:
Tabella 02
name
gender
age0
age1
age2
age3
age4
age5
age6
Jackson Smith
M
NA
76.69
84.91
97.06
105.73
107.32
NA
Sophia Johnson
F
NA
76.05
NA
NA
NA
NA
NA
Emma Williams
F
72.65
82.46
91.76
NA
NA
NA
NA
Aiden Jones
M
69.76
79.89
NA
NA
NA
NA
NA
Liam Brown
M
NA
NA
85.34
93.22
105.78
105.84
114.82
Lucas Davis
M
71.59
84.87
92.10
100.73
104.21
NA
NA
Olivia Miller
F
62.74
81.39
92.02
98.32
106.44
NA
NA
Ava Wilson
F
NA
NA
88.39
100.67
107.58
111.52
NA
Il numero di NA è aumentato. ## Dati in formato wide Ma cosa faresti se volessi indicare l’età in mesi di un bebè? Potrebbe essere qualcosa del genere:
Tabella 03
name
gender
m4
m6
m7
m10
m12
...
m55
m60
m65
m72
Jackson Smith
M
NA
NA
NA
NA
76.69
...
NA
107.32
NA
NA
Sophia Johnson
F
NA
NA
NA
NA
76.05
...
NA
NA
NA
NA
Emma Williams
F
NA
NA
NA
72.65
NA
...
NA
NA
NA
NA
Aiden Jones
M
NA
69.76
NA
NA
NA
...
NA
NA
NA
NA
Liam Brown
M
NA
NA
NA
NA
NA
...
NA
105.84
NA
114.82
Lucas Davis
M
NA
NA
71.59
NA
NA
...
104.21
NA
NA
NA
Olivia Miller
F
62.74
NA
NA
NA
NA
...
NA
NA
NA
NA
Ava Wilson
F
NA
NA
NA
NA
NA
...
NA
NA
111.52
NA
Ci sono un sacco di NA nella tabella qui sopra. Se i bebè differiscono nei tempi relativi delle misurazioni, il formato wide può sprecare molto spazio. Un’altra opzione è includere l’età dei bebè riferita al 2015, ma ciò è possibile solo quando i tempi assoluti di misurazione sono uguali per tutti. Se i bebè differiscono di mesi nel momento della misurazione e vuoi conoscere l’età in mesi, non funziona. Allora questo esempio sembra l’unico modo. In questo caso, puoi considerare il formato long. ## Dati in formato long Mentre nel formato wide tutte le misure di un bebè sono in un’unica riga, nel formato long vedi una sola misurazione per riga. Il modo più semplice per ottenere quest’ultimo è mostrare il nome del bambino, il momento della misurazione e la misurazione (altezza) su una riga. È esattamente ciò che mostra questa tabella:
Tabella 04
name
gender
month
height
Olivia Miller
F
4
62.74
Aiden Jones
M
6
69.76
Lucas Davis
M
7
71.59
Emma Williams
F
10
72.65
Jackson Smith
M
12
76.69
...
...
...
...
Liam Brown
M
72
114.82
Se ordini i dati per nome, otterrai qualcosa di simile alla tabella qui sotto. È evidente che questa tabella occupa meno spazio della Tabella 3, che vedi sopra!
Tabella 05
name
gender
month
height
Jackson Smith
M
12
76.69
Jackson Smith
M
24
84.91
Jackson Smith
M
36
97.06
Jackson Smith
M
48
105.73
Jackson Smith
M
60
107.32
Sophia Johnson
F
12
76.05
Emma Williams
F
10
72.65
...
...
...
...
Ava Wilson
F
65
111.52
Long contro Wide
Nota ancora una volta le differenze fondamentali tra wide-form e long-form: una differenza semplice è che il wide-form mostra molte misure dello stesso individuo su una riga e i nomi delle colonne indicano quali misure sono.
Questa tabella mostra le altezze di Liam Brown negli anni 2011-2015 in un’unica riga:
Tabella 06
name
gender
year2011
year2012
year2013
year2014
year2015
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
Nel long-form le altezze di Liam Brown sono mostrate in un’unica colonna:
Tabella 07
name
gender
_
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Come vedi, non puoi sapere a cosa si riferiscono le misure. Se scrivi il nome della colonna, apparirebbe così:
Tabella 08
name
gender
year2011, 2012, 2013, 2014, 2015
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Ma anche questo ha un suo problema. L’altezza di Sophia Johnson non è stata misurata negli anni 2011-2014. Quindi, come vedi sotto, il nome della colonna non può essere definito facilmente:
Tabella 09
name
gender
?
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Sophia Johnson
F
76.05
Dal formato wide al formato long
Convertire il wide-form in long-form si può vedere come un processo a step. Prima di convertire le misure di una riga in un’unica colonna, puoi riorganizzare la tabella in modo che contenga una sola misura per riga. Facciamolo per questa tabella:
Tabella 10
name
gender
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
72.65
82.46
91.76
NA
NA
NA
NA
Aiden Jones
M
69.76
79.89
NA
NA
NA
NA
NA
Il risultato è come la tabella seguente:
Tabella 11
name
gender
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
72.65
NA
NA
NA
NA
Emma Williams
F
82.46
NA
Emma Williams
F
91.76
Aiden Jones
M
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
79.89
Prima di raccogliere quelle misurazioni sparse tra le colonne in un’unica colonna, devi creare una colonna aggiuntiva che indichi cosa sono le misure, proprio come sotto:
Tabella 12
name
gender
measure
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
age0
72.65
NA
NA
NA
NA
Emma Williams
F
age1
82.46
NA
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
age1
79.89
Il nome della colonna è solitamente “measure” o “key”. Noterai nella tabella sopra che ci sono “age0”, “age1”, “age2”, “age3”, “age4”, “age5” sia tra i nomi delle colonne sia in una colonna. Se ometti i nomi delle colonne, la tabella sarà come sotto.
Tabella 13
name
gender
measure
_
__
___
____
_____
______
_______
Emma Williams
F
age0
72.65
NA
NA
NA
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
age1
79.89
Dal momento che c’è una sola misura per riga, puoi raccoglierle in un’unica colonna e il risultato sarà il seguente:
Tabella 14
name
gender
measure
Emma Williams
F
age0
72.65
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Diamo un nome di colonna nuovo a tutte le misure. Di solito si chiama "value":
Tabella 15
name
gender
measure
value
Emma Williams
F
age0
72.65
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Guarda la tabella sopra. Noti che "age" si ripete? Puoi omettere l’entità ripetuta, ottenendo questo risultato:
Tabella 16
name
gender
age
value
Emma Williams
F
0
72.65
Emma Williams
F
1
82.46
Emma Williams
F
2
91.76
Aiden Jones
M
0
69.76
Aiden Jones
M
1
79.89
Age, che si ripete in ogni riga, ora è un nome di colonna. Il nome di colonna value nella tabella sopra può essere più specifico. Lo sostituisci con height, che è più esplicito. Il risultato è nella tabella seguente:
Tabella 17
name
gender
age
height
Emma Williams
F
0
72.65
Emma Williams
F
1
82.46
Emma Williams
F
2
91.76
Aiden Jones
M
0
69.76
Aiden Jones
M
1
79.89
Confrontiamo la Tabella 15 con la Tabella 17. value, uno dei nomi di colonna della Tabella 15, può significare qualsiasi cosa, mentre height nella Tabella 17 ha un significato molto specifico: può indicare solo l’altezza, mentre il value nella Tabella 15 potrebbe essere qualunque valore, come altezza, peso, velocità o colore. Un altro modo sarebbe questo:
Tabella 18
name
gender
measure
value
Emma Williams
F
height.age0
72.65
Emma Williams
F
height.age1
82.46
Emma Williams
F
height.age2
91.76
Aiden Jones
M
height.age0
69.76
Aiden Jones
M
height.age1
79.89
Consideriamo ora il caso in cui le misure siano diverse. Se le misure sono altezza, peso e BMI, sarà come la tabella sotto. Ma in questo caso la colonna value contiene valori numerici su scale diverse, quindi leggerli può confondere. In questa tabella l’altezza è in centimetri e il peso in chilogrammi:
Tabella 19
name
gender
measure
value
Emma Williams
F
height
72.65
Emma Williams
F
weight
8.22
Emma Williams
F
BMI
22.60
Aiden Jones
M
height
69.76
Aiden Jones
M
weight
8.51
Quindi, quando converti dal wide-form al long-form, devi decidere quali valori raccogliere in un’unica colonna. Dopo di che, puoi decidere il nome della colonna.
Riepiloghiamo quanto detto finora: per convertire dal wide-form al long-form devi decidere quali colonne modificare affinché finiscano in un’unica colonna. Facendo ciò, molte colonne vengono combinate in una sola. Serve quindi un nome per quella colonna, come vedi nelle prossime tabelle:
Tabella 20
id1
id2
age0
age1
age2
Emma Williams
F
NA
82.46
91.76
Aiden Jones
M
69.76
79.89
NA
Emma Williams
F
NA
82.46
91.76
Tabella 21
id1
id2
age0
age1
age2
Emma Williams
F
NA
Emma Williams
F
82.46
Emma Williams
F
91.76
Aiden Jones
M
69.76
Aiden Jones
M
79.89
Aiden Jones
M
NA
Emma Williams
F
NA
Emma Williams
F
82.46
Emma Williams
F
91.76
Tabella 22
id1
id2
age_
age0
age1
age2
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabella 23
id1
id2
age_
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabella 24
id1
id2
key
value
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabella 25
id1
id2
key
value
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Osserva le colonne id1 e id2 nella tabella sopra. id2 non identifica un individuo ma è un attributo (genere) dell’individuo. In altre parole, puoi considerarlo una misura. Quindi puoi convertirla in un formato ancora più long. Il formato più long è composto da tre colonne: id, key e value.
Tabella 26
id
key
value
Emma Williams
gender
F
Emma Williams
age1
82.46
Emma Williams
age2
91.76
Aiden Jones
gender
F
Aiden Jones
age0
69.76
Aiden Jones
age1
79.89
Emma Williams
gender
F
Emma Williams
age1
82.46
Emma Williams
age2
91.76
La tabella sopra mostra il formato più long a partire dalla tabella 25. Ma persone diverse possono avere lo stesso nome.
In tal caso, il long-form può creare ambiguità perché id non identifica univocamente una persona. Puoi aggiungere un numero dopo il nome per distinguere le persone (per esempio, usando la funzione R make.unique()), ma non puoi distinguere un nome modificato dall’originale se conteneva già un numero. Pensa a una persona che si chiama davvero "John.2"!
La soluzione più ovvia è assegnare un ID numerico diverso a ogni persona. In tal caso, i nomi diventano un’altra misura.
La prossima tabella mostra che anche i nomi sono considerati misure. In un certo senso, questo è il vero formato più long.
Tabella 27
id
key
value
1
name
Emma Williams
1
gender
F
1
age1
82.46
1
age2
91.76
2
name
Aiden Jones
2
gender
F
2
age0
69.76
2
age1
79.89
3
name
Emma Williams
3
gender
F
3
age1
82.46
3
age2
91.76
Il formato più long è il più facile da trasformare in formato wide. Se inverti il processo di conversione dal wide al long mostrato nelle tabelle 20–25, torni al formato wide. Le tabelle qui sotto mostrano questo processo:
Tabella 28. Le misure nella colonna key si ripetono come nomi di colonna
id
key
name
gender
age0
age1
age2
1
name
Emma Williams
1
gender
F
1
age1
82.46
1
age2
91.76
2
name
Aiden Jones
2
gender
F
2
age0
69.76
2
age1
79.89
3
name
Emma Williams
3
gender
F
3
age1
82.46
3
age2
91.76
Tabella 29. La colonna key può essere eliminata
id
name
gender
age0
age1
age2
1
Emma Williams
1
F
1
82.46
1
91.76
2
Aiden Jones
2
F
2
69.76
2
79.89
3
Emma Williams
3
F
3
82.46
3
91.76
Tabella 30. Lo stesso id può essere raccolto in un’unica riga
id
name
gender
age0
age1
age2
1
Emma Williams
F
82.46
91.76
1
1
1
2
Aiden Jones
F
69.76
79.89
2
2
2
3
Emma Williams
F
82.46
91.76
3
3
3
Tabella 31. Elimina le righe che non hanno misure
id
name
gender
age0
age1
age2
1
Emma Williams
F
82.46
91.76
2
Aiden Jones
F
69.76
79.89
3
Emma Williams
F
82.46
91.76
Il fattore chiave nella conversione dal formato wide al formato long è decidere quali colonne raccogliere in un’unica colonna.
Ma non deve per forza essere una sola colonna. Puoi usarne due, se necessario, come nella tabella seguente:
Tabella 32
name
gender
h2011
h2012
w2011
w2012
Jackson Smith
M
74.69
84.99
9.60
12.0
Olivia Miller
F
NA
80.76
7.15
10.7
Ava Wilson
F
88.77
96.45
NA
15.0
Riesci a trasformarla in formato long?
Le colonne h2011, h2012, w2011, w2012 indicano altezze e pesi negli anni 2011 e 2012. height e weight sono misurate su scale diverse – cm, kg. Puoi quindi usare una sola colonna per entrambe oppure due colonne, come in questa tabella:
Tabella 33
name
gender
year
height
weight
Jackson Smith
M
2011
74.69
9.60
Jackson Smith
M
2012
84.99
12.00
Olivia Miller
F
2011
NA
80.76
Olivia Miller
F
2012
7.15
10.70
Ava Wilson
F
2011
88.77
96.45
Ava Wilson
F
2012
NA
15.00
Questo è long-form o wide-form?
Da long a wide in R
Facciamo la conversione tra long-form e wide-form con R. Ci sono molte funzioni e pacchetti per questo compito.
Tabella 34
func
package
to_long_form
to_wide_form
stack/unstack
utils
stack
unstack
reshape
stats
reshape(direction="long", ...)
reshape(direction="wide", ...)
melt/dcast
reshape2
melt
dcast
gather/spread
tidyr
gather
spread
Qui spiegherò come usare le funzioni melt() e dcast() del pacchetto reshape2. Il motivo è che stack() e unstack() sono funzioni di base, quindi il loro risultato richiede post-processing. Nota che gather() e spread() sono funzioni di tidyr anch’esse molto popolari, ma non verranno trattate in questo tutorial.
Un’altra funzione che potresti usare è reshape(), che fa parte del pacchetto stats. In realtà non confonderti con questa funzione: esiste anche un pacchetto chiamato reshape! Questo pacchetto, insieme a reshape2, è stato sviluppato per chi aveva difficoltà con reshape(). Inoltre, la funzione reshape() sembra presupporre che i dati siano longitudinali, cioè che le misurazioni si ripetano nel tempo.
Convertiamo i dati della tabella 35 nel formato long. Supponi che la tabella seguente sia memorizzata in un data.frame chiamato dat.
## name gender year2011 year2012 year2013
## 1 Jackson Smith M74.6984.9991.73
## 2 Emma Williams FNANA75.74
## 3 Liam Brown M88.24NA101.83
## 4 Ava Wilson F88.7796.45NAOfferto da
La domanda che vuoi porti è: "quali colonne combinare in un’unica colonna?".
Saranno year2011, year2012, year2013. Quando usi la funzione melt(), queste colonne vanno elencate in measure.vars:
melt(babies, measure.vars =c("year2011","year2012","year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NAOfferto da
year2011, year2012, year2013 sono le colonne in 3ª, 4ª, 5ª posizione, quindi puoi usare questa specifica:
melt(babies, measure.vars =3:5)
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NAOfferto da
Il risultato è nella tabella sopra. Nota i nomi di colonna variable e value. Le Tabelle 23 e 24 mostravano che servono nuovi nomi di colonna. La funzione melt() usa nomi predefiniti per le nuove colonne — variable e value. Puoi sovrascriverli con gli argomenti variable.name= e value.name=. Vediamolo qui sotto:
melt(babies, measure.vars=3:5, variable.name="year", value.name="height")
## name gender year height
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NAOfferto da
Nell’esempio sopra le misure sono state specificate esplicitamente. In certi contesti Id può specificare indirettamente le misure. Puoi quindi scegliere le colonne di id invece delle misure.
I risultati sono uguali nei due casi sotto. Il primo sceglie le colonne di id, il secondo le colonne da raccogliere:
melt(babies, id.vars=c("name","gender"))melt(babies, measure.vars =c("year2011","year2012","year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NAOfferto da
Se specifichi sia id.vars sia measure.vars, le colonne non incluse in nessuna delle due vengono escluse dal risultato. Per esempio, guarda il blocco di codice qui sotto:
melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"))
## name variable value
## 1 Jackson Smith year2011 74.69
## 2 Emma Williams year2011 NA
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 6 Emma Williams year2012 NA
## 7 Liam Brown year2012 NA
## 8 Ava Wilson year2012 96.45Offerto da
Inoltre, na.rm=T può eliminare gli NA:
melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"), na.rm=T)
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45Offerto da
La funzione dcast() fa l’inverso di melt(). id, variable e value sono le colonne del formato più long. dcast(data, id ~ variable, value.var="value") porta il formato più long nel formato wide.
babiesLong <-melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"), na.rm=T)
babiesLong
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45Offerto da
babiesLong ha name per id, variable per variable e value per value. Quindi puoi usare dcast() per trasformarlo in formato long:
dcast(babiesLong, name ~ variable, value.var="value")
## name year2011 year2012
## 1 Ava Wilson 88.7796.45
## 2 Jackson Smith 74.6984.99
## 3 Liam Brown 88.24NAOfferto da
Conclusione
Direi che ci siamo. In questo tutorial ti sei concentrato sulla logica e sul processo di rimodellamento dei dati. Di solito il long-form è preferito per l’analisi, ma ci sono eccezioni. La presentazione dei dati in wide-form può far risparmiare spazio quando è appropriato, ma man mano che aumentano i valori mancanti, conviene passare al long-form.
Per la conversione di formato, devi concentrarti su cosa sono le misure. Il motto del long-form è una misura per riga, mentre il wide-form ha molte misure su una riga. Quando raccogli misure distribuite su più colonne in un’unica colonna, i nomi originali delle colonne devono essere preservati in una colonna aggiuntiva. Quando distribuisci misure da un’unica colonna su più colonne, devi ricavare i nomi delle colonne dalla colonna variable.
Una volta compreso il processo, usare funzioni come dcast() e melt() diventa molto più semplice!
Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Capita spesso di dover convertire i dati dal formato long (chiamato anche "long-form", il cui significato sarà chiaro tra poco) al formato wide e viceversa. I dati del mondo reale arrivano nei formati più disparati, ma molte funzioni di R sono pensate per un formato specifico.
Per esempio,
lme4::lmer()per i modelli lineari misti eggplot2::ggplot()per la visualizzazione sono progettate per il long-form. Altre funzioni, comemosaicplot(), sono invece pensate per il wide-form. Questo significa che devi convertire il formato per fare analisi o visualizzazioni, a meno che i dati non siano già nel formato giusto.In R esistono diverse opzioni per la conversione di formato, ma quando si inizia possono risultare abbastanza confuse.
In questo tutorial vedrai come capire la meccanica della conversione dei dati tra long-form e wide-form. Esplorerai i seguenti argomenti:
melt()edcast().I dati
Questa tabella mostra l’altezza di alcuni bebè in una piccola area locale. Le altezze sono state misurate dal 2011 al 2015. Come forse sai già,
NAsignifica ‘Not Available’. Dalla posizione degli NA puoi dedurre l’età dei bebè, ma l’età esatta non è disponibile dalla tabella. La tabella sembra ben organizzata, ma per chi vuole studiare la crescita dei bebè c’è un problema: l’informazione importante non è il momento assoluto in cui un bebè è stato misurato, bensì l’età che aveva al momento della misurazione. Riusciresti a inserire questa informazione nella tabella? Qui sotto vedi un modo:Il numero di
NAè aumentato. ## Dati in formato wide Ma cosa faresti se volessi indicare l’età in mesi di un bebè? Potrebbe essere qualcosa del genere:Ci sono un sacco di
NAnella tabella qui sopra. Se i bebè differiscono nei tempi relativi delle misurazioni, il formato wide può sprecare molto spazio. Un’altra opzione è includere l’età dei bebè riferita al 2015, ma ciò è possibile solo quando i tempi assoluti di misurazione sono uguali per tutti. Se i bebè differiscono di mesi nel momento della misurazione e vuoi conoscere l’età in mesi, non funziona. Allora questo esempio sembra l’unico modo. In questo caso, puoi considerare il formato long. ## Dati in formato long Mentre nel formato wide tutte le misure di un bebè sono in un’unica riga, nel formato long vedi una sola misurazione per riga. Il modo più semplice per ottenere quest’ultimo è mostrare il nome del bambino, il momento della misurazione e la misurazione (altezza) su una riga. È esattamente ciò che mostra questa tabella:Se ordini i dati per nome, otterrai qualcosa di simile alla tabella qui sotto. È evidente che questa tabella occupa meno spazio della Tabella 3, che vedi sopra!
Long contro Wide
Nota ancora una volta le differenze fondamentali tra wide-form e long-form: una differenza semplice è che il wide-form mostra molte misure dello stesso individuo su una riga e i nomi delle colonne indicano quali misure sono.
Questa tabella mostra le altezze di Liam Brown negli anni 2011-2015 in un’unica riga:
Nel long-form le altezze di Liam Brown sono mostrate in un’unica colonna:
Come vedi, non puoi sapere a cosa si riferiscono le misure. Se scrivi il nome della colonna, apparirebbe così:
Ma anche questo ha un suo problema. L’altezza di Sophia Johnson non è stata misurata negli anni 2011-2014. Quindi, come vedi sotto, il nome della colonna non può essere definito facilmente:
Dal formato wide al formato long
Convertire il wide-form in long-form si può vedere come un processo a step. Prima di convertire le misure di una riga in un’unica colonna, puoi riorganizzare la tabella in modo che contenga una sola misura per riga. Facciamolo per questa tabella:
Il risultato è come la tabella seguente:
Prima di raccogliere quelle misurazioni sparse tra le colonne in un’unica colonna, devi creare una colonna aggiuntiva che indichi cosa sono le misure, proprio come sotto:
Il nome della colonna è solitamente
“measure”o“key”. Noterai nella tabella sopra che ci sono“age0”,“age1”,“age2”,“age3”,“age4”,“age5”sia tra i nomi delle colonne sia in una colonna. Se ometti i nomi delle colonne, la tabella sarà come sotto.Dal momento che c’è una sola misura per riga, puoi raccoglierle in un’unica colonna e il risultato sarà il seguente:
Diamo un nome di colonna nuovo a tutte le misure. Di solito si chiama "value":
Guarda la tabella sopra. Noti che "age" si ripete? Puoi omettere l’entità ripetuta, ottenendo questo risultato:
Age, che si ripete in ogni riga, ora è un nome di colonna. Il nome di colonnavaluenella tabella sopra può essere più specifico. Lo sostituisci conheight, che è più esplicito. Il risultato è nella tabella seguente:Confrontiamo la Tabella 15 con la Tabella 17.
value, uno dei nomi di colonna della Tabella 15, può significare qualsiasi cosa, mentreheightnella Tabella 17 ha un significato molto specifico: può indicare solo l’altezza, mentre il value nella Tabella 15 potrebbe essere qualunque valore, come altezza, peso, velocità o colore. Un altro modo sarebbe questo:Consideriamo ora il caso in cui le misure siano diverse. Se le misure sono altezza, peso e BMI, sarà come la tabella sotto. Ma in questo caso la colonna
valuecontiene valori numerici su scale diverse, quindi leggerli può confondere. In questa tabella l’altezza è in centimetri e il peso in chilogrammi:Quindi, quando converti dal wide-form al long-form, devi decidere quali valori raccogliere in un’unica colonna. Dopo di che, puoi decidere il nome della colonna.
Riepiloghiamo quanto detto finora: per convertire dal wide-form al long-form devi decidere quali colonne modificare affinché finiscano in un’unica colonna. Facendo ciò, molte colonne vengono combinate in una sola. Serve quindi un nome per quella colonna, come vedi nelle prossime tabelle:
Osserva le colonne
id1eid2nella tabella sopra.id2non identifica un individuo ma è un attributo (genere) dell’individuo. In altre parole, puoi considerarlo una misura. Quindi puoi convertirla in un formato ancora più long. Il formato più long è composto da tre colonne:id,keyevalue.La tabella sopra mostra il formato più long a partire dalla tabella 25. Ma persone diverse possono avere lo stesso nome.
In tal caso, il long-form può creare ambiguità perché
idnon identifica univocamente una persona. Puoi aggiungere un numero dopo il nome per distinguere le persone (per esempio, usando la funzione Rmake.unique()), ma non puoi distinguere un nome modificato dall’originale se conteneva già un numero. Pensa a una persona che si chiama davvero "John.2"!La soluzione più ovvia è assegnare un ID numerico diverso a ogni persona. In tal caso, i nomi diventano un’altra misura.
La prossima tabella mostra che anche i nomi sono considerati misure. In un certo senso, questo è il vero formato più long.
Il formato più long è il più facile da trasformare in formato wide. Se inverti il processo di conversione dal wide al long mostrato nelle tabelle 20–25, torni al formato wide. Le tabelle qui sotto mostrano questo processo:
Il fattore chiave nella conversione dal formato wide al formato long è decidere quali colonne raccogliere in un’unica colonna.
Ma non deve per forza essere una sola colonna. Puoi usarne due, se necessario, come nella tabella seguente:
Riesci a trasformarla in formato long?
Le colonne
h2011,h2012,w2011,w2012indicano altezze e pesi negli anni 2011 e 2012.heighteweightsono misurate su scale diverse – cm, kg. Puoi quindi usare una sola colonna per entrambe oppure due colonne, come in questa tabella:Questo è long-form o wide-form?
Da long a wide in R
Facciamo la conversione tra long-form e wide-form con R. Ci sono molte funzioni e pacchetti per questo compito.
Qui spiegherò come usare le funzioni
melt()edcast()del pacchettoreshape2. Il motivo è chestack()eunstack()sono funzioni di base, quindi il loro risultato richiede post-processing. Nota chegather()espread()sono funzioni ditidyranch’esse molto popolari, ma non verranno trattate in questo tutorial.Un’altra funzione che potresti usare è
reshape(), che fa parte del pacchettostats. In realtà non confonderti con questa funzione: esiste anche un pacchetto chiamatoreshape! Questo pacchetto, insieme areshape2, è stato sviluppato per chi aveva difficoltà conreshape(). Inoltre, la funzionereshape()sembra presupporre che i dati siano longitudinali, cioè che le misurazioni si ripetano nel tempo.Convertiamo i dati della tabella 35 nel formato long. Supponi che la tabella seguente sia memorizzata in un
data.framechiamatodat.babies = data.frame(name= c("Jackson Smith", "Emma Williams", "Liam Brown", "Ava Wilson"), gender = c("M", "F", "M", "F"), year2011= c(74.69, NA, 88.24, 88.77), year2012=c(84.99, NA, NA, 96.45), year2013=c(91.73, 75.74, 101.83, NA)) babies
La domanda che vuoi porti è: "quali colonne combinare in un’unica colonna?".
Saranno
year2011,year2012,year2013. Quando usi la funzionemelt(), queste colonne vanno elencate inmeasure.vars:year2011,year2012,year2013sono le colonne in 3ª, 4ª, 5ª posizione, quindi puoi usare questa specifica:Il risultato è nella tabella sopra. Nota i nomi di colonna
variableevalue. Le Tabelle 23 e 24 mostravano che servono nuovi nomi di colonna. La funzionemelt()usa nomi predefiniti per le nuove colonne —variableevalue. Puoi sovrascriverli con gli argomentivariable.name=evalue.name=. Vediamolo qui sotto:Nell’esempio sopra le misure sono state specificate esplicitamente. In certi contesti
Idpuò specificare indirettamente le misure. Puoi quindi scegliere le colonne di id invece delle misure.I risultati sono uguali nei due casi sotto. Il primo sceglie le colonne di id, il secondo le colonne da raccogliere:
Se specifichi sia
id.varssiameasure.vars, le colonne non incluse in nessuna delle due vengono escluse dal risultato. Per esempio, guarda il blocco di codice qui sotto:Inoltre,
na.rm=Tpuò eliminare gli NA:La funzione
dcast()fa l’inverso dimelt().id,variableevaluesono le colonne del formato più long.dcast(data, id ~ variable, value.var="value")porta il formato più long nel formato wide.babiesLongha name perid, variable pervariablee value pervalue. Quindi puoi usaredcast()per trasformarlo in formato long:Conclusione
Direi che ci siamo. In questo tutorial ti sei concentrato sulla logica e sul processo di rimodellamento dei dati. Di solito il long-form è preferito per l’analisi, ma ci sono eccezioni. La presentazione dei dati in wide-form può far risparmiare spazio quando è appropriato, ma man mano che aumentano i valori mancanti, conviene passare al long-form.
Per la conversione di formato, devi concentrarti su cosa sono le misure. Il motto del long-form è una misura per riga, mentre il wide-form ha molte misure su una riga. Quando raccogli misure distribuite su più colonne in un’unica colonna, i nomi originali delle colonne devono essere preservati in una colonna aggiuntiva. Quando distribuisci misure da un’unica colonna su più colonne, devi ricavare i nomi delle colonne dalla colonna
variable.Una volta compreso il processo, usare funzioni come
dcast()emelt()diventa molto più semplice!