Antes de importar datos

Hay algunos hábitos para la entrada de datos que facilitarán la importación de datos correctamente en R:

  • Reserve la primera fila para el encabezado

  • Reserve la primera columna a la unidad de muestreo

  • Utilice "_“,”." o “-” en lugar de espacios vacíos (por ejemplo, “Cornell_University”)

  • Use nombres cortos

  • Evite usar símbolos poco comunes como?, $,%, ^, &, *, (,), -, #,? ,,, <,>, /, |, , [,], {, y}

  • Sea coherente cuando se refiera a las mismas cosas (es decir, escríbalas siempre de la misma manera)

  • Eliminar cualquier comentario adicional fuera de las columnas del conjunto de datos

  • Indicar valores faltantes con NA (o al menos espacios vacíos)

  • Ni siquiera piense en codificar por colores tus datos en Excel

 

El estilo importa

Basado en la Guía de estilo R de Google

Nombres de archivo

Los nombres de archivo deben terminar en ‘.R’ y, por supuesto, tener sentido:

  • BIEN: predic_ad_revenue.R
  • MAL: foo.R

Nombres de objetos

Variables y funciones:

  • minúsculas
  • Utilice un guión bajo (_) (estilo Hadley Wickham)
  • Generalmente, sustantivos para variables y verbos para funciones
  • Esfuércese por nombres concisos y descriptivos (no siempre fáciles)
  • Evite usar nombres de funciones o variables existentes
  - BIEN: dia_uno: dia_1, dia.promedio(),
  
  - MAL: diaUno, dia1, primer_dia.delmes, mean <- function(x) sum(x), c <- 10

 

Sintaxis

Espaciado:

  • Use espacios alrededor de operadores y para argumentos dentro de una función
  • Siempre ponga un espacio después de una coma, y nunca antes (como en el español normal)
  • Coloque un espacio antes del paréntesis izquierdo, excepto cuando llama una función
  - BIEN: 
          a <- rnorm(n = 10, sd = 10, mean = 1)
          tab.prior <- table(df[df$days.from.opt < 0, "campaign.id"])
          total <- sum(x[, 1])
          total <- sum(x[1, ])
          if (debug)
          mean(1:10)
          
  - MAL: 
         a<-rnorm(n=10,sd=10,mean=1)
         tab.prior <- table(df[df$days.from.opt<0, "campaign.id"])  # necesita espacio al lado de  '<'
         tab.prior <- table(df[df$days.from.opt < 0,"campaign.id"])  # necesita espacio despues de la coma
         tab.prior<- table(df[df$days.from.opt < 0, "campaign.id"])  # necesita espacio antes de <-
         tab.prior<-table(df[df$days.from.opt < 0, "campaign.id"])  # necesita espacio a los lados de <-
         total <- sum(x[,1])  # necesita espacio despues de la coma
         total <- sum(x[ ,1])  # necesita espacio despues de la coma, no antes
         if(debug) # necesita espacio antes del parentesis
         mean (1:10) # ) # espacio extra antes del parentesis

 

Llaves:

  • Una llave de apertura nunca debe ir en su propia línea
  • El cierre de llaves debe ir siempre en su propia línea
  • Puede omitir llaves cuando un bloque consta de una sola declaración
  - BIEN:
              if (is.null(ylim)) {
              ylim <- c(0, 0.06)
            }
                      
            if (is.null(ylim))
              ylim <- c(0, 0.06)
          
  - MAL:
            
         if (is.null(ylim)) ylim <- c(0, 0.06)
                    
         if (is.null(ylim)) {ylim <- c(0, 0.06)} 

         if (is.null(ylim)) {
           ylim <- c(0, 0.06)
           } 

 

Crear objetos:

  • Use <-, not =
  - BIEN:
         x <- 5 
          
  - MAL:
         x = 5

 

Comentar el código:

  • Comenta tu código
  • Las líneas comentadas completas deben comenzar con # y un espacio
  • Se pueden colocar comentarios cortos después del código precedido por dos espacios, # y luego un espacio
# Crear un hisograma con la columna de gastos 
hist(df$pct.spent,
     breaks = "scott",  # metodo para escoger numero de columnas
     main   = "Histograma: fraccion del presupuesto",
     xlab   = "Fraccion gastada",
     ylab   = "Frecuencia")

 

Importando datos

Importar datos a R es un paso crucial y aparentemente simple. Sin embargo, dada la diversidad de formatos de datos y sistemas operativos, así como las muchas posibles fuentes de error, ingresar datos en R no siempre es tan sencillo. La mayoría de los problemas están relacionados con:

  • Indicar a R en qué directorio se encuentra el archivo

  • Indicar a R cómo se codifican los datos (por ejemplo, separados por comas, ancho fijo, etc.)

  • Manejo de celdas vacías y caracteres poco comunes

 

Configuración del directorio de trabajo

Para leer datos en R, debe especificar el directorio de trabajo. Se puede configurar con la función setwd (). La forma de hacerlo depende del sistema operativo (Windows, Mac, Linux). La sintaxis del directorio de carpetas sigue la estructura anidada de las carpetas. Por ejemplo:

setwd("/inicio/m/Escritorio/")

… establece el directorio de trabajo en la carpeta “Escritorio”, que se encuentra dentro de “m”, que se encuentra dentro de “inicio”.

 

Algunos consejos básicos para configurar el directorio de trabajo:

  • Asegúrese de que se cita la ubicación

  • Asegúrese de tener una barra diagonal (/) entre los nombres de las carpetas (aunque las barras diagonales dobles parecen funcionar en Windows)

  • No incluya ningún nombre de archivo en el nombre del directorio de la carpeta

  • Para encontrar la ubicación, puede mirar las propiedades de un archivo en esa carpeta y copiarlo

  • La ruta a la carpeta debe citarse ("")

  • El nombre coincide exactamente (mejor copiar / pegar)

  • Use list.files () para verificar qué archivos están en el directorio de trabajo

 

R puede sugerir y completar automáticamente los nombres de las carpetas presionando" tab "cuando está entre comillas:

 

Color spectro

 

Configuración del directorio de trabajo en Windows

En Windows debería ser algo como esto:

setwd("C:/carpeta")

También puede hacer esto (¡solo en Windows!):

setwd(choose.dir())

  Eso debería abrir una ventana donde puedes elegir la ubicación. Sin embargo, esto solo debe usarse para descubrir la forma correcta de escribir la ubicación del directorio, no como parte del código en sí.

 

Configuración del directorio de trabajo en OSX (mac)

Para mac, la configuración del directorio de trabajo debería ser algo como esto:

setwd("/Usuarios/nombre/..")

no incluya lo que tenga antes de “usuarios” (como macintosh …)

 

Configuración del directorio de trabajo en Linux

Similar al código utilizado en OSX:

setwd("/inicio/m/Escritorio/")

 

El símbolo “~” (virgulilla) también se puede utilizar para omitir la carpeta “inicio” y “usuario” en Linux:

setwd("~/Escritorio/")

 

El directorio de trabajo actual se puede verificar de la siguiente manera:

getwd()
## [1] "/home/m/Dropbox/Cursos/R_avanzado_2019/Clases_M_Araya/Importar y dar formato  a bases de datos"

 

Lectura de datos

Cualquier archivo se puede leer en R. Solo se trata de informar a R en qué formato está codificado el archivo (por ejemplo, qué convenciones se siguieron al generar el archivo). Los formatos más comunes para almacenar / intercambiar conjuntos de datos como los que usualmente manejamos en ciencias biológicas son txt, csv y xls/xlsx.

 

La función más utilizada para importar datos en R esread.table. La documentación de esta función en realidad incluye todas las funciones predeterminadas para ingresar datos:

?read.table

 

read table

 

Lectura de archivos .txt

Los archivos txt se pueden leer usando read.table. Primero descarguemos un conjunto de datos disponible gratuitamente en formato txt:

# definir directorio de trabajo
setwd("PONER EL NOMBRE DEL DIRECTORIO DONDE QUIERE GUARDAR LOS ARCHIVOS AQUI")

# bajar archivo
download.file("http://esapubs.org/archive/ecol/E090/184/PanTHERIA_1-0_WR93_Aug2008.txt", destfile = "pantheria_mammals_data.txt")

También puede descargar manualmente el archivo desde aquí.

 

El archivo se puede ingresar en R de la siguiente manera:

# leer archivo
pntr_dt <- read.table("pantheria_mammals_data.txt", stringsAsFactors = FALSE, sep = "\t", header = TRUE)

