Modelos Estadísticos. Grado Biotecnología



Introducción


Esta unidad mostrará cómo utilizar la visualización y la transformación para explorar los datos de un diseño experimental de una manera sistemática, una tarea que los estadísticos llaman análisis exploratorio de datos, o AED (EDA en inglés) para abreviar. Los contenidos para este tema se han obtenido de Wickham and Grolemund (2016).

EDA es un ciclo iterativo en el que el investigador debe: este caso se irán mezclando los contenidos teóricos con los prácticos para ir mostrando el funcionamiento de las diferentes funciones y procedimientos para el análisis inicial de nuestro banco de datos.

  • Generar preguntas sobre tus datos.
  • Buscar respuestas visualizando, transformando y modelando sus datos.
  • Usar lo que aprende para refinar sus preguntas y / o generar nuevas preguntas.

EDA no es un proceso formal con un conjunto estricto de reglas. Más que nada, EDA es un estado mental. Durante las fases iniciales de EDA, debe sentirse libre de investigar cada idea que se le ocurra. Algunas de estas ideas funcionarán, y algunas serán callejones sin salida. A medida que continúe su exploración, se dirigirá a algunas áreas particularmente productivas que eventualmente escribirá y comunicará a otros.

El EDA es una parte importante de cualquier análisis de datos porque siempre debe investigar la calidad de sus datos. La limpieza de datos es solo una aplicación de EDA: el investigador debe hacer preguntas sobre si sus datos cumplen con sus expectativas o no. Para realizar la limpieza de datos, deberá implementar todas las herramientas de EDA: visualización, transformación y modelado.


Objetivos


El objetivo durante EDA es desarrollar una comprensión de los datos experimentales recogidos. La forma más fácil de hacerlo es utilizar preguntas como herramientas para guiar su investigación. Cuando se hace una pregunta, la pregunta centra la atención del investigador en una parte específica del conjunto de datos y le ayuda a decidir qué gráficos, modelos o transformaciones realizar.

EDA es fundamentalmente un proceso creativo. Como la mayoría de los procesos creativos, la clave para hacer preguntas de calidad es generar una gran cantidad de preguntas. Es difícil hacer preguntas reveladoras al comienzo del análisis porque el investigador no sabe qué información contiene su conjunto de datos. Por otro lado, cada nueva pregunta que haga le expondrá a un nuevo aspecto de sus datos y aumentará sus posibilidades de hacer un descubrimiento. Se puede profundizar rápidamente en las partes más interesantes de los datos experimentales recogidos y desarrollar una serie de preguntas que invitan a la reflexión, si se realiza un seguimiento de cada pregunta con una nueva pregunta basada en lo que se encuentre.

No hay una regla sobre qué preguntas se deben hacer para guiar la investigación, ya que debe ser el investigador en función de los objetivos del experimento planteado el que desarrolle dichas preguntas. Sin embargo, dos tipos de preguntas siempre serán útiles para hacer descubrimientos dentro de los datos. Estas preguntas son:

  • ¿Qué tipo de variabilidad ocurre dentro de las variables recogidas?
  • ¿Qué tipo de covariación (o variabilidad conjunta entre dos o más variables) ocurre entre las variables recogidas?

Variabilidad


La variabilidad es la tendencia de los valores de una variable a cambiar de medición a medición. Dicha variabilidad se parecía claramente en la vida real; si se mide cualquier variable continua dos veces, se obtendrán dos resultados diferentes. Esto es cierto incluso si se miden cantidades que son constantes, como la velocidad de la luz. Cada una de sus medidas incluirá una pequeña cantidad de error que varía de una medida a otra. Las variables categóricas también pueden variar si se miden diferentes sujetos (por ejemplo, los colores de los ojos de diferentes personas) o en diferentes momentos (por ejemplo, los niveles de energía de un electrón en diferentes momentos). Cada variable tiene su propio patrón de variación, que puede revelar información interesante. La mejor manera de entender ese patrón es visualizar la distribución de los valores de la variable mediante descriptores numéricos o gráficos.

Si la variación describe el comportamiento dentro de una variable, la covariación describe el comportamiento entre las variables. La covariación es la tendencia de los valores de dos o más variables a variar juntas de una manera relacionada. La mejor forma de detectar la covariación es visualizar la relación entre dos o más variables. Cómo hacer eso nuevamente debería depender del tipo de variables involucradas.


