Hay momentos en los que necesitas convertir datos del formato largo (lo llamaremos «formato long», y enseguida verás a qué nos referimos) al formato ancho y viceversa. En la vida real, los datos llegan en todo tipo de formatos, pero muchas funciones de R están pensadas para un formato concreto.
Por ejemplo, lme4::lmer() para modelos lineales mixtos y ggplot2::ggplot() para visualización están diseñadas para formato long. Otras, como mosaicplot(), funcionan mejor con formato ancho. Eso significa que tendrás que convertir el formato para analizar o visualizar, salvo que tus datos ya estén procesados y en el formato adecuado.
En R hay varias opciones para convertir formatos, pero al empezar puede resultar algo confuso.
En este tutorial vas a entender la mecánica de convertir datos entre formato long y ancho. Verás estas ideas:
Aprenderás qué es el formato long.
Después, verás el formato ancho.
Repasarás las diferencias entre ambos;
Y qué pasos seguir para pasar de un formato a otro.
Por último, lo pondrás en práctica en R. Verás cómo pasar de formato long a formato ancho con las funciones melt() y dcast().
Los datos
Tabla 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
Esta tabla muestra la estatura de bebés en una zona local. Las mediciones van de 2011 a 2015. Como sabrás, NA significa «no disponible». Por la posición de los NA puedes deducir la edad de los bebés, pero la edad exacta no aparece. Aunque la tabla parece ordenada, para estudiar el crecimiento hay un problema: lo relevante no es el momento absoluto de la medición, sino la edad que tenía el bebé al medirse. ¿Podrías añadir esa información a la tabla? Aquí tienes una forma:
Tabla 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
Ha aumentado el número de NA. ## Datos en formato ancho Pero ¿qué harías si quisieras indicar cuántos meses tenía el bebé? Podría verse así:
Tabla 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
Como ves, hay muchísimos NA. Si las edades relativas difieren, el formato ancho desperdicia mucho espacio. Otra opción sería indicar las edades que tenían en 2015, pero solo funciona si todos se midieron en el mismo momento absoluto. Si difieren por meses y quieres saber la edad en meses, no sirve. En ese caso, este ejemplo parece la única forma. Aquí te conviene usar el formato long. ## Datos en formato long Mientras que en el formato ancho todas las mediciones de un bebé están en una sola fila, en el formato long cada fila contiene una única medición de un bebé. La forma más simple es poner en una fila el nombre, el momento de medida y el valor (altura). Eso es lo que ves aquí:
Tabla 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
Si ordenas por nombre, obtendrás algo como la tabla siguiente. Claramente ocupa menos espacio que la Tabla 3 de arriba.
Tabla 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
Formato long frente a ancho
Recuerda las diferencias fundamentales entre formato ancho y long: una diferencia simple es que el formato ancho muestra muchas mediciones de un individuo en una sola fila y los nombres de columna indican qué mide cada una.
Esta tabla muestra las alturas de Liam Brown entre 2011 y 2015 en una sola fila:
Tabla 06
name
gender
year2011
year2012
year2013
year2014
year2015
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
En formato long, las alturas de Liam Brown aparecen en una sola columna:
Tabla 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
Como ves, no puedes saber a qué corresponde cada medición. Si incluyes el nombre de la columna, quedaría así:
Tabla 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
Pero esto tiene su propio problema. A Sophia Johnson no se le midió la altura en 2011-2014. Así que, como ves, el nombre de la columna no se puede fijar fácilmente:
Tabla 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
De formato ancho a formato long
Convertir de ancho a long puede verse como un proceso por pasos. Antes de pasar todas las mediciones de una fila a una columna, puedes crear una tabla con una sola medición por fila. Hagámoslo con esta tabla:
Tabla 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
El resultado sería como esta tabla:
Tabla 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
Antes de reunir en una sola columna esas mediciones dispersas, necesitas una columna adicional que indique qué medición es, como aquí:
Tabla 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
El nombre de esa columna suele ser "measure" o "key". Fíjate que aparecen "age0", "age1", "age2", "age3", "age4", "age5" tanto como nombres de columna como en una columna. Si omites los nombres de columna, la tabla queda así:
Tabla 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
Como ahora hay una sola medición por fila, ya puedes reunirlas en una única columna. El resultado sería:
Tabla 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
Vamos a darle un nombre a esa nueva columna de valores. Normalmente se llama «value»:
Tabla 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
Mira la tabla anterior. ¿Ves que «age» se repite? Puedes eliminar esa parte repetida y quedarte con:
Tabla 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, que se repetía en cada fila, ahora es el nombre de una columna. Y value puede ser más específico: cámbialo por height, que es más informativo. El resultado:
Tabla 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
Compáralas: en la Tabla 15, value podría significar cualquier cosa; en la Tabla 17, height es específico: solo puede ser altura. Otra opción sería esta:
Tabla 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
Piensa ahora que las mediciones son diversas. Si tienes altura, peso y el IMC, quedaría como la siguiente tabla. Pero en este caso, value mezcla magnitudes en escalas distintas y puede confundir. Aquí la altura está en centímetros y el peso en kilogramos:
Tabla 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
Así que, al convertir de ancho a long, debes decidir qué valores reunirás en una sola columna. Después eliges el nombre de esa columna.
Resumamos: para convertir de ancho a long debes decidir qué columnas combinar en una sola. Al hacerlo, muchas columnas se condensan en una. Necesitas un nombre para esa nueva columna, como verás en las tablas siguientes:
Tabla 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
Tabla 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
Tabla 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
Tabla 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
Tabla 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
Tabla 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
Fíjate en las columnas id1 e id2. id2 no identifica a una persona, sino que es un atributo (gender). Es decir, también es una medición. Así que puedes llevarla al formato aún más long. El formato «más largo» tiene tres columnas: id, key y value.
Tabla 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 tabla anterior muestra el formato más long a partir de la tabla 25. Pero diferentes personas pueden compartir nombre.
En ese caso, el formato long puede ser confuso porque id no identifica de forma única. Puedes añadir un número al nombre para distinguir (por ejemplo, con make.unique() de R), pero no puedes diferenciar entre un nombre original y uno que ya llevaba un número. ¡Imagina a alguien que realmente se llame «John.2»!
La salida obvia es asignar un identificador numérico distinto a cada persona. En ese caso, los nombres pasan a ser otra medición.
La siguiente tabla trata incluso los nombres como mediciones. En cierto modo, es el formato verdaderamente más long.
Tabla 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
El formato más long es el más sencillo para volver al formato ancho. Si inviertes el proceso de las Tablas 20 a 25, llegas al formato ancho. Aquí se muestra el proceso:
Tabla 28. Las mediciones en la columna key pasan a los nombres de columna
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
Tabla 29. Se puede eliminar la columna key
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
Tabla 30. Reúne en una fila los registros con el mismo id
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
Tabla 31. Elimina las filas sin mediciones
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
La clave al convertir de ancho a long es decidir qué columnas se reunirán en una sola.
Pero no tiene por qué ser solo una. Puedes usar dos columnas si lo necesitas, como en la tabla siguiente:
Tabla 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
¿Puedes pasarlo a formato long?
Las columnas h2011, h2012, w2011, w2012 representan altura y peso en 2011 y 2012. height y weight están en escalas distintas (cm, kg). Puedes reunir ambas en una sola columna o usar dos columnas, como aquí:
Tabla 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
¿Esto es formato long o ancho?
De long a ancho en R
Vamos a hacer la conversión entre formatos long y ancho en R. Hay muchas funciones y paquetes para ello.
Tabla 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
Aquí explicaremos cómo usar melt() y dcast() del paquete reshape2. ¿Por qué? Porque stack() y unstack() son funciones básicas y suelen requerir posprocesado. Ten en cuenta que gather() y spread() de tidyr también son muy populares, pero no las cubriremos en este tutorial.
Otra función que puedes usar es reshape(), del paquete stats. Ojo, no la confundas con el paquete reshape. Este paquete, junto con reshape2, se creó precisamente para quienes tenían dificultades con reshape(). Además, reshape() parece asumir datos longitudinales (mediciones repetidas en el tiempo).
Convirtamos los datos de la tabla 35 al formato long. Supón que la tabla siguiente está en un data.frame llamado 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.45NACon la tecnología de
La pregunta que debes hacerte es: «¿qué columnas voy a combinar en una sola?».
Serían year2011, year2012, year2013. Al usar melt(), esas columnas van en 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 NACon la tecnología de
year2011, year2012, year2013 están en las columnas 3, 4 y 5, así que también puedes indicar eso:
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 NACon la tecnología de
El resultado es la tabla de arriba. Fíjate en los nombres de columna variable y value. Las tablas 23 y 24 mostraron que se necesitan nuevos nombres. melt() usa esos por defecto, pero puedes cambiarlos con variable.name= y value.name=. Hagámoslo:
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 NACon la tecnología de
Las mediciones se especificaron arriba. En estos casos, Id puede especificar indirectamente las mediciones. Así que puedes elegir columnas para id en lugar de para mediciones.
Los resultados son iguales en ambos casos. El primero elige columnas para id, el segundo elige columnas para reunir:
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 NACon la tecnología de
Si especificas tanto id.vars como measure.vars, las columnas no incluidas en ninguna se excluyen del resultado. Mira el siguiente bloque de código:
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.45Con la tecnología de
Además, na.rm=T puede eliminar los 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.45Con la tecnología de
La función dcast() hace lo inverso a melt(). id, variable y value son las columnas del formato más long. dcast(data, id ~ variable, value.var="value") lleva el formato más long al formato ancho.
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.45Con la tecnología de
babiesLong tiene name para id, variable para variable y value para value. Así que puedes usar dcast() para pasarlo a 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.24NACon la tecnología de
Conclusión
Eso es todo. En este tutorial te has centrado en entender la lógica y el proceso de reestructuración de datos. Normalmente, el formato long es preferible para el análisis, pero hay excepciones. La presentación de datos en formato ancho puede ahorrar espacio cuando es apropiado, pero a medida que aumenta el número de valores faltantes, es mejor convertir al formato long.
Para la conversión de formato, debes centrarte en cuáles son las mediciones. El lema del formato long es una medición por fila, y el formato ancho tiene muchas mediciones en una fila. Cuando haces que las mediciones a lo largo de las columnas se reúnan en una sola, los nombres de columna originales deben conservarse en una columna adicional. Cuando haces que las mediciones en una columna se dispersen a lo largo de las columnas, debes averiguar cuáles deberían ser los nombres de columna a partir de la columna variable.
Una vez que entiendes el proceso, usar funciones como dcast() y melt() resulta mucho más fácil.
Averigua cómo importar datos a R, incluidos archivos CSV, JSON, Excel, HTML, bases de datos, SAS, SPSS, Matlab y otros, utilizando los conocidos paquetes de R.
Hay momentos en los que necesitas convertir datos del formato largo (lo llamaremos «formato long», y enseguida verás a qué nos referimos) al formato ancho y viceversa. En la vida real, los datos llegan en todo tipo de formatos, pero muchas funciones de R están pensadas para un formato concreto.
Por ejemplo,
lme4::lmer()para modelos lineales mixtos yggplot2::ggplot()para visualización están diseñadas para formato long. Otras, comomosaicplot(), funcionan mejor con formato ancho. Eso significa que tendrás que convertir el formato para analizar o visualizar, salvo que tus datos ya estén procesados y en el formato adecuado.En R hay varias opciones para convertir formatos, pero al empezar puede resultar algo confuso.
En este tutorial vas a entender la mecánica de convertir datos entre formato long y ancho. Verás estas ideas:
melt()ydcast().Los datos
Esta tabla muestra la estatura de bebés en una zona local. Las mediciones van de 2011 a 2015. Como sabrás,
NAsignifica «no disponible». Por la posición de los NA puedes deducir la edad de los bebés, pero la edad exacta no aparece. Aunque la tabla parece ordenada, para estudiar el crecimiento hay un problema: lo relevante no es el momento absoluto de la medición, sino la edad que tenía el bebé al medirse. ¿Podrías añadir esa información a la tabla? Aquí tienes una forma:Ha aumentado el número de
NA. ## Datos en formato ancho Pero ¿qué harías si quisieras indicar cuántos meses tenía el bebé? Podría verse así:Como ves, hay muchísimos
NA. Si las edades relativas difieren, el formato ancho desperdicia mucho espacio. Otra opción sería indicar las edades que tenían en 2015, pero solo funciona si todos se midieron en el mismo momento absoluto. Si difieren por meses y quieres saber la edad en meses, no sirve. En ese caso, este ejemplo parece la única forma. Aquí te conviene usar el formato long. ## Datos en formato long Mientras que en el formato ancho todas las mediciones de un bebé están en una sola fila, en el formato long cada fila contiene una única medición de un bebé. La forma más simple es poner en una fila el nombre, el momento de medida y el valor (altura). Eso es lo que ves aquí:Si ordenas por nombre, obtendrás algo como la tabla siguiente. Claramente ocupa menos espacio que la Tabla 3 de arriba.
Formato long frente a ancho
Recuerda las diferencias fundamentales entre formato ancho y long: una diferencia simple es que el formato ancho muestra muchas mediciones de un individuo en una sola fila y los nombres de columna indican qué mide cada una.
Esta tabla muestra las alturas de Liam Brown entre 2011 y 2015 en una sola fila:
En formato long, las alturas de Liam Brown aparecen en una sola columna:
Como ves, no puedes saber a qué corresponde cada medición. Si incluyes el nombre de la columna, quedaría así:
Pero esto tiene su propio problema. A Sophia Johnson no se le midió la altura en 2011-2014. Así que, como ves, el nombre de la columna no se puede fijar fácilmente:
De formato ancho a formato long
Convertir de ancho a long puede verse como un proceso por pasos. Antes de pasar todas las mediciones de una fila a una columna, puedes crear una tabla con una sola medición por fila. Hagámoslo con esta tabla:
El resultado sería como esta tabla:
Antes de reunir en una sola columna esas mediciones dispersas, necesitas una columna adicional que indique qué medición es, como aquí:
El nombre de esa columna suele ser
"measure"o"key". Fíjate que aparecen"age0","age1","age2","age3","age4","age5"tanto como nombres de columna como en una columna. Si omites los nombres de columna, la tabla queda así:Como ahora hay una sola medición por fila, ya puedes reunirlas en una única columna. El resultado sería:
Vamos a darle un nombre a esa nueva columna de valores. Normalmente se llama «value»:
Mira la tabla anterior. ¿Ves que «age» se repite? Puedes eliminar esa parte repetida y quedarte con:
Age, que se repetía en cada fila, ahora es el nombre de una columna. Yvaluepuede ser más específico: cámbialo porheight, que es más informativo. El resultado:Compáralas: en la Tabla 15,
valuepodría significar cualquier cosa; en la Tabla 17,heightes específico: solo puede ser altura. Otra opción sería esta:Piensa ahora que las mediciones son diversas. Si tienes altura, peso y el IMC, quedaría como la siguiente tabla. Pero en este caso,
valuemezcla magnitudes en escalas distintas y puede confundir. Aquí la altura está en centímetros y el peso en kilogramos:Así que, al convertir de ancho a long, debes decidir qué valores reunirás en una sola columna. Después eliges el nombre de esa columna.
Resumamos: para convertir de ancho a long debes decidir qué columnas combinar en una sola. Al hacerlo, muchas columnas se condensan en una. Necesitas un nombre para esa nueva columna, como verás en las tablas siguientes:
Fíjate en las columnas
id1eid2.id2no identifica a una persona, sino que es un atributo (gender). Es decir, también es una medición. Así que puedes llevarla al formato aún más long. El formato «más largo» tiene tres columnas:id,keyyvalue.La tabla anterior muestra el formato más long a partir de la tabla 25. Pero diferentes personas pueden compartir nombre.
En ese caso, el formato long puede ser confuso porque
idno identifica de forma única. Puedes añadir un número al nombre para distinguir (por ejemplo, conmake.unique()de R), pero no puedes diferenciar entre un nombre original y uno que ya llevaba un número. ¡Imagina a alguien que realmente se llame «John.2»!La salida obvia es asignar un identificador numérico distinto a cada persona. En ese caso, los nombres pasan a ser otra medición.
La siguiente tabla trata incluso los nombres como mediciones. En cierto modo, es el formato verdaderamente más long.
El formato más long es el más sencillo para volver al formato ancho. Si inviertes el proceso de las Tablas 20 a 25, llegas al formato ancho. Aquí se muestra el proceso:
La clave al convertir de ancho a long es decidir qué columnas se reunirán en una sola.
Pero no tiene por qué ser solo una. Puedes usar dos columnas si lo necesitas, como en la tabla siguiente:
¿Puedes pasarlo a formato long?
Las columnas
h2011,h2012,w2011,w2012representan altura y peso en 2011 y 2012.heightyweightestán en escalas distintas (cm, kg). Puedes reunir ambas en una sola columna o usar dos columnas, como aquí:¿Esto es formato long o ancho?
De long a ancho en R
Vamos a hacer la conversión entre formatos long y ancho en R. Hay muchas funciones y paquetes para ello.
Aquí explicaremos cómo usar
melt()ydcast()del paquetereshape2. ¿Por qué? Porquestack()yunstack()son funciones básicas y suelen requerir posprocesado. Ten en cuenta quegather()yspread()detidyrtambién son muy populares, pero no las cubriremos en este tutorial.Otra función que puedes usar es
reshape(), del paquetestats. Ojo, no la confundas con el paquetereshape. Este paquete, junto conreshape2, se creó precisamente para quienes tenían dificultades conreshape(). Además,reshape()parece asumir datos longitudinales (mediciones repetidas en el tiempo).Convirtamos los datos de la tabla 35 al formato long. Supón que la tabla siguiente está en un
data.framellamadodat.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 pregunta que debes hacerte es: «¿qué columnas voy a combinar en una sola?».
Serían
year2011,year2012,year2013. Al usarmelt(), esas columnas van enmeasure.vars:year2011,year2012,year2013están en las columnas 3, 4 y 5, así que también puedes indicar eso:El resultado es la tabla de arriba. Fíjate en los nombres de columna
variableyvalue. Las tablas 23 y 24 mostraron que se necesitan nuevos nombres.melt()usa esos por defecto, pero puedes cambiarlos convariable.name=yvalue.name=. Hagámoslo:Las mediciones se especificaron arriba. En estos casos,
Idpuede especificar indirectamente las mediciones. Así que puedes elegir columnas para id en lugar de para mediciones.Los resultados son iguales en ambos casos. El primero elige columnas para id, el segundo elige columnas para reunir:
Si especificas tanto
id.varscomomeasure.vars, las columnas no incluidas en ninguna se excluyen del resultado. Mira el siguiente bloque de código:Además,
na.rm=Tpuede eliminar los NA:La función
dcast()hace lo inverso amelt().id,variableyvalueson las columnas del formato más long.dcast(data, id ~ variable, value.var="value")lleva el formato más long al formato ancho.babiesLongtiene name paraid, variable paravariabley value paravalue. Así que puedes usardcast()para pasarlo a formato long:Conclusión
Eso es todo. En este tutorial te has centrado en entender la lógica y el proceso de reestructuración de datos. Normalmente, el formato long es preferible para el análisis, pero hay excepciones. La presentación de datos en formato ancho puede ahorrar espacio cuando es apropiado, pero a medida que aumenta el número de valores faltantes, es mejor convertir al formato long.
Para la conversión de formato, debes centrarte en cuáles son las mediciones. El lema del formato long es una medición por fila, y el formato ancho tiene muchas mediciones en una fila. Cuando haces que las mediciones a lo largo de las columnas se reúnan en una sola, los nombres de columna originales deben conservarse en una columna adicional. Cuando haces que las mediciones en una columna se dispersen a lo largo de las columnas, debes averiguar cuáles deberían ser los nombres de columna a partir de la columna
variable.Una vez que entiendes el proceso, usar funciones como
dcast()ymelt()resulta mucho más fácil.