# revisar la clase de los datos
sapply(pntr_dt[, 1:10], class)
# revisar estructura
head(pntr_dt)
MSW93_Order MSW93_Family MSW93_Genus MSW93_Species MSW93_Binomial X1.1_ActivityCycle
Rodentia Muridae Abditomys latidens Abditomys latidens -999
Rodentia Muridae Abrawayaomys ruschii Abrawayaomys ruschii -999
Rodentia Abrocomidae Abrocoma bennettii Abrocoma bennettii 1
Rodentia Abrocomidae Abrocoma boliviensis Abrocoma boliviensis -999
Rodentia Abrocomidae Abrocoma cinerea Abrocoma cinerea -999
Chiroptera Pteropodidae Acerodon celebensis Acerodon celebensis -999
X5.1_AdultBodyMass_g X8.1_AdultForearmLen_mm X13.1_AdultHeadBodyLen_mm X2.1_AgeatEyeOpening_d
268 -999.00 223.99 -999
63 -999.00 -999.00 -999
251 -999.00 -999.00 -999
158 -999.00 -999.00 -999
194 -999.00 -999.00 -999
382 133.49 201.55 -999

 

El nombre del archivo se pone en comillas y debe incluir la extensión del archivo.

 

Tenga en cuenta que el valor -999 se utiliza para definir celdas vacías. Podemos leer estos valores como NA mientras importamos los datos usando el argumento ‘na.strings’:

# leer archivo
pntr_dt <- read.table("pantheria_mammals_data.txt", sep = "\t", header = TRUE, na.strings = "-999")

# revisar estructura
head(pntr_dt)
MSW93_Order MSW93_Family MSW93_Genus MSW93_Species MSW93_Binomial X1.1_ActivityCycle
Rodentia Muridae Abditomys latidens Abditomys latidens NA
Rodentia Muridae Abrawayaomys ruschii Abrawayaomys ruschii NA
Rodentia Abrocomidae Abrocoma bennettii Abrocoma bennettii 1
Rodentia Abrocomidae Abrocoma boliviensis Abrocoma boliviensis NA
Rodentia Abrocomidae Abrocoma cinerea Abrocoma cinerea NA
Chiroptera Pteropodidae Acerodon celebensis Acerodon celebensis NA
X5.1_AdultBodyMass_g X8.1_AdultForearmLen_mm X13.1_AdultHeadBodyLen_mm X2.1_AgeatEyeOpening_d
268 NA 223.99 NA
63 NA NA NA
251 NA NA NA
158 NA NA NA
194 NA NA NA
382 133.49 201.55 NA

 

Lectura de archivos .csv

Nuevamente, podemos descargar un archivo de ejemplo en línea:

# bajar archivo 
download.file("http://www.birds.cornell.edu/clementschecklist/wp-content/uploads/2019/08/eBird_Taxonomy_v2019.csv", destfile = "clements_bird_list.csv")

# leer archivo
clm_lst <- read.csv("clements_bird_list.csv", stringsAsFactors = FALSE)

head(clm_lst)
TAXON_ORDER CATEGORY SPECIES_CODE PRIMARY_COM_NAME SCI_NAME
3 species ostric2 Common Ostrich Struthio camelus
5 species ostric3 Somali Ostrich Struthio molybdophanes
6 slash y00934 Common/Somali Ostrich Struthio camelus/molybdophanes
7 species grerhe1 Greater Rhea Rhea americana
13 species lesrhe2 Lesser Rhea Rhea pennata
14 issf lesrhe4 Lesser Rhea (Puna) Rhea pennata tarapacensis/garleppi
ORDER1 FAMILY SPECIES_GROUP REPORT_AS
Struthioniformes Struthionidae (Ostriches) Ostriches
Struthioniformes Struthionidae (Ostriches)
Struthioniformes Struthionidae (Ostriches)
Rheiformes Rheidae (Rheas) Rheas
Rheiformes Rheidae (Rheas)
Rheiformes Rheidae (Rheas) lesrhe2

También puede descargar manualmente el archivo desde aquí

 

Como en el ejemplo anterior, podemos decirle a R cómo identificar celdas vacías usando el argumento ‘na.strings’:

# bajar archivo
download.file("http://www.birds.cornell.edu/clementschecklist/wp-content/uploads/2019/08/eBird_Taxonomy_v2019.csv", destfile = "clements_bird_list.csv")

# leer archivo
clm_lst <- read.csv("clements_bird_list.csv", stringsAsFactors = FALSE)

# ver datos
head(clm_lst)
TAXON_ORDER CATEGORY SPECIES_CODE PRIMARY_COM_NAME SCI_NAME
3 species ostric2 Common Ostrich Struthio camelus
5 species ostric3 Somali Ostrich Struthio molybdophanes
6 slash y00934 Common/Somali Ostrich Struthio camelus/molybdophanes
7 species grerhe1 Greater Rhea Rhea americana
13 species lesrhe2 Lesser Rhea Rhea pennata
14 issf lesrhe4 Lesser Rhea (Puna) Rhea pennata tarapacensis/garleppi
ORDER1 FAMILY SPECIES_GROUP REPORT_AS
Struthioniformes Struthionidae (Ostriches) Ostriches NA
Struthioniformes Struthionidae (Ostriches) NA NA
Struthioniformes Struthionidae (Ostriches) NA NA
Rheiformes Rheidae (Rheas) Rheas NA
Rheiformes Rheidae (Rheas) NA NA
Rheiformes Rheidae (Rheas) NA lesrhe2

 

Lectura de archivos de Excel

La mayoría de los investigadores ingresan datos en hojas de cálculo de Excel. Por lo tanto, sería bastante útil leer los datos directamente desde allí. Para leer los archivos xls y xlsx necesitamos instalar el paquete “readxl” (hay otros paquetes que se pueden usar pero todos funcionan de manera similar):

install.packages(pkgs = "readxl")

 

… y cargarglo:

library(readxl)

 

Como hicimos anteriormente, descargue un archivo de ejemplo de un repositorio en línea. En este caso, es la misma lista de taxonomía de aves Clements en formato xlsx:

download.file("http://www.birds.cornell.edu/clementschecklist/wp-content/uploads/2017/08/eBird_Taxonomy_v2017_18Aug2017.xlsx", destfile = "clements_bird_list.xlsx")

También puede descargar manualmente el archivo desde aquí.

 

Ahora podemos usar la función read_excel() para leer el archivo:

# leer archivo
clm_lst2 <- read_excel("clements_bird_list.xlsx", sheet = 1)

# ver datos
head(clm_lst2)
TAXON_ORDER CATEGORY SPECIES_CODE PRIMARY_COM_NAME SCI_NAME
3 species ostric2 Common Ostrich Struthio camelus
5 species ostric3 Somali Ostrich Struthio molybdophanes
6 slash y00934 Common/Somali Ostrich Struthio camelus/molybdophanes
7 species grerhe1 Greater Rhea Rhea americana
13 species lesrhe2 Lesser Rhea Rhea pennata
14 issf lesrhe4 Lesser Rhea (Puna) Rhea pennata tarapacensis/garleppi
ORDER1 FAMILY SPECIES_GROUP REPORT_AS
Struthioniformes Struthionidae (Ostriches) Ostriches NA
Struthioniformes Struthionidae (Ostriches) NA NA
Struthioniformes Struthionidae (Ostriches) NA NA
Rheiformes Rheidae (Rheas) Rheas NA
Rheiformes Rheidae (Rheas) NA NA
Rheiformes Rheidae (Rheas) NA lesrhe2

 

Debe especificar el nombre del archivo (incluida la extensión) y el nombre de la hoja de Excel (pestaña). read_excel() auto detecta el formato de la extensión del archivo. Las funciones read_xls() y read_xlsx() se pueden usar para leer archivos sin extensión.

 

Ejercicio 1

Todas las funciones predeterminadas para ingresar datos en R tienen una contraparte para exportar el mismo tipo de datos. Los nombres de estas otras funciones son similares a los de lectura de datos, aunque generalmente comienzan con “write” o “save”.


1.1 ¿Cuáles son los nombres de las funciones predeterminadas para exportar los formatos de datos que utilizamos anteriormente? (sugerencia: intente apropos() para verificar qué funciones están disponibles)


1.2 Exporte los datos de mamíferos como un archivo .csv


1.3 Exporte los datos de mamíferos nuevamente, esta vez excluyendo los nombres de las filas


1.4 Lea el archivo .csv usando read.table


1.5 ¿Qué otros paquetes pueden importar archivos de Excel en R?


1.6 ¿Puede exportar un archivo de Excel o agregar datos a un archivo de Excel existente desde R?


1.7 Usando el archivo “clements_bird_list.csv”, ¿cómo le dirías a R que lea “Rheiformes”y “Avestruces” (Ostriches) como celdas vacías (mientras sigue leyendo celdas vacías como celdas vacías)?


Datos de formato

Esta sección trate acerca de organizar sus datos de una manera que simplifique su manejo, exploración y análisis. Como probablemente pueda adivinar, cuanto más consistentes se hagan las cosas, más predecibles se volverán. Esto también se aplica a los datos. Si los datos se organizan con la misma lógica, puede esperar que se aplique el mismo tipo de manipulaciones y análisis en diferentes conjuntos de datos. Organizar los datos es un aspecto clave (pero generalmente descuidado) del flujo de trabajo de análisis de datos. Cuando los datos se organizan correctamente, pasará mucho menos tiempo formateando y más tiempo en las preguntas analíticas reales.

Cuando sea posible, ejecutaremos los ejemplos de formato de datos utilizando tanto el paquete ‘tidyr’ como las funciones base R.