Procesado inicial


La descripción numérica y la visualización gráfica son las herramientas más importantes en los pasos iniciales para la generación de conocimiento sobre los datos experimentales, pero en ocasiones los datos no son recogidos en la forma más efectiva para realizar dichos análisis. A menudo se necesitara crear algunas variables o resúmenes nuevos, o tal vez solo se quiera cambiar el nombre de las variables o reordenar las observaciones para facilitar el trabajo de los datos. En este tema aprenderemos cómo hacer todo eso. Para ejemplificar los procedimientos utilizaremos el conjunto de datos flights contenido en la librería nycflights13 , que contiene toda la información sobre los vuelos que salieron desde la ciudad de Nueva York en 2013.

Recuerda que debes instalar dicha librería antes de poder reproducir todo los procedimiento que mostramos en las secciones siguientes.

Instalamos la librería (junto con todas las necesarias para la asignatura) y cargamos los datos para poder visualizarlos:

library(tidyverse)
library(stringr)
library(forcats)
library(lubridate)
library(magrittr)
library(broom)
library(datasets)
library(nycflights13)

Visualizamos los primeras 10000 observaciones del banco de datos

flights

Las variables que contiene este banco de datos (336776 observaciones = vuelos) son:

  • year: Fecha de salida (año).
  • month: Fecha de salida (mes).
  • year,month,day: Fecha de salida (día).
  • dep_time: Hora real de salida.
  • arr_time: Hora real de llegada (en horario de la ciudad de llegada).
  • sched_dep_time: Hora programada de salida. (Esta variable debe coincidir con la información de las variables hour y minute)
  • sched_arr_time: Hora programada de llegada (en horario de la ciudad de llegada).
  • dep_delay: Demora de salida (en minutos). Los tiempos negativos representan salidas tempranas.
  • arr_delay: Demora de llegada (en minutos). Los tiempos negativos representan llegadas tempranas.
  • hour: Hora de partida programada.
  • minute: Minuto de partida programada.
  • carrier: Aerolínea encargada del vuelo
  • tailnum: Identificador del avión
  • flight: Identificador del vuelo
  • origin: Origen del vuelo
  • dest: Destino del vuelo
  • air_time: Tiempo de vuelo (en minutos)
  • distance: Distancia entre los dos aeropuertos (en millas)
  • time_hour: Fecha y hora programadas del vuelo como una fecha POSIXct. Junto con el origen, se puede usar para unir datos de vuelos a datos meteorológicos.

En la cabecera del conjunto de datos se aprecia además el tipo de variable asignada. Los tipos de variables que se admiten en R son: int para enteros, dbl para números reales, chr para vectores de caracteres o cadenas, dttm para fechas-tiempos (una fecha + una hora), lgl para vectores lógicos que solo contienen VERDADERO o FALSO, fctr para factores (que R usa para representar variables categóricas con valores posibles fijos), y date para fechas.

Trabajando con sujetos

Los procedimientos para el trabajo con los sujetos de nuestra muestra se reducen al filtrado u ordenación, para quedarnos con un subconjunto de sujetos o para organizar su visualización en otra forma.

Filtrado

Usamos el filtrado para seleccionar un subconjunto de observaciones del data.frame que contiene nuestros datos. Esto se hace a menudo cuando queremos limitar un análisis a un subconjunto de observaciones. El uso básico del filtro se hace mediante la función filter():

filter(data_set, <expression1>, <expression2>, ...)

donde data_set es el nombre del objeto que contiene nuestros datos y <expression1>, <expression2>,...son uno o más argumentos adicionales, donde cada uno de estos es una expresión de R válida que implica una o más condiciones a aplicar sobre las variables del conjunto de datos. Cada expresión se interpreta como una condición lógica (verdadero o falso).

Para usar el filtrado de manera efectiva, se debe saber cómo seleccionar las observaciones que se desea utilizando los operadores de comparación. R proporciona el paquete estándar: > (mayor que), >= (mayor o igual que), < (menor que), <= (menor o igual que), != (no igual a), y == (igual a).

