8.1 La función melt y datos en formato largo
Una tabla está en formato largo cuando cada fila contiene un dato y el resto de las columnas son etiquetas que le dan contexto. Además de ser más claras conceptualmente, suele ser más sencillo procesar tablas en formato largo. A los interesados en saber más sobre este tipo de datos se les recomienda leer el artículo Tidy Data28.
Vamos a comenzar leyendo un fichero de datos que contiene la población en 2014 de las provincias aragonesas por sexo. Se trata de un conjunto de datos simple y minúsculo pero que, gracias a eso, permite visualizar las transformaciones que vamos a realizar.
pob.aragon.2014 <- read.table("data/pob_aragon_2014.csv",
header = T, sep = "\t")
pob.aragon.2014
## Provincia Hombres Mujeres
## 1 Huesca 113840 111069
## 2 Teruel 71449 68916
## 3 Zaragoza 471675 488436
Es habitual encontrar conjuntos de datos (aunque típicamente más grandes) en formatos similares. Estos datos no están en formato largo o arreglado. En tablas arregladas, las columnas representan necesariamente variables. Sin embargo, en pob.aragon.2014
existe una variable implícita, sexo
de la que Hombres
y Mujeres
son niveles (o valores).
Podemos usar la función melt
para pivotar la tabla y arreglar los datos, i.e., disponerlos en formato largo:
library(reshape2)
melt(pob.aragon.2014)
## Provincia variable value
## 1 Huesca Hombres 113840
## 2 Teruel Hombres 71449
## 3 Zaragoza Hombres 471675
## 4 Huesca Mujeres 111069
## 5 Teruel Mujeres 68916
## 6 Zaragoza Mujeres 488436
Es evidente que la información contenida en ambos conjuntos de datos es la misma. Pero en la nueva tabla cada fila tiene un único valor. El resto de las columnas, Provincia
y variable
—como R desconoce que el nombre ideal de la nueva variable sería sexo
, por defecto, la denomina variable
— contextualizan dicha cifra.
Un ejemplo un poco más intersante es este:
pob.aragon <- read.table("data/pob_aragon.csv",
header = T, sep = "\t")
pob.aragon
## Provincia Periodo Hombres Mujeres
## 1 Huesca 2014 113840 111069
## 2 Huesca 2004 107961 104940
## 3 Teruel 2014 71449 68916
## 4 Teruel 2004 71073 68260
## 5 Zaragoza 2014 471675 488436
## 6 Zaragoza 2004 441840 455510
El nuevo conjunto de datos tiene una variable adicional, Periodo
. Si se le aplica melt
directamente, el resultado dista del esperado:
melt(pob.aragon)
## Provincia variable value
## 1 Huesca Periodo 2014
## 2 Huesca Periodo 2004
## 3 Teruel Periodo 2014
## 4 Teruel Periodo 2004
## 5 Zaragoza Periodo 2014
## 6 Zaragoza Periodo 2004
## 7 Huesca Hombres 113840
## 8 Huesca Hombres 107961
## 9 Teruel Hombres 71449
## 10 Teruel Hombres 71073
## 11 Zaragoza Hombres 471675
## 12 Zaragoza Hombres 441840
## 13 Huesca Mujeres 111069
## 14 Huesca Mujeres 104940
## 15 Teruel Mujeres 68916
## 16 Teruel Mujeres 68260
## 17 Zaragoza Mujeres 488436
## 18 Zaragoza Mujeres 455510
Efectivamente, R confunde Periodo
con un nivel más de la nueva variable, junto a Hombres
y Mujeres
. Pero, en realidad, tanto la provincia como el periodo forman la clave de la tabla. Esto se le puede indicar a melt
así:
melt(pob.aragon, id.vars = c("Provincia", "Periodo"))
## Provincia Periodo variable value
## 1 Huesca 2014 Hombres 113840
## 2 Huesca 2004 Hombres 107961
## 3 Teruel 2014 Hombres 71449
## 4 Teruel 2004 Hombres 71073
## 5 Zaragoza 2014 Hombres 471675
## 6 Zaragoza 2004 Hombres 441840
## 7 Huesca 2014 Mujeres 111069
## 8 Huesca 2004 Mujeres 104940
## 9 Teruel 2014 Mujeres 68916
## 10 Teruel 2004 Mujeres 68260
## 11 Zaragoza 2014 Mujeres 488436
## 12 Zaragoza 2004 Mujeres 455510
Los datos en formato largo están muy relacionados con los arrays (conocidos en algunos contextos empresariales como cubos multidimensionales). Un ejemplo de ellos es la tabla Titanic
de R, que se refiere a los viajeros del Titanic, y que tiene cuatro dimensiones: la clase, el sexo, el grupo de edad y si sobrevivieron o no al hundimiento:
dimnames(Titanic)
## $Class
## [1] "1st" "2nd" "3rd" "Crew"
##
## $Sex
## [1] "Male" "Female"
##
## $Age
## [1] "Child" "Adult"
##
## $Survived
## [1] "No" "Yes"
La función as.data.frame
aplicada a un array multidimensional produce una tabla en formato largo:
tmp <- as.data.frame(Titanic)
rbind(head(tmp), tail(tmp))
## Class Sex Age Survived Freq
## 1 1st Male Child No 0
## 2 2nd Male Child No 0
## 3 3rd Male Child No 35
## 4 Crew Male Child No 0
## 5 1st Female Child No 0
## 6 2nd Female Child No 0
## 27 3rd Male Adult Yes 75
## 28 Crew Male Adult Yes 192
## 29 1st Female Adult Yes 140
## 30 2nd Female Adult Yes 80
## 31 3rd Female Adult Yes 76
## 32 Crew Female Adult Yes 20
La función melt
también funciona con matrices. Una de ellas es VADeaths
. Usa melt
para disponer esa matriz en formato largo. Verás que aparece una columna con valores del tipo Rural Male
: construye a partir de ella dos columnas (sex
y residency
). Nota: existe una función auxiliar en reshape2
, colsplit
que realiza precisamente esa operación.
Toma el conjunto de datos airquality
y disponlo en formato largo. Ten cuidado con la definición de la clave de la tabla.
Cambia el nombre a la variable variable
creada automáticamente por melt
en el ejercicio anterior.
Calcula el valor mediano (median
) de las variables de airquality
(después de haberlo dispuesto en formato largo). Usa la función tapply
.
En general, disponer datos en formato largo facilita muchas operaciones de manipulación de datos. En el ejercicio anterior, en lugar de calcular la mediana variable a variable, ha sido posible obtenerla en dos líneas de código. Que son independientes, además, del número de indicadores de la tabla.
Cuyo autor lo es también del paquete
reshape2
, el tema de esta sección↩