martes, 21 de junio de 2016

Listas en R y qué hacer con ellas (2/2)

Como continuación de un post anterior sobre listas, en éste vamos a explorar las situaciones en las que se utilizan con más frecuencia y cómo tratarlas para el análisis de encuestas.

Un ejemplo: “histogram”

Para ilustrar el uso de listas en R tomamos el ejemplo del histograma, cuya estructura interna es la de una lista. Lo vemos creando el siguiente ejemplo:

x <- rnorm (100)
a <- hist (x)

is.list (a)
## [1] TRUE
str (a)
## List of 6
##  $ breaks  : num [1:13] -3 -2.5 -2 -1.5 -1 -0.5 0 0.5 1 1.5 ...
##  $ counts  : int [1:12] 2 2 5 8 22 10 18 14 9 7 ...
##  $ density : num [1:12] 0.04 0.04 0.1 0.16 0.44 0.2 0.36 0.28 0.18 0.14 ...
##  $ mids    : num [1:12] -2.75 -2.25 -1.75 -1.25 -0.75 -0.25 0.25 0.75 1.25 1.75 ...
##  $ xname   : chr "x"
##  $ equidist: logi TRUE
##  - attr(*, "class")= chr "histogram"

Como puede observarse el histograma “a” tiene una estructura de lista con seis componentes de diferentes clases de datos:

  • breaks es el vector numérico de los límites superior e inferior de los intervalos;
  • counts es el vector de números enteros de los casos incluidos en cada intervalo;
  • density es el vector numérico de la proporción de casos en cada intervalo;
  • mids es el vector numérico de los puntos medios de cada intervalo;
  • xname es el vector de cadena de caracteres del nombre del histograma;
  • equidist es el vector lógico de longitud 1 que indica si la anchura de cada intervalo es la misma o no.

El tratamiento de estos componentes y sus contenidos puede hacerse tal y como se vio en el post anterior. En “a” también se contienen metadatos (=attr).

El histograma no es el único ejemplo en R en que un objeto contiene sus resultados en formato lista. Otro caso muy habitual es el resultado de una regresión lineal (función lm), cuyo manejo analizaremos en otro futuro post.

Una lista como resultado de un split

Cuando nos interesa trocear un data.frame según el valor de una variable concreta el método idóneo es utilizar la función split. Veamos un ejemplo utilizando el data.frame mtcars incluido en R. Este data.frame recoge las características de un conjunto de modelos de automóviles con las variables siguientes:

str (mtcars)
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

La variable “cyl” describe el número de cilindros de cada modelo: 4, 6 u 8. Si ahora queremos crear diferentes data.frames según el número de cilindros, se utiliza la función split:

cilin_cars <- split (mtcars, mtcars$cyl)

El resultado es una lista, con la siguiente estructura:

str (cilin_cars,max.level = 1)
## List of 3
##  $ 4:'data.frame':   11 obs. of  11 variables:
##  $ 6:'data.frame':   7 obs. of  11 variables:
##  $ 8:'data.frame':   14 obs. of  11 variables:

El argumento max.level nos permite definir a qué nivel de profundidad queremos presentar la estructura de la lista.

Trabajar sobre una lista: la función lapply

Cuando queremos realizar una operación o función sobre todos y cada uno de los elementos de una lista, lo que en otros lenguajes de programación se resuelve habitualmente con un “loop (for)”, R lo ejecuta con una función más rápida y eficaz, la función lapply. La filosofía es la de “split-apply-combine” (dividir-ejecutar-reunir) y su sintaxis es la siguiente:

                resultado(lista) <- lapply (lista, función)

Por ejemplo:

resultado.lista <- lapply (cilin_cars, dimnames)
resultado.lista
## $`4`
## $`4`[[1]]
##  [1] "Datsun 710"     "Merc 240D"      "Merc 230"       "Fiat 128"      
##  [5] "Honda Civic"    "Toyota Corolla" "Toyota Corona"  "Fiat X1-9"     
##  [9] "Porsche 914-2"  "Lotus Europa"   "Volvo 142E"    
## 
## $`4`[[2]]
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
## 
## 
## $`6`
## $`6`[[1]]
## [1] "Mazda RX4"      "Mazda RX4 Wag"  "Hornet 4 Drive" "Valiant"       
## [5] "Merc 280"       "Merc 280C"      "Ferrari Dino"  
## 
## $`6`[[2]]
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
## 
## 
## $`8`
## $`8`[[1]]
##  [1] "Hornet Sportabout"   "Duster 360"          "Merc 450SE"         
##  [4] "Merc 450SL"          "Merc 450SLC"         "Cadillac Fleetwood" 
##  [7] "Lincoln Continental" "Chrysler Imperial"   "Dodge Challenger"   
## [10] "AMC Javelin"         "Camaro Z28"          "Pontiac Firebird"   
## [13] "Ford Pantera L"      "Maserati Bora"      
## 
## $`8`[[2]]
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"

Se crea una lista que incluye el resultado de aplicar a cada componente de la lista cilin_cars la función dimnames, que devuelve los nombres de las filas y las columnas de cada uno de los componentes de cilin_cars.

No hay comentarios:

Publicar un comentario