Veamos diferentes posibilidades de filtrado sobre el banco de datos flights. En primer lugar filtramos todos los vuelos cuya día de origen sea el 1 de enero de 2013

filter(flights, month == 1, day == 1)

El resultado es un conjunto de datos con 842 observaciones donde aparece la información de dichos vuelos. Si queremos almacenar el resultado para un trabajo posterior podemos asignarlo a un nuevo objeto

jan1 <- filter(flights, month == 1, day == 1)
str(jan1) # La función str() nos da la estructura del banco de datos resultante (número de variables y observaciones, así como una muestra de los datos para cada variable)
## Classes 'tbl_df', 'tbl' and 'data.frame':    842 obs. of  19 variables:
##  $ year          : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day           : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_time      : int  517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int  515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int  830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int  819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr  "UA" "UA" "AA" "B6" ...
##  $ flight        : int  1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr  "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr  "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr  "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num  227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num  1400 1416 1089 1576 762 ...
##  $ hour          : num  5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num  15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct, format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...

Podemos combinar diferentes condiciones de filtrado mediante los operadores lógicos & es “y” (condición 1 y condición 2), | es “o” (condición 1 o condición 2).

Queremos seleccionar ahora todos los vuelos con mes de origen igual a Noviembre o Diciembre

nov_dec <- filter(flights, month == 11 | month == 12)
dim(nov_dec) # Para saber cuantas observaciones contiene el banco de datos filtrado 
## [1] 55403    19

Los datos filtrados contienen la información completa de 55403 vuelos. Otra forma de conseguir el mismo resultado es con el operador %in%

nov_dec <- filter(flights, month %in% c(11, 12))
dim(nov_dec)
## [1] 55403    19