Datos ordenados (‘tidy’)

“Tidy data” es una lógica para organizar conjuntos de datos de manera coherente e intuitiva. Para ejecutar parte del código a continuación, necesitará los paquetes ‘tidyr’ y ‘dplyr’, que pueden instalarse/cargarse de la siguiente manera:

# instalar paquetes
install.packages(pkgs = c("tidyr", "dplyr"))

# cargar paquetes
library(tidyr)
library(dplyr)

 

Los mismos datos se pueden representar de muchas maneras. En el siguiente ejemplo, cada conjunto de datos muestra exactamente los mismos valores de cuatro variables country, year, population y cases, pero en cada conjunto de datos los valores se organizan de manera diferente. Los datos muestran el número de casos de tuberculosis en Afganistán, Brasil y China entre 1999 y 2000:

# ver datos
as.data.frame(table1)
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583
# ver datos
as.data.frame(table2)
country year type count
Afghanistan 1999 cases 745
Afghanistan 1999 population 19987071
Afghanistan 2000 cases 2666
Afghanistan 2000 population 20595360
Brazil 1999 cases 37737
Brazil 1999 population 172006362
Brazil 2000 cases 80488
Brazil 2000 population 174504898
China 1999 cases 212258
China 1999 population 1272915272
China 2000 cases 213766
China 2000 population 1280428583
# ver datos
as.data.frame(table3)
country year rate
Afghanistan 1999 745/19987071
Afghanistan 2000 2666/20595360
Brazil 1999 37737/172006362
Brazil 2000 80488/174504898
China 1999 212258/1272915272
China 2000 213766/1280428583

O incluso distribuido en 2 conjuntos de datos diferentes:

# ver datos
as.data.frame(table4a)
country 1999 2000
Afghanistan 745 2666
Brazil 37737 80488
China 212258 213766
# ver datos
as.data.frame(table4b)
country 1999 2000
Afghanistan 19987071 20595360
Brazil 172006362 174504898
China 1272915272 1280428583

 

Todos estos conjuntos de datos contenían los mismos datos subyacentes. Sin embargo, no son igualmente fáciles de usar.

Hay tres reglas interrelacionadas para ordenar un conjunto de datos:

  1. Cada variable debe tener su propia columna

  2. Cada observación debe tener su propia fila

  3. Cada valor debe tener su propia celda

Esta figura muestra las reglas visualmente:

datos ordenados *Modificado de R para Data Science  

Estas tres reglas están interrelacionadas porque es imposible satisfacer solo dos de las tres. Esa interrelación conduce a un conjunto aún más simple de instrucciones prácticas:

  1. Coloque cada conjunto de datos en un marco de datos

  2. Ponga cada variable en una columna

 

En el ejemplo anterior, solo table1 es ordenado. Es la única representación donde cada columna es una variable. Hay dos ventajas principales de formatear los datos de esta manera:

  1. Si tiene una estructura de datos coherente, es más fácil aprender las herramientas que funcionan con ella porque tienen una uniformidad subyacente

  2. Colocar variables en columnas se ajusta bien a la naturaleza vectorizada de R. Como hemos visto, las funciones incorporadas R funcionan con vectores de valores. Eso hace que la transformación de datos ordenados se sienta particularmente natural

 

Ejercicio 2


2.1 Describa cómo se organizan las variables y observaciones en cada uno de los marcos de datos de muestra


2.2 Calcule la tasa de casos por 10000 personas para “table1”, “table2” y “table4a” / “table4b”


Juntar datos

Un problema común es un conjunto de datos donde algunos de los nombres de columna no son nombres de variables, sino valores de una variable. Tome “table4a”: los nombres de columna 1999 y 2000 representan valores de la variable del año, y cada fila representa dos observaciones, no una:

# ver datos
as.data.frame(table4a)
country 1999 2000
Afghanistan 745 2666
Brazil 37737 80488
China 212258 213766

 