A veces se pueden simplificar condiciones de filtrado más complicadas sin más que recordar la ley de De Morgan: !(x & y) es lo mismo que!x | !y, y!(x | y)es lo mismo que!x & !y`. Por ejemplo, si se desean obtener todos vuelos que no se retrasaron (en llegada o partida) en más de dos horas, se pueden usar cualquiera de los dos filtros siguientes:

db_sel1 <- filter(flights, !(arr_delay > 120 | dep_delay > 120))
dim(db_sel1)
## [1] 316050     19
db_sel2 <- filter(flights, arr_delay <= 120, dep_delay <= 120)
dim(db_sel2)
## [1] 316050     19

Ordenación

Otro procesamiento muy habitual con los sujetos es reordenar las filas de un objeto que contiene nuestros datos. Esto se usa cuando queremos inspeccionar un conjunto de datos para buscar asociaciones entre las diferentes variables, lo que resulta difícil de hacer si no están ordenados. Para realizar la ordenación se utiliza la función arrange(). El uso básico de la función es:

arrange(data_set, varname1, varname2, ...)

donde data_set es el nombre del objeto que contiene nuestros datos y varname1, varname2,... son las variables que vamos a utilizar para la ordenación. Por ejemplo deseamos ordenar nuestro datos siguiendo el orden año, mes y día:

dbf_ord1 <- arrange(flights, year, month, day)
str(dbf_ord1)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  19 variables:
##  $ year          : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day           : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_time      : int  517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int  515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int  830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int  819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr  "UA" "UA" "AA" "B6" ...
##  $ flight        : int  1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr  "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr  "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr  "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num  227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num  1400 1416 1089 1576 762 ...
##  $ hour          : num  5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num  15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct, format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...

Podemos introducir la función desc() para ordenar de forma descendente por la variable seleccionada. Ordenamos nuestros datos (de mayor a menor) por la demora en el tiempo de llegada:

dbf_ord2 <- arrange(flights, desc(arr_delay))
str(dbf_ord2)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  19 variables:
##  $ year          : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int  1 6 1 9 7 4 3 7 12 5 ...
##  $ day           : int  9 15 10 20 22 10 17 22 5 3 ...
##  $ dep_time      : int  641 1432 1121 1139 845 1100 2321 2257 756 1133 ...
##  $ sched_dep_time: int  900 1935 1635 1845 1600 1900 810 759 1700 2055 ...
##  $ dep_delay     : num  1301 1137 1126 1014 1005 ...
##  $ arr_time      : int  1242 1607 1239 1457 1044 1342 135 121 1058 1250 ...
##  $ sched_arr_time: int  1530 2120 1810 2210 1815 2211 1020 1026 2020 2215 ...
##  $ arr_delay     : num  1272 1127 1109 1007 989 ...
##  $ carrier       : chr  "HA" "MQ" "MQ" "AA" ...
##  $ flight        : int  51 3535 3695 177 3075 2391 2119 2047 172 3744 ...
##  $ tailnum       : chr  "N384HA" "N504MQ" "N517MQ" "N338AA" ...
##  $ origin        : chr  "JFK" "JFK" "EWR" "JFK" ...
##  $ dest          : chr  "HNL" "CMH" "ORD" "SFO" ...
##  $ air_time      : num  640 74 111 354 96 139 167 109 149 112 ...
##  $ distance      : num  4983 483 719 2586 589 ...
##  $ hour          : num  9 19 16 18 16 19 8 7 17 20 ...
##  $ minute        : num  0 35 35 45 0 0 10 59 0 55 ...
##  $ time_hour     : POSIXct, format: "2013-01-09 09:00:00" "2013-06-15 19:00:00" ...

En el resumen de los datos presentados se pueden apreciar las diferencia entre los datos ordenados de una u otra forma.

Trabajando con variables

Los procedimientos para el trabajo con las variables de nuestra muestra se reducen a la selección de un subconjunto de variables, la creación de nuevas variables, el renombrado de variables, y la recodificación en nuevas variables.

Selección

Usamos la función select() para seleccionar un subconjunto de variables de nuestro banco de datos. Esto función se usa cuando tenemos un conjunto de datos con muchas variables, pero solo necesitamos trabajar con un subconjunto de ellas. La función tiene la estructura:

select(data_set, varname1, varname2, ...)

El primer argumento, data_set, es el nombre del objeto que contiene nuestros datos. A continuación incluimos una serie de uno o más argumentos adicionales, donde cada uno es el nombre de una o más variables en el conjunto de datos. Estas son las variables que aparecerán en el nuevo banco de datos.

Para el conjunto de datos flights vamos a seleccionar las variables year, month, y day.

dbf_sel1 <- select(flights, year, month, day)
str(dbf_sel1) 
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  3 variables:
##  $ year : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month: int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day  : int  1 1 1 1 1 1 1 1 1 1 ...

A veces es más conveniente establecer la selección especificando aquellas que no necesitamos, en lugar de especificar cuáles guardar. Usamos el operador - para indicar que variables deben ser eliminadas.

dbf_sel2 <- select(flights, -(year:day)) # NO seleccionamos las varaibles que se encuentran entre las variables year y day
str(dbf_sel2)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  16 variables:
##  $ dep_time      : int  517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int  515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int  830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int  819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr  "UA" "UA" "AA" "B6" ...
##  $ flight        : int  1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr  "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr  "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr  "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num  227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num  1400 1416 1089 1576 762 ...
##  $ hour          : num  5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num  15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct, format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...

Cuando las variables que deseamos eliminar no se muestran de forma consecutiva en nuestro banco de datos podemos utilizar una expresión equivalente

dbf_sel3 <- select(flights, -c(year,month,day)) 
str(dbf_sel3)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  16 variables:
##  $ dep_time      : int  517 533 542 544 554 554 555 557 557 558 ...
##  $ sched_dep_time: int  515 529 540 545 600 558 600 600 600 600 ...
##  $ dep_delay     : num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_time      : int  830 850 923 1004 812 740 913 709 838 753 ...
##  $ sched_arr_time: int  819 830 850 1022 837 728 854 723 846 745 ...
##  $ arr_delay     : num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ carrier       : chr  "UA" "UA" "AA" "B6" ...
##  $ flight        : int  1545 1714 1141 725 461 1696 507 5708 79 301 ...
##  $ tailnum       : chr  "N14228" "N24211" "N619AA" "N804JB" ...
##  $ origin        : chr  "EWR" "LGA" "JFK" "JFK" ...
##  $ dest          : chr  "IAH" "IAH" "MIA" "BQN" ...
##  $ air_time      : num  227 227 160 183 116 150 158 53 140 138 ...
##  $ distance      : num  1400 1416 1089 1576 762 ...
##  $ hour          : num  5 5 5 5 6 5 6 6 6 6 ...
##  $ minute        : num  15 29 40 45 0 58 0 0 0 0 ...
##  $ time_hour     : POSIXct, format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...

Creación

En la creación de variables a partir de las originales en nuestros datos tenemos dos opciones: i) crear una nueva variable sin eliminar las variables originales, ii) crear una nueva variable eliminando las variables originales.

Usamos la función mutate() para crear nuevas variables en nuestro banco de datos sin eliminar las variables que forman parte de la nueva variable. La función tiene la estructura:

mutate(data_set, <expression1>, <expression2>, ...)

El primer argumento, data_set, es el nombre del objeto que contiene nuestros datos. A continuación incluimos una serie de uno o más argumentos adicionales, donde cada uno es la expresión para la nueva o nuevas variables.

Veamos un ejemplo de uso de la función

dbf_sel4 <- select(flights, c(year,month,day,dep_delay,arr_delay,distance,air_time)) # Seleccionamos un subconjunto de las variables originales
str(dbf_sel4)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  7 variables:
##  $ year     : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month    : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day      : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_delay: num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_delay: num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ distance : num  1400 1416 1089 1576 762 ...
##  $ air_time : num  227 227 160 183 116 150 158 53 140 138 ...
# Creamos una varaible que indica la reducción de demora entre salida y llegada
# Calculamos la velocidad del viaje
dbf_new <- mutate(dbf_sel4,
  gain = arr_delay - dep_delay,
  speed = distance / air_time * 60
) 
str(dbf_new)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  9 variables:
##  $ year     : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month    : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day      : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_delay: num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_delay: num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ distance : num  1400 1416 1089 1576 762 ...
##  $ air_time : num  227 227 160 183 116 150 158 53 140 138 ...
##  $ gain     : num  9 16 31 -17 -19 16 24 -11 -5 10 ...
##  $ speed    : num  370 374 408 517 394 ...

Podemos ver que se han añadido las dos variables en el nuevo banco de datos que se ha creado.

Una ventaja de esta función es que resulta posible crear nuevas variables a partir de las nuevas creadas

dbf_new2 <- mutate(dbf_sel4,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
) 
str(dbf_new2)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  10 variables:
##  $ year         : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month        : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day          : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_delay    : num  2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
##  $ arr_delay    : num  11 20 33 -18 -25 12 19 -14 -8 8 ...
##  $ distance     : num  1400 1416 1089 1576 762 ...
##  $ air_time     : num  227 227 160 183 116 150 158 53 140 138 ...
##  $ gain         : num  9 16 31 -17 -19 16 24 -11 -5 10 ...
##  $ hours        : num  3.78 3.78 2.67 3.05 1.93 ...
##  $ gain_per_hour: num  2.38 4.23 11.62 -5.57 -9.83 ...

Usamos la función transmute() para crear un banco de datos donde solo aparecen las nuevas variables creadas. La estructura de la función es idéntica a la de la función mutate().

dbf_new3 <- transmute(dbf_sel4,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
) 
str(dbf_new3)
## Classes 'tbl_df', 'tbl' and 'data.frame':    336776 obs. of  3 variables:
##  $ gain         : num  9 16 31 -17 -19 16 24 -11 -5 10 ...
##  $ hours        : num  3.78 3.78 2.67 3.05 1.93 ...
##  $ gain_per_hour: num  2.38 4.23 11.62 -5.57 -9.83 ...

El listado de funciones que podemos usar con las funciones mutate() y transmute() son:

  • Operadores aritméticos: +, -, *, /, ^
  • Funciones logaritmo: log(), log2(), log10()
  • Funciones de agregación: cumsum() (suma acumulada), cumprod() (producto acumulado), cummin() (mínimo acumulado), cummax() (máximo acumulado), cummean() (media acumulada).
  • Comparaciones lógicas: <, <=, >, >=, !=

Creación de factores

La creación de variables tipo factor es un aspecto muy importante en el análisis de datos. Existen tres formas principales de conseguir variables de tipo factor:

  1. A partir de variables tipo carácter
  2. A partir de variables de tipo entero que pueden identificar niveles de una variable
  3. A partir de una variable de tipo numérico.

Por el momento solo mostraremos las opciones 1 y 2. La función utilizada para estas operaciones es fct_recode() cuya estructura viene dada por:

fct_recode(varfactor, levelnew1=levelold1, levelnew2=levelold2, ...)

donde varfactor es la variable factor original, levelnew son los niveles del factor recodificados y levelold son los niveles del factor en la variable original.

Vamos a ver un ejemplo de su uso sobre el banco de datos NCBIRTH800 que presentamos en la unidad anterior. Cargamos los datos desde el repositorio y vemos su estructura:

NCBIRTH800=read_csv("https://goo.gl/mB9Jcn", col_types = "dcddcccdccddcc")

En esta base de datos hay varias variables que se han recogido como carácter (aunque se les ha asignado un código numérico). A continuación se presentan dichas variables así como la asignación de valor a cada uno de los códigos numéricos:

sex: "male" = 1,"female" = 2
marital: "married" = 1,"not married" = 2
racemom: "other non white" = 0, "White" = 1,"Black" = 2,"America indian" = 3,"Chinese" = 4,"Hawaiian" = 5,"Filipino" = 6,"Other asian" = 7, "Other" = 8
hispmom: "Cuban" = C, "Mexican" = M, "Non-Hispanic" = N ,"Other" = O,"Puerto Rican" = P, "Central/South american" = S,"U" = Not classificable
smoke: "Yes"=1, "No" = 0
drink: "Yes" = 1 ,"No" = 0
low: "Yes" = 1, "No" = 0
premie: "Yes"= 1, "No" = 0

Realizamos la asignación de los valores

NCBIRTHnew <- mutate(NCBIRTH800,      
                sex = fct_recode(sex,"male" = "1","female" = "2"),
                marital = fct_recode(marital,"married" = "1","not married" = "2"),
                racemom = fct_recode(racemom,"other non white" = "0","White" = "1","Black" = "2","America  indian" = "3","Chinese" = "4","Hawaiian" = "5","Filipino" = "6","Other asian" = "7","Other" = "8"),
                hispmom = fct_recode(hispmom,"Cuban" = "C","Mexican" = "M","Non-Hispanic" = "N","Other" = "O","Puerto Rican" = "P","Central/South american" = "S","U" = "Not classificable"),
                smoke = fct_recode(smoke,"Yes" = "1","No" = "0"),
                drink = fct_recode(drink,"Yes" = "1","No" = "0"),
                low = fct_recode(low,"Yes" = "1","No" = "0"),
                premie = fct_recode(premie,"Yes" = "1","No" = "0"))
NCBIRTHnew

En el resultado se aprecia la modificación de los diferentes factores.

Reuniendo los datos

Un problema bastante común que parece en la recogida de datos experimentales es que los nombres de las columnas de la base de datos no es una variable en si, sino los valores de una variable. Si tomamos como ejemplo el banco de datos PCKDATA.

PCKDATA = read_csv("https://goo.gl/W8Bfgv", col_types = "idd")
PCKDATA

Como se puede ver aparecen dos columnas indicando el tratamiento del sujeto, es decir, cada fila no identifica a un único sujeto. Por ese motivo en cada una de ellas aparece el valor del nivel de creatinina. Para poder trabajar de forma óptima cada fila debe contener la información única de cada sujeto. En este caso cada fila contiene la información de dos sujetos: el identificado como 1 en el tratamiento A y el identificado como 1 en el tratamiento B.

La función gather()nos permite reorganizar los datos de un banco de datos de forma muy sencilla. La estructura básica de la función es:

gather(data_set,var, key = "key", value = "value", ...)

donde data_set es el banco de datos, var es el conjunto de variables que reorganizamos, key es el nombre de la variable donde reorganizamos las variables anteriores, y value es el nombre de la variable donde almacenamos los valores de respuesta. Para el conjunto de datos anterior tenemos:

gather(PCKDATA,`A`,`B`, key = "Grupo", value = creatine)

Podemos ver que se han reorganizado las filas de la base de datos. De hecho se han duplicado el número de filas (hemos ampliado dos variables) y ahora cada columna identifica claramente la información de un sujeto.


Bibliografía


Wickham, Hadley, and Garrett Grolemund. 2016. R for Data Science. O’Reilly.


Copyright © 2018 Javier Morales. Universidad Miguel Hernández de Elche.