Para ordenar un conjunto de datos como este, necesitamos juntar esas columnas en un nuevo par de variables. Para hacer esto necesitamos tres parámetros:

  • El conjunto de columnas que representan valores, no variables. En este ejemplo, esas son las columnas ‘1999’ y ’2000`

  • El nombre de la variable cuyos valores forman los nombres de columna. En la sintaxis ‘tidyr’ que se llama la clave (key), que en este caso es year

  • El nombre de la variable cuyos valores se extienden por las celdas. En la sintaxis ‘tidyr’ que se llama ese valor (value), que en este caso es el número de cases

Estos parámetros se pueden usar para crear un conjunto de datos ordenado usando la función gather():

# unir
gather(table4a, key = "year", value = "cases", `1999`, `2000`)
country year cases
Afghanistan 1999 745
Brazil 1999 37737
China 1999 212258
Afghanistan 2000 2666
Brazil 2000 80488
China 2000 213766

Podemos visualizar este formato de la siguiente manera:

recopilar datos * Modificado de R para Data Science  

gather() también se puede usar para ordenar table4b. La única diferencia es la variable almacenada en los valores de la celda:

#unir
gather(data = table4b, key = "year", value = "population", `1999`, `2000`)
country year population
Afghanistan 1999 19987071
Brazil 1999 172006362
China 1999 1272915272
Afghanistan 2000 20595360
Brazil 2000 174504898
China 2000 1280428583

 

Para combinar las versiones ordenadas de table4a ytable4b en un solo marco de datos (o ‘tibble’), podemos usar dplyr::left_join():

# unir
tidy4a <- gather(table4a, key = "year", value = "cases", `1999`, `2000`)

# unir
tidy4b <- gather(table4b, key = "year", value = "population", `1999`, `2000`)

left_join(x = tidy4a, y = tidy4b, by = c("country", "year"))
country year cases population
Afghanistan 1999 745 19987071
Brazil 1999 37737 172006362
China 1999 212258 1272915272
Afghanistan 2000 2666 20595360
Brazil 2000 80488 174504898
China 2000 213766 1280428583

 

Tambien podemos usar la función merge() de R básico, la cual identifica columnas en común de dos bases de datos distintas:

# combinar
merge(x = tidy4a, y =  tidy4b)
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

 

Lo cual es equivalente a:

# combinar
merge(x = tidy4a, y =  tidy4b, by = c("country", "year"))
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

 

Como se muestra, la función merge() encuentra automáticamente las columnas en común entre las dos bases de datos.

La función merge() tiene un número grande de argumentos. Sin embargo, estos se pueden resumir en cuatro grupos:

  • x: base de datos 1

  • y: base de datos 2

  • by, by.x, by.y: nombres de las columnas en común de la base de datos 1 y base de datos 2. Lo usual es usar las columnas de ambas bases de datos que tengan el mismo nombre.

  • all, all.x, all.y: valores lógicos que especifican la forma en que se combinarían ambas bases de datos. Por defecto, all=FALSE, lo que significa que solo las filas que son iguales serán escogidas.

 

merge

 

En el siguiente ejemplo, veremos varias formas en las que podemos unir o combinar dos bases de datos usando merge():

# Crear dos bases de datos
dat1 <- data.frame(ind = c(1:6), sexo = c(rep("macho", 3), rep("hembra", 3)))
dat1
##   ind   sexo
## 1   1  macho
## 2   2  macho
## 3   3  macho
## 4   4 hembra
## 5   5 hembra
## 6   6 hembra
dat2 <- data.frame(ind = c(2, 4, 6), sitio = c(rep("arrecife", 2), rep("estuario", 1)))
dat2
##   ind    sitio
## 1   2 arrecife
## 2   4 arrecife
## 3   6 estuario
# Opción 1: "inner join"
dat.new <- merge(dat1, dat2, by = "ind")
dat.new
##   ind   sexo    sitio
## 1   2  macho arrecife
## 2   4 hembra arrecife
## 3   6 hembra estuario
# Opción 2: "full outer join"
dat.new2 <- merge(dat1, dat2, by = "ind", all = T)
dat.new2
##   ind   sexo    sitio
## 1   1  macho     <NA>
## 2   2  macho arrecife
## 3   3  macho     <NA>
## 4   4 hembra arrecife
## 5   5 hembra     <NA>
## 6   6 hembra estuario
# Opción 3: "left outer join"
dat.new3 <- merge(dat1, dat2, by = "ind", all.x = T)
dat.new3
##   ind   sexo    sitio
## 1   1  macho     <NA>
## 2   2  macho arrecife
## 3   3  macho     <NA>
## 4   4 hembra arrecife
## 5   5 hembra     <NA>
## 6   6 hembra estuario
# Opción 4: "right outer join"
dat.new4 <- merge(dat1, dat2, by = "ind", all.y = T)
dat.new4
##   ind   sexo    sitio
## 1   2  macho arrecife
## 2   4 hembra arrecife
## 3   6 hembra estuario
### ¿Qué pasa si las columnas en común de las dos bases de datos tienen distintos nombres? ###

# Crear dos bases de datos
dat1a <- data.frame(individuo = c(1:6), sexo = c(rep("macho", 3), rep("hembra", 3)))
dat1a
##   individuo   sexo
## 1         1  macho
## 2         2  macho
## 3         3  macho
## 4         4 hembra
## 5         5 hembra
## 6         6 hembra
dat2a <- data.frame(ind = c(2, 4, 6), sitio = c(rep("arrecife", 2), rep("estuario", 1)))
dat2a
##   ind    sitio
## 1   2 arrecife
## 2   4 arrecife
## 3   6 estuario
# Unir ambas bases de datos
dat.merge <- merge(dat1a, dat2a, by = "ind")
## Error in fix.by(by.x, x): 'by' must specify a uniquely valid column
dat.merge <- merge(dat1a, dat2a, by.x = "individuo", by.y = "ind")
dat.merge
##   individuo   sexo    sitio
## 1         2  macho arrecife
## 2         4 hembra arrecife
## 3         6 hembra estuario
dat.merge2 <- merge(dat2a, dat1a, by.x = "ind", by.y = "individuo")
dat.merge2
##   ind    sitio   sexo
## 1   2 arrecife  macho
## 2   4 arrecife hembra
## 3   6 estuario hembra

Extender (spreading)

Extender (spreading) es lo contrario de “juntar”. Lo usa cuando una observación está dispersa en varias filas. Por ejemplo, en table2 una observación es un país en un año, pero cada observación se distribuye en dos filas:

# ver datos
table2
country year type count
Afghanistan 1999 cases 745
Afghanistan 1999 population 19987071
Afghanistan 2000 cases 2666
Afghanistan 2000 population 20595360
Brazil 1999 cases 37737
Brazil 1999 population 172006362
Brazil 2000 cases 80488
Brazil 2000 population 174504898
China 1999 cases 212258
China 1999 population 1272915272
China 2000 cases 213766
China 2000 population 1280428583

 

Para ordenar esta configuración de datos, solo necesitamos dos parámetros:

  • La columna que contiene nombres de variables, la columna key. Aqui estype.

  • La columna que contiene valores forma múltiples variables, la columna value. Aquí es count.

 

Para hacer esto podemos usar spread():

# extender
spread(table2, key = "type", value = "count")
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

  que se puede visualizar de la siguiente manera:

difusión de datos *Modificado de R para Data Science  

spread() y gather() son funciones complementarias. collect() hace que las mesas anchas sean más angostas y largas; spread() hace que las cuadros de datos largos sean más cortos y anchos.

 

Ejercicio 3


3.1 Ordene el siguiente conjunto de datos con la altura de árboles de 2 especies:

# crear datos
tmn_plnt <- data.frame(bosque = c("maduro", "perturbado"), 
                      especies_1 = c(154, 160), 
                      especies_2 = c(120, 113))

 


Separar y unir

Hasta ahora hemos arreglado table2 y table4, pero no table3. table3 tiene un problema diferente: tenemos una columna (tasa) que contiene dos variables (casos y población). Esto se puede solucionar con la función separate(). También veremos su complementounite(), que se usa cuando una sola variable se extiende a través de múltiples columnas.

 

Separar

separate() separa una columna en varias columnas, dividiéndolas donde aparezca un carácter separador. Tome table3:

# ver datos
as.data.frame(table3)
country year rate
Afghanistan 1999 745/19987071
Afghanistan 2000 2666/20595360
Brazil 1999 37737/172006362
Brazil 2000 80488/174504898
China 1999 212258/1272915272
China 2000 213766/1280428583

Visualmente hace algo como esto:

datos separados *Modificado de R para Data Science

 

La columna rate contiene la información para ‘número de casos’ y ‘población’, y necesitamos dividirla en dos variables. separate() toma el nombre de la columna para separar, y los nombres de las nuevas columnas que se crearán:

# separar
separate(data = table3, col =  rate, into = c("cases", "population"))
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

Por defecto, separate() dividirá en función de cualquier carácter no alfanumérico (es decir, un carácter que no sea un número o letra). En el código anterior, separate() divide los valores de velocidad en los caracteres de barra diagonal. Esto se puede establecer explícitamente (para evitar cualquier error):

tb3 <- separate(data = table3, col = rate,  into = c("cases", "population"), sep = "/")

tb3 
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583
## Classes 'tbl_df', 'tbl' and 'data.frame':    6 obs. of  4 variables:
##  $ country   : chr  "Afghanistan" "Afghanistan" "Brazil" "Brazil" ...
##  $ year      : int  1999 2000 1999 2000 1999 2000
##  $ cases     : chr  "745" "2666" "37737" "80488" ...
##  $ population: chr  "19987071" "20595360" "172006362" "174504898" ...

 

Tenga en cuenta que case y population son columnas de caracteres. Por defecto, separate() deja el tipo de las nuevas columnas como en la original. En este caso esto no es útil, ya que realmente son números. Podemos pedirle a separate() que intente convertir a tipos mejores usando convert = TRUE:

tb3 <- separate(data = table3, col = rate, into = c("cases", "population"), convert = TRUE)

str(tb3)
## Classes 'tbl_df', 'tbl' and 'data.frame':    6 obs. of  4 variables:
##  $ country   : chr  "Afghanistan" "Afghanistan" "Brazil" "Brazil" ...
##  $ year      : int  1999 2000 1999 2000 1999 2000
##  $ cases     : int  745 2666 37737 80488 212258 213766
##  $ population: int  19987071 20595360 172006362 174504898 1272915272 1280428583

 

También puede pasar un vector de enteros a sep, que se interpretará como posiciones para dividir. Los valores positivos comienzan en 1 en el extremo izquierdo de las cadenas; el valor negativo comienza en -1 en el extremo derecho de las cadenas. Cuando se usan números enteros para separar cadenas, la longitud de sep debe ser uno menos que el número de nombres eninto. Puede usar esto para separar los dos últimos dígitos de cada año:

separate(data = table3, col = year, into = c("century", "year"), 
         sep = 2)
country century year rate
Afghanistan 19 99 745/19987071
Afghanistan 20 00 2666/20595360
Brazil 19 99 37737/172006362
Brazil 20 00 80488/174504898
China 19 99 212258/1272915272
China 20 00 213766/1280428583

La separación de columnas también se puede hacer con R básico, aunque requiere un poco más de código:

table3$cases <- sapply(table3$rate, function(x) try(strsplit(x, "/")[[1]][1]), USE.NAMES = FALSE)

table3$population <- sapply(table3$rate, function(x) try(strsplit(x, "/")[[1]][2]), USE.NAMES = FALSE)

tb3 
country year rate cases population
Afghanistan 1999 745/19987071 745 19987071
Afghanistan 2000 2666/20595360 2666 20595360
Brazil 1999 37737/172006362 37737 172006362
Brazil 2000 80488/174504898 80488 174504898
China 1999 212258/1272915272 212258 1272915272
China 2000 213766/1280428583 213766 1280428583
## Classes 'tbl_df', 'tbl' and 'data.frame':    6 obs. of  4 variables:
##  $ country   : chr  "Afghanistan" "Afghanistan" "Brazil" "Brazil" ...
##  $ year      : int  1999 2000 1999 2000 1999 2000
##  $ cases     : chr  "745" "2666" "37737" "80488" ...
##  $ population: chr  "19987071" "20595360" "172006362" "174504898" ...

 

Unir

unite() es el inverso de separate(): combina varias columnas en una sola columna:

unir datos * Modificado de R para Data Science

 

Sin embargo, lo necesitará con mucha menos frecuencia que separate().

Podemos usar unite() para volver a unir las columnas * century * y * year * que creamos anteriormente:

# unir
unite(data = table5, col = "new", "century", "year")
country new rate
Afghanistan 19_99 745/19987071
Afghanistan 20_00 2666/20595360
Brazil 19_99 37737/172006362
Brazil 20_00 80488/174504898
China 19_99 212258/1272915272
China 20_00 213766/1280428583

En esta función también podemos usar el argumento sep (aunque en este ejemplo no se especificó).

 

Ejercicio 4


4.1 Unir century y year en “table5” usando R básico (sugerencia:paste())


Encontrar/modificar patrones de caracteres

A veces necesitamos seleccionar un subconjunto de datos usando caracteres con un patrón particular. R básico provee de funciones parar buscar y manipular caracteres que pueden ser muy útil en el manejo de datos.

Función grep

La función grep() realiza una busqueda de un patrón de caracteres sobre un vector y regresa un índice de todos los valores en donde se encontró el patrón. Por ejemplo el siguiente código busca los meses que contienen el patrón “Ju”:

# vector con nombre de meses
month.name
##  [1] "January"   "February"  "March"     "April"     "May"      
##  [6] "June"      "July"      "August"    "September" "October"  
## [11] "November"  "December"
# busqueda de "Ju"
grep(pattern = "Ju", month.name)
## [1] 6 7

Podemos usar esos indices para extraer un el subconjunto del vector con los meses que coinciden con la búsqueda:

# busqueda de "Ju"
month.name[grep(pattern = "Ju", month.name)]
## [1] "June" "July"

Tambien podemos buscar por varios patrones al mismo tiempo separando los patrones con “|”:

# busqueda de "Ju"
month.name[grep(pattern = "Ju|Au", month.name)]
## [1] "June"   "July"   "August"

Función gsub

La función gsub() funciona de manera similar a grep(), sin embargo esta reemplaza todas las instancias donde el patrón fue identificado:

# remplazar macho por M
dat1$sexo <- gsub(pattern = "macho", replacement = "M", dat1$sexo)

dat1$sexo
## [1] "M"      "M"      "M"      "hembra" "hembra" "hembra"

 

Ejercicio 5


5.1 ¿Para que sirve los argumentos “value” y “ignore.case” de grep()?


5.2 Remplace “hembras” por “H” como en el ejemplo de la función gsub() pero esta vez utilizando la función grep()


5.3 ¿Cómo difiere la función grepl() de la función grep()?


 

Caso de estudio


A continuación vamos a usar datos reales donde trataremos de unir dos bases de datos usando una columna en común. Estos datos fueron colectados usando cámaras de video con cebo o cámaras pescadoras (“BRUVS”, por sus siglas en inglés) para monitorear la diversidad de tiburones en la Gran Barrera de Australia.

 

Estructura de una cámara pescadora o "BRUVS (a). Imágenes del tiburón gris de arrecife (Carcharhinus amblyrhynchos) (b), tiburón plateado (C. albimarginatus) (c), y tiburón tigre (Galeocerdo cuvier) (d). Cortesía de Mario Espinoza.

Estructura de una cámara pescadora o "BRUVS (a). Imágenes del tiburón gris de arrecife (Carcharhinus amblyrhynchos) (b), tiburón plateado (C. albimarginatus) (c), y tiburón tigre (Galeocerdo cuvier) (d). Cortesía de Mario Espinoza.

 

Mapa de la Gran Barrera de Australia mostrando la ubicación de las cámaras pescadoras o “BRUVS” y la distribución de las especies de tiburones más comunes observadas en cámaras “BRUVS”. Cortesía de Mario Espinoza.

Mapa de la Gran Barrera de Australia mostrando la ubicación de las cámaras pescadoras o “BRUVS” y la distribución de las especies de tiburones más comunes observadas en cámaras “BRUVS”. Cortesía de Mario Espinoza.

 

Vamos a importar dos bases de datos, la primera contiene información de cada uno de los sitios en donde se pusieron las cámaras “BRUVS” (localidad, fecha, duración, etc,.). La segunda base de datos contiene información de las especies que fueron observadas en las cámaras. Ambas bases de datos tienen una columna en común (“BRUVSID”) que usaremos para realizar la unión, y análisis posteriores.

# Importar base de datos de sitios
sitios <- read.csv("bruvs.sitios.csv", header = T, sep = ",")

head(sitios)
##   BRUVSID  OPCODE CAMERA      SITE        LOCATION DEPTH     LAT    LON
## 1    3046      92      3      S_92 #10 Ribbon reef  38.2 -14.694 145.65
## 2    3047      92      2      S_92 #10 Ribbon reef  37.4 -14.693 145.64
## 3    3048      92      1      S_92 #10 Ribbon reef  39.2 -14.690 145.64
## 4    7054 ARP3G15      1 S_ARP3G15         _20348S  37.5 -20.874 150.94
## 5    7055 ARP3G15      2 S_ARP3G15         _20348S  34.0 -20.875 150.94
## 6    7056 ARP3G15      3 S_ARP3G15         _20348S  39.2 -20.876 150.94
##    DATETIME YEAR MONTH DAY SoaktimeTotal_mins   TAPEREADER
## 1 10/5/2003 2003    10   5             62.083 Peter Speare
## 2 10/5/2003 2003    10   5             62.467 Peter Speare
## 3 10/5/2003 2003    10   5             62.417 Peter Speare
## 4 1/20/2009 2009     1  20             62.533   Mike Cappo
## 5 1/20/2009 2009     1  20             62.467   Mike Cappo
## 6 1/20/2009 2009     1  20             62.450   Mike Cappo
str(sitios)
## 'data.frame':    499 obs. of  14 variables:
##  $ BRUVSID           : int  3046 3047 3048 7054 7055 7056 7057 7059 7060 7061 ...
##  $ OPCODE            : Factor w/ 43 levels "2647","815","92",..: 3 3 3 22 22 22 22 22 22 22 ...
##  $ CAMERA            : int  3 2 1 1 2 3 4 6 7 8 ...
##  $ SITE              : Factor w/ 38 levels "S_2647","S_815",..: 3 3 3 22 22 22 22 22 22 22 ...
##  $ LOCATION          : Factor w/ 36 levels "_20348S","_20353S",..: 33 33 33 1 1 1 1 1 1 1 ...
##  $ DEPTH             : num  38.2 37.4 39.2 37.5 34 39.2 29.6 43 37.7 37.7 ...
##  $ LAT               : num  -14.7 -14.7 -14.7 -20.9 -20.9 ...
##  $ LON               : num  146 146 146 151 151 ...
##  $ DATETIME          : Factor w/ 26 levels "1/11/2009","1/16/2009",..: 13 13 13 6 6 6 6 6 6 6 ...
##  $ YEAR              : int  2003 2003 2003 2009 2009 2009 2009 2009 2009 2009 ...
##  $ MONTH             : int  10 10 10 1 1 1 1 1 1 1 ...
##  $ DAY               : int  5 5 5 20 20 20 20 20 20 20 ...
##  $ SoaktimeTotal_mins: num  62.1 62.5 62.4 62.5 62.5 ...
##  $ TAPEREADER        : Factor w/ 4 levels "Charlotte Johansson",..: 4 4 4 3 3 3 3 3 3 3 ...
dim(sitios)
## [1] 499  14
length(unique(sitios$BRUVSID))
## [1] 499
# Importar base de datos de especies
especies <- read.csv("bruvs.spp.csv", header = T, sep = ",")

head(especies)
##   BRUVSID FISHID  GROUP         FAMILY        GENUS        SPECIES
## 1    3649   7770   Rays   Rhinobatidae Aptychotrema       rostrata
## 2    7470  18516   Rays   Rhinobatidae Aptychotrema       rostrata
## 3    2097   3233 Sharks Carcharhinidae Carcharhinus albimarginatus
## 4    2117   3377 Sharks Carcharhinidae Carcharhinus albimarginatus
## 5    2123    736 Sharks Carcharhinidae Carcharhinus albimarginatus
## 6    2132   8231 Sharks Carcharhinidae Carcharhinus albimarginatus
##                          COMMON                         SPP STAGE
## 1 Eastern shovelnose guitarfish       Aptychotrema rostrata    AD
## 2 Eastern shovelnose guitarfish       Aptychotrema rostrata    AD
## 3               Silvertip shark Carcharhinus albimarginatus    AD
## 4               Silvertip shark Carcharhinus albimarginatus    AD
## 5               Silvertip shark Carcharhinus albimarginatus    AD
## 6               Silvertip shark Carcharhinus albimarginatus    AD
##                    ENVIRON Depthrange    TAPEREADER TimeMaxNmins MaxN
## 1 Marine-brackish-demersal   1 to 60m    Mike Cappo       10.633    1
## 2 Marine-brackish-demersal   1 to 60m    Mike Cappo       19.067    1
## 3          Reef-associated  1 to 800m  Peter Speare       37.450    1
## 4          Reef-associated  1 to 800m  Peter Speare       40.283    1
## 5          Reef-associated  1 to 800m Helen Sturmey       33.350    1
## 6          Reef-associated  1 to 800m    Mike Cappo       43.683    1
str(especies)
## 'data.frame':    971 obs. of  14 variables:
##  $ BRUVSID     : int  3649 7470 2097 2117 2123 2132 2135 2165 2668 2669 ...
##  $ FISHID      : int  7770 18516 3233 3377 736 8231 8997 3209 7587 7571 ...
##  $ GROUP       : Factor w/ 2 levels "Rays","Sharks": 1 1 2 2 2 2 2 2 2 2 ...
##  $ FAMILY      : Factor w/ 9 levels "Carcharhinidae",..: 7 7 1 1 1 1 1 1 1 1 ...
##  $ GENUS       : Factor w/ 23 levels "Aptychotrema",..: 1 1 2 2 2 2 2 2 2 2 ...
##  $ SPECIES     : Factor w/ 35 levels "acutidens","albimarginatus",..: 27 27 2 2 2 2 2 2 2 2 ...
##  $ COMMON      : Factor w/ 38 levels "Australian blacktip shark",..: 10 10 27 27 27 27 27 27 27 27 ...
##  $ SPP         : Factor w/ 38 levels "Aptychotrema rostrata",..: 1 1 2 2 2 2 2 2 2 2 ...
##  $ STAGE       : Factor w/ 3 levels "","AD","JUV": 2 2 2 2 2 2 3 2 2 2 ...
##  $ ENVIRON     : Factor w/ 13 levels "Marine-brackish-benthopelagic",..: 2 2 13 13 13 13 13 13 13 13 ...
##  $ Depthrange  : Factor w/ 29 levels "1 to 1000m","1 to 100m",..: 17 17 19 19 19 19 19 19 19 19 ...
##  $ TAPEREADER  : Factor w/ 5 levels "Charlotte Johansson",..: 4 4 5 5 2 4 4 5 4 4 ...
##  $ TimeMaxNmins: num  10.6 19.1 37.5 40.3 33.4 ...
##  $ MaxN        : int  1 1 1 1 1 1 1 1 1 1 ...
dim(especies)
## [1] 971  14
length(unique(especies$BRUVSID))
## [1] 785
# Unir ambas bases de datos por columna en común ("BRUVSID")
db.final <- merge(sitios, especies, by = "BRUVSID", all.x=T)
head(db.final)
##   BRUVSID OPCODE CAMERA   SITE  LOCATION DEPTH     LAT    LON  DATETIME
## 1    2400   2647      5 S_2647 Acheron I  21.8 -18.915 146.62 4/26/2004
## 2    2401   2647      3 S_2647 Acheron I  21.9 -18.914 146.62 4/26/2004
## 3    2402   2647      2 S_2647 Acheron I  21.9 -18.913 146.61 4/26/2004
## 4    2809    815      4  S_815  Arc Reef  48.3 -18.491 147.40 9/19/2003
## 5    2810    815      3  S_815  Arc Reef  29.5 -18.489 147.40 9/19/2003
## 6    2811    815      2  S_815  Arc Reef  42.9 -18.486 147.39 9/19/2003
##   YEAR MONTH DAY SoaktimeTotal_mins TAPEREADER.x FISHID GROUP FAMILY GENUS
## 1 2004     4  26             62.550   Mike Cappo     NA  <NA>   <NA>  <NA>
## 2 2004     4  26             62.500   Mike Cappo     NA  <NA>   <NA>  <NA>
## 3 2004     4  26             57.567   Mike Cappo     NA  <NA>   <NA>  <NA>
## 4 2003     9  19             62.467 Peter Speare     NA  <NA>   <NA>  <NA>
## 5 2003     9  19             62.467 Peter Speare     NA  <NA>   <NA>  <NA>
## 6 2003     9  19             62.533 Peter Speare     NA  <NA>   <NA>  <NA>
##   SPECIES COMMON  SPP STAGE ENVIRON Depthrange TAPEREADER.y TimeMaxNmins
## 1    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 2    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 3    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 4    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 5    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 6    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
##   MaxN
## 1   NA
## 2   NA
## 3   NA
## 4   NA
## 5   NA
## 6   NA
dim(db.final)
## [1] 557  27
# Exportar base de datos final
name <- paste(Sys.Date(), "_", "bd.final.exportada.csv", sep = "")
write.csv(db.final, name, row.names = F)

 

Luego de unir ambas bases de datos vamos a “limpiar” un poco los datos y manipularlos para determinar cuales especies fueron más abundantes.

# Visualizar base de datos
head(db.final)
##   BRUVSID OPCODE CAMERA   SITE  LOCATION DEPTH     LAT    LON  DATETIME
## 1    2400   2647      5 S_2647 Acheron I  21.8 -18.915 146.62 4/26/2004
## 2    2401   2647      3 S_2647 Acheron I  21.9 -18.914 146.62 4/26/2004
## 3    2402   2647      2 S_2647 Acheron I  21.9 -18.913 146.61 4/26/2004
## 4    2809    815      4  S_815  Arc Reef  48.3 -18.491 147.40 9/19/2003
## 5    2810    815      3  S_815  Arc Reef  29.5 -18.489 147.40 9/19/2003
## 6    2811    815      2  S_815  Arc Reef  42.9 -18.486 147.39 9/19/2003
##   YEAR MONTH DAY SoaktimeTotal_mins TAPEREADER.x FISHID GROUP FAMILY GENUS
## 1 2004     4  26             62.550   Mike Cappo     NA  <NA>   <NA>  <NA>
## 2 2004     4  26             62.500   Mike Cappo     NA  <NA>   <NA>  <NA>
## 3 2004     4  26             57.567   Mike Cappo     NA  <NA>   <NA>  <NA>
## 4 2003     9  19             62.467 Peter Speare     NA  <NA>   <NA>  <NA>
## 5 2003     9  19             62.467 Peter Speare     NA  <NA>   <NA>  <NA>
## 6 2003     9  19             62.533 Peter Speare     NA  <NA>   <NA>  <NA>
##   SPECIES COMMON  SPP STAGE ENVIRON Depthrange TAPEREADER.y TimeMaxNmins
## 1    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 2    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 3    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 4    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 5    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
## 6    <NA>   <NA> <NA>  <NA>    <NA>       <NA>         <NA>           NA
##   MaxN
## 1   NA
## 2   NA
## 3   NA
## 4   NA
## 5   NA
## 6   NA
names(db.final)
##  [1] "BRUVSID"            "OPCODE"             "CAMERA"            
##  [4] "SITE"               "LOCATION"           "DEPTH"             
##  [7] "LAT"                "LON"                "DATETIME"          
## [10] "YEAR"               "MONTH"              "DAY"               
## [13] "SoaktimeTotal_mins" "TAPEREADER.x"       "FISHID"            
## [16] "GROUP"              "FAMILY"             "GENUS"             
## [19] "SPECIES"            "COMMON"             "SPP"               
## [22] "STAGE"              "ENVIRON"            "Depthrange"        
## [25] "TAPEREADER.y"       "TimeMaxNmins"       "MaxN"
# Crear un subset de la base de datos con variables de interés
#db <- db.final[, c("BRUVSID", "SITE", "LOCATION", "DEPTH", "LAT", "LON", "DATETIME",
#                   "YEAR", "MONTH", "DAY", "SoaktimeTotal_mins")]
db <- db.final[, c(1, 4:13, 18:19, 21, 27)]

head(db)
##   BRUVSID   SITE  LOCATION DEPTH     LAT    LON  DATETIME YEAR MONTH DAY
## 1    2400 S_2647 Acheron I  21.8 -18.915 146.62 4/26/2004 2004     4  26
## 2    2401 S_2647 Acheron I  21.9 -18.914 146.62 4/26/2004 2004     4  26
## 3    2402 S_2647 Acheron I  21.9 -18.913 146.61 4/26/2004 2004     4  26
## 4    2809  S_815  Arc Reef  48.3 -18.491 147.40 9/19/2003 2003     9  19
## 5    2810  S_815  Arc Reef  29.5 -18.489 147.40 9/19/2003 2003     9  19
## 6    2811  S_815  Arc Reef  42.9 -18.486 147.39 9/19/2003 2003     9  19
##   SoaktimeTotal_mins GENUS SPECIES  SPP MaxN
## 1             62.550  <NA>    <NA> <NA>   NA
## 2             62.500  <NA>    <NA> <NA>   NA
## 3             57.567  <NA>    <NA> <NA>   NA
## 4             62.467  <NA>    <NA> <NA>   NA
## 5             62.467  <NA>    <NA> <NA>   NA
## 6             62.533  <NA>    <NA> <NA>   NA
names(db)
##  [1] "BRUVSID"            "SITE"               "LOCATION"          
##  [4] "DEPTH"              "LAT"                "LON"               
##  [7] "DATETIME"           "YEAR"               "MONTH"             
## [10] "DAY"                "SoaktimeTotal_mins" "GENUS"             
## [13] "SPECIES"            "SPP"                "MaxN"
str(db)
## 'data.frame':    557 obs. of  15 variables:
##  $ BRUVSID           : int  2400 2401 2402 2809 2810 2811 2812 3046 3047 3047 ...
##  $ SITE              : Factor w/ 38 levels "S_2647","S_815",..: 1 1 1 2 2 2 2 3 3 3 ...
##  $ LOCATION          : Factor w/ 36 levels "_20348S","_20353S",..: 34 34 34 35 35 35 35 33 33 33 ...
##  $ DEPTH             : num  21.8 21.9 21.9 48.3 29.5 42.9 47.3 38.2 37.4 37.4 ...
##  $ LAT               : num  -18.9 -18.9 -18.9 -18.5 -18.5 ...
##  $ LON               : num  147 147 147 147 147 ...
##  $ DATETIME          : Factor w/ 26 levels "1/11/2009","1/16/2009",..: 23 23 23 26 26 26 26 13 13 13 ...
##  $ YEAR              : int  2004 2004 2004 2003 2003 2003 2003 2003 2003 2003 ...
##  $ MONTH             : int  4 4 4 9 9 9 9 10 10 10 ...
##  $ DAY               : int  26 26 26 19 19 19 19 5 5 5 ...
##  $ SoaktimeTotal_mins: num  62.5 62.5 57.6 62.5 62.5 ...
##  $ GENUS             : Factor w/ 23 levels "Aptychotrema",..: NA NA NA NA NA NA NA NA 2 2 ...
##  $ SPECIES           : Factor w/ 35 levels "acutidens","albimarginatus",..: NA NA NA NA NA NA NA NA 5 4 ...
##  $ SPP               : Factor w/ 38 levels "Aptychotrema rostrata",..: NA NA NA NA NA NA NA NA 5 4 ...
##  $ MaxN              : int  NA NA NA NA NA NA NA NA 1 1 ...
# Crear base de datos de sitios
db.sitios <- db[, c(1:11)]
head(db.sitios)
##   BRUVSID   SITE  LOCATION DEPTH     LAT    LON  DATETIME YEAR MONTH DAY
## 1    2400 S_2647 Acheron I  21.8 -18.915 146.62 4/26/2004 2004     4  26
## 2    2401 S_2647 Acheron I  21.9 -18.914 146.62 4/26/2004 2004     4  26
## 3    2402 S_2647 Acheron I  21.9 -18.913 146.61 4/26/2004 2004     4  26
## 4    2809  S_815  Arc Reef  48.3 -18.491 147.40 9/19/2003 2003     9  19
## 5    2810  S_815  Arc Reef  29.5 -18.489 147.40 9/19/2003 2003     9  19
## 6    2811  S_815  Arc Reef  42.9 -18.486 147.39 9/19/2003 2003     9  19
##   SoaktimeTotal_mins
## 1             62.550
## 2             62.500
## 3             57.567
## 4             62.467
## 5             62.467
## 6             62.533
names(db.sitios)
##  [1] "BRUVSID"            "SITE"               "LOCATION"          
##  [4] "DEPTH"              "LAT"                "LON"               
##  [7] "DATETIME"           "YEAR"               "MONTH"             
## [10] "DAY"                "SoaktimeTotal_mins"
### Formato de columnas con información de especies ###

# Crear código de 3 letras para especies
db$GENUS <- as.character(db$GENUS)
db$SPECIES <- as.character(db$SPECIES)

spp.code1 <- abbreviate(db$GENUS, 1, strict = T)
spp.code2 <- abbreviate(db$SPECIES, 4, strict = T, method = "left.kept")

db$spp.code <- paste(spp.code1, spp.code2, sep = "")
db[db == "NANA" ] = NA

# Analizar datos de especies
unique(db$spp.code)
##  [1] NA      "Cambn" "Cambl" "Tmeyn" "Tobss" "Calbm" "Dkuhl" "Rdjdd"
##  [9] "Cplmb" "Gcuvr" "Psphn" "Nfrrg" "Hastr" "Smkrr" "Hfai"  "Lmcrr"
## [17] "Clecs" "Helng" "Mbrst" "Rtylr" "Cbrvp" "Rancy" "Arstr"
unique(db$SPP) 
##  [1] <NA>                        Carcharhinus amboinensis   
##  [3] Carcharhinus amblyrhynchos  Taeniura meyeni            
##  [5] Triaenodon obesus           Carcharhinus albimarginatus
##  [7] Neotrygon kuhlii            Rhynchobatus djiddensis    
##  [9] Carcharhinus plumbeus       Galeocerdo cuvier          
## [11] Pastinachus sephen          Nebrius ferrugineus        
## [13] Hemigaleus australiensis    Sphyrna mokarran           
## [15] Himantura fai               Loxodon macrorhinus        
## [17] Carcharhinus leucas         Hemipristis elongata       
## [19] Manta birostris             Rhizoprionodon taylori     
## [21] Carcharhinus brevipinna     Rhina ancylostoma          
## [23] Aptychotrema rostrata      
## 38 Levels: Aptychotrema rostrata ... Triaenodon obesus
length(unique(db$SPP))
## [1] 23
# Cambiar el nombre de base de datos
dat.maxn <- db

# Ordenar base de datos por códigos de especies
dat.maxn <- dat.maxn[order(dat.maxn$spp.code), ]
head(dat.maxn)
##     BRUVSID       SITE           LOCATION DEPTH     LAT    LON  DATETIME
## 539    7470 S_ARP4BB-1        Barcoo Bank  25.5 -22.831 151.67 11/5/2009
## 33     6111  S_RAPBBgB        Barcoo Bank  23.2 -22.831 151.68  8/6/2007
## 34     6112  S_RAPBBgB        Barcoo Bank  39.6 -22.831 151.69  8/6/2007
## 135    6910  S_ARP3B19            _21245S  34.0 -21.296 152.44 1/22/2009
## 148    6922  S_ARP3B20 _SMALL LAGOON REEF  38.2 -21.863 152.53 1/24/2009
## 149    6923  S_ARP3B20 _SMALL LAGOON REEF  38.4 -21.862 152.53 1/24/2009
##     YEAR MONTH DAY SoaktimeTotal_mins        GENUS        SPECIES
## 539 2009    11   5             62.000 Aptychotrema       rostrata
## 33  2007     8   6             62.450 Carcharhinus albimarginatus
## 34  2007     8   6             62.433 Carcharhinus albimarginatus
## 135 2009     1  22             62.467 Carcharhinus albimarginatus
## 148 2009     1  24             62.433 Carcharhinus albimarginatus
## 149 2009     1  24             62.400 Carcharhinus albimarginatus
##                             SPP MaxN spp.code
## 539       Aptychotrema rostrata    1    Arstr
## 33  Carcharhinus albimarginatus    1    Calbm
## 34  Carcharhinus albimarginatus    1    Calbm
## 135 Carcharhinus albimarginatus    1    Calbm
## 148 Carcharhinus albimarginatus    1    Calbm
## 149 Carcharhinus albimarginatus    1    Calbm
# Calcular abundancias
dat.maxn2 <- reshape2:::dcast(dat.maxn, BRUVSID ~ spp.code, value.var = "MaxN")
## Aggregation function missing: defaulting to length
head(dat.maxn2)
##   BRUVSID Arstr Calbm Cambl Cambn Cbrvp Clecs Cplmb Dkuhl Gcuvr Hastr
## 1    2400     0     0     0     0     0     0     0     0     0     0
## 2    2401     0     0     0     0     0     0     0     0     0     0
## 3    2402     0     0     0     0     0     0     0     0     0     0
## 4    2809     0     0     0     0     0     0     0     0     0     0
## 5    2810     0     0     0     0     0     0     0     0     0     0
## 6    2811     0     0     0     0     0     0     0     0     0     0
##   Helng Hfai Lmcrr Mbrst Nfrrg Psphn Rancy Rdjdd Rtylr Smkrr Tmeyn Tobss
## 1     0    0     0     0     0     0     0     0     0     0     0     0
## 2     0    0     0     0     0     0     0     0     0     0     0     0
## 3     0    0     0     0     0     0     0     0     0     0     0     0
## 4     0    0     0     0     0     0     0     0     0     0     0     0
## 5     0    0     0     0     0     0     0     0     0     0     0     0
## 6     0    0     0     0     0     0     0     0     0     0     0     0
##   NA
## 1  1
## 2  1
## 3  1
## 4  1
## 5  1
## 6  1
dim(dat.maxn2)  
## [1] 499  24
str(dat.maxn2)
## 'data.frame':    499 obs. of  24 variables:
##  $ BRUVSID: int  2400 2401 2402 2809 2810 2811 2812 3046 3047 3048 ...
##  $ Arstr  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Calbm  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Cambl  : int  0 0 0 0 0 0 0 0 1 0 ...
##  $ Cambn  : int  0 0 0 0 0 0 0 0 1 0 ...
##  $ Cbrvp  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Clecs  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Cplmb  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Dkuhl  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Gcuvr  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Hastr  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Helng  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Hfai   : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Lmcrr  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Mbrst  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Nfrrg  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Psphn  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Rancy  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Rdjdd  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Rtylr  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Smkrr  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Tmeyn  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Tobss  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ NA     : int  1 1 1 1 1 1 1 1 0 1 ...
dat.maxn <- dat.maxn2

# Unir bases de abundancias y sitios
d.bruvs <- merge(db.sitios, dat.maxn, by="BRUVSID", all.x=T)

head(d.bruvs)
##   BRUVSID   SITE  LOCATION DEPTH     LAT    LON  DATETIME YEAR MONTH DAY
## 1    2400 S_2647 Acheron I  21.8 -18.915 146.62 4/26/2004 2004     4  26
## 2    2401 S_2647 Acheron I  21.9 -18.914 146.62 4/26/2004 2004     4  26
## 3    2402 S_2647 Acheron I  21.9 -18.913 146.61 4/26/2004 2004     4  26
## 4    2809  S_815  Arc Reef  48.3 -18.491 147.40 9/19/2003 2003     9  19
## 5    2810  S_815  Arc Reef  29.5 -18.489 147.40 9/19/2003 2003     9  19
## 6    2811  S_815  Arc Reef  42.9 -18.486 147.39 9/19/2003 2003     9  19
##   SoaktimeTotal_mins Arstr Calbm Cambl Cambn Cbrvp Clecs Cplmb Dkuhl Gcuvr
## 1             62.550     0     0     0     0     0     0     0     0     0
## 2             62.500     0     0     0     0     0     0     0     0     0
## 3             57.567     0     0     0     0     0     0     0     0     0
## 4             62.467     0     0     0     0     0     0     0     0     0
## 5             62.467     0     0     0     0     0     0     0     0     0
## 6             62.533     0     0     0     0     0     0     0     0     0
##   Hastr Helng Hfai Lmcrr Mbrst Nfrrg Psphn Rancy Rdjdd Rtylr Smkrr Tmeyn
## 1     0     0    0     0     0     0     0     0     0     0     0     0
## 2     0     0    0     0     0     0     0     0     0     0     0     0
## 3     0     0    0     0     0     0     0     0     0     0     0     0
## 4     0     0    0     0     0     0     0     0     0     0     0     0
## 5     0     0    0     0     0     0     0     0     0     0     0     0
## 6     0     0    0     0     0     0     0     0     0     0     0     0
##   Tobss NA
## 1     0  1
## 2     0  1
## 3     0  1
## 4     0  1
## 5     0  1
## 6     0  1
names(d.bruvs)
##  [1] "BRUVSID"            "SITE"               "LOCATION"          
##  [4] "DEPTH"              "LAT"                "LON"               
##  [7] "DATETIME"           "YEAR"               "MONTH"             
## [10] "DAY"                "SoaktimeTotal_mins" "Arstr"             
## [13] "Calbm"              "Cambl"              "Cambn"             
## [16] "Cbrvp"              "Clecs"              "Cplmb"             
## [19] "Dkuhl"              "Gcuvr"              "Hastr"             
## [22] "Helng"              "Hfai"               "Lmcrr"             
## [25] "Mbrst"              "Nfrrg"              "Psphn"             
## [28] "Rancy"              "Rdjdd"              "Rtylr"             
## [31] "Smkrr"              "Tmeyn"              "Tobss"             
## [34] "NA"
# Columnas que contienen spp
n1 <- 12   # first species column
n2 <- 33 # last species column

colSums(d.bruvs[,c(n1:n2)])
## Arstr Calbm Cambl Cambn Cbrvp Clecs Cplmb Dkuhl Gcuvr Hastr Helng  Hfai 
##     1    26   159     2     2     1     2    23    29     2     3     2 
## Lmcrr Mbrst Nfrrg Psphn Rancy Rdjdd Rtylr Smkrr Tmeyn Tobss 
##     2     9    14     2     2    30     2     8    26    58
# Ordenar columnas según abundancia
ord.db <- rev(order(apply(d.bruvs[n1:n2], 2, sum)))

db1 <- d.bruvs[n1:n2] 
names(db1)
##  [1] "Arstr" "Calbm" "Cambl" "Cambn" "Cbrvp" "Clecs" "Cplmb" "Dkuhl"
##  [9] "Gcuvr" "Hastr" "Helng" "Hfai"  "Lmcrr" "Mbrst" "Nfrrg" "Psphn"
## [17] "Rancy" "Rdjdd" "Rtylr" "Smkrr" "Tmeyn" "Tobss"
# Ordenar presencia/ausencia por ocurrencia
db2 <- db1[, ord.db]
names(db2)
##  [1] "Cambl" "Tobss" "Rdjdd" "Gcuvr" "Tmeyn" "Calbm" "Dkuhl" "Nfrrg"
##  [9] "Mbrst" "Smkrr" "Helng" "Rtylr" "Rancy" "Psphn" "Lmcrr" "Hfai" 
## [17] "Hastr" "Cplmb" "Cbrvp" "Cambn" "Clecs" "Arstr"
maxn.spp <- cbind(d.bruvs[,c(1:(n1-1))], db2)
head(maxn.spp)
##   BRUVSID   SITE  LOCATION DEPTH     LAT    LON  DATETIME YEAR MONTH DAY
## 1    2400 S_2647 Acheron I  21.8 -18.915 146.62 4/26/2004 2004     4  26
## 2    2401 S_2647 Acheron I  21.9 -18.914 146.62 4/26/2004 2004     4  26
## 3    2402 S_2647 Acheron I  21.9 -18.913 146.61 4/26/2004 2004     4  26
## 4    2809  S_815  Arc Reef  48.3 -18.491 147.40 9/19/2003 2003     9  19
## 5    2810  S_815  Arc Reef  29.5 -18.489 147.40 9/19/2003 2003     9  19
## 6    2811  S_815  Arc Reef  42.9 -18.486 147.39 9/19/2003 2003     9  19
##   SoaktimeTotal_mins Cambl Tobss Rdjdd Gcuvr Tmeyn Calbm Dkuhl Nfrrg Mbrst
## 1             62.550     0     0     0     0     0     0     0     0     0
## 2             62.500     0     0     0     0     0     0     0     0     0
## 3             57.567     0     0     0     0     0     0     0     0     0
## 4             62.467     0     0     0     0     0     0     0     0     0
## 5             62.467     0     0     0     0     0     0     0     0     0
## 6             62.533     0     0     0     0     0     0     0     0     0
##   Smkrr Helng Rtylr Rancy Psphn Lmcrr Hfai Hastr Cplmb Cbrvp Cambn Clecs
## 1     0     0     0     0     0     0    0     0     0     0     0     0
## 2     0     0     0     0     0     0    0     0     0     0     0     0
## 3     0     0     0     0     0     0    0     0     0     0     0     0
## 4     0     0     0     0     0     0    0     0     0     0     0     0
## 5     0     0     0     0     0     0    0     0     0     0     0     0
## 6     0     0     0     0     0     0    0     0     0     0     0     0
##   Arstr
## 1     0
## 2     0
## 3     0
## 4     0
## 5     0
## 6     0
# Crear un gráfico resumen de abundancias
sum.maxn.spp <- colSums(maxn.spp[,c(n1:n2)])

# Parámetros del gráfico
par(mar = c(4, 6, 1, 2))

# Visualizar gráfico de barras
barplot(as.matrix(t(sum.maxn.spp)), horiz = T, ann = F, col = "indianred1",
        xlim = c(0, max(sum.maxn.spp + 10)),
        las = 1, axes = F, font = 1, xlab = "", ylab = "")

# Poner eje X
axis(1)

# Títulos de ejes
mtext("MaxN", 1, line = 2.5, cex = 1.5)
mtext("Especies", 2, line = 3.85, cex = 1.5)

box(bty = "l")


Referencias

  • Clements, J. F., T. S. Schulenberg, M. J. Iliff, D. Roberson, T. A. Fredericks, B. L. Sullivan, and C. L. Wood. 2017. The eBird/Clements checklist of birds of the world: v2016.

  • Jones, Jon Bielby, Marcel Cardillo, Susanne A. Fritz, Justin O’Dell, C. David L. Orme, Kamran Safi, Wes Sechrest, Elizabeth H. Boakes, Chris Carbone, Christina Connolly, Michael J. Cutts, Janine K. Foster, Richard Grenyer, Michael Habib, Christopher A. Plaster, Samantha A. Price, Elizabeth A. Rigby, Janna Rist, Amber Teacher, Olaf R. P. Bininda-Emonds, John L. Gittleman, Georgina M. Mace, and Andy Purvis. 2009. PanTHERIA: a species-level database of life history, ecology, and geography of extant and recently extinct mammals. Ecology 90:2648.

  • Wickham, Hadley, and Garrett Grolemund. 2016. R for data science: import, tidy, transform, visualize, and model data. sitio web

  • Data import tutorial- DataCamp


Informacíon de la sesión

## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 19.04
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.8.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.8.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=es_CR.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=es_CR.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=es_CR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=es_CR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] rmdformats_0.3.5   dplyr_0.8.0.1      tidyr_0.8.3       
## [4] readxl_1.3.1       kableExtra_1.1.0   knitr_1.23        
## [7] ggplot2_3.1.1      RColorBrewer_1.1-2
## 
## loaded via a namespace (and not attached):
##  [1] tidyselect_0.2.5  xfun_0.7          reshape2_1.4.3   
##  [4] purrr_0.3.2       colorspace_1.4-1  miniUI_0.1.1.1   
##  [7] htmltools_0.3.6   viridisLite_0.3.0 yaml_2.2.0       
## [10] rlang_0.3.4       pillar_1.4.0      later_0.8.0      
## [13] glue_1.3.1        withr_2.1.2       plyr_1.8.4       
## [16] questionr_0.7.0   stringr_1.4.0     munsell_0.5.0    
## [19] gtable_0.3.0      cellranger_1.1.0  rvest_0.3.3      
## [22] evaluate_0.14     httpuv_1.5.1      highr_0.8        
## [25] Rcpp_1.0.1        xtable_1.8-4      readr_1.3.1      
## [28] scales_1.0.0      promises_1.0.1    webshot_0.5.1    
## [31] mime_0.6          hms_0.4.2         digest_0.6.19    
## [34] stringi_1.4.3     bookdown_0.11     shiny_1.3.2      
## [37] grid_3.6.1        tools_3.6.1       magrittr_1.5     
## [40] lazyeval_0.2.2    tibble_2.1.1      crayon_1.3.4     
## [43] pkgconfig_2.0.2   xml2_1.2.0        assertthat_0.2.1 
## [46] rmarkdown_1.13    httr_1.4.0        rstudioapi_0.10  
## [49] R6_2.4.0          compiler_3.6.1