Capítulo 5 Importando datos

Hemos estado usando sets de datos ya almacenados como objetos R. Los científicos de datos rara vez tendrán tanta suerte y frecuentemente tendrán que importar datos a R desde un archivo, una base de datos u otras fuentes. Actualmente, una de las formas más comunes de almacenar y compartir datos para el análisis es a través de hojas de cálculo electrónicas. Una hoja de cálculo almacena datos en filas y columnas. Básicamente es una versión de archivo de un data frame. Al guardar dicha tabla en un archivo de computadora, uno necesita una manera de definir cuándo termina una nueva fila o columna y cuando comienza la otra. Esto a su vez define las celdas en las que se almacenan los valores individuales.

Al crear hojas de cálculo con archivos de texto, como esas creadas con un editor sencillo de texto, se define una nueva fila con return y se separan las columnas con un carácter especial predefinido. Los caracteres más comunes son coma (,), punto y coma (;), espacio ( ) y el tab (un número predeterminado de espacios o \t). Aquí tenemos un ejemplo de cómo se ve un archivo separado por comas si lo abrimos con un editor básico de texto:

La primera fila contiene nombres de columnas en lugar de datos. Nos referimos a esto como un encabezado (header en inglés), y cuando leemos (read-in en inglés) datos de una hoja de cálculo es importante saber si el archivo tiene un encabezado o no. La mayoría de las funciones de lectura suponen que hay un encabezado. Para saber si el archivo tiene un encabezado, miren el archivo antes de intentar leerlo. Esto se puede hacer con un editor de texto o con RStudio. En RStudio, podemos hacerlo abriendo el archivo en el editor o navegando a la ubicación del archivo, haciendo doble clic en el archivo y presionando View File.

Sin embargo, no todos los archivos de hojas de cálculo están en formato de texto. Las hojas de cálculo de Google (Google Sheets en inglés), por ejemplo, se acceden con un navegador. Otro ejemplo es el formato propietario utilizado por Microsoft Excel, que no se puede ver con un editor de texto. A pesar de esto y debido a la popularidad del software Microsoft Excel, este formato se utiliza ampliamente.

Comenzamos este capítulo describiendo las diferencias entre archivos de texto (ASCII), Unicode y binarios y cómo estas afectan la forma en que los importamos. Entonces, explicamos los conceptos de rutas de archivos y directorios de trabajo, que son esenciales para comprender cómo importar datos de manera efectiva. Luego, presentamos los paquetes readr y readxl y las funciones disponibles para importar hojas de cálculo en R. Finalmente, ofrecemos algunas recomendaciones sobre cómo almacenar y organizar datos en archivos. Los desafíos más complejos, sin embargo, como la extracción de datos de páginas web o de documentos PDF, se discutirán en la parte del libro “Wrangling de datos”.

5.1 Las rutas y el directorio de trabajo

El primer paso para importar datos desde una hoja de cálculo es ubicar el archivo que contiene los datos. Aunque no lo recomendamos, pueden utilizar un enfoque similar al que usan para abrir archivos en Microsoft Excel: haciendo clic en el menú de File de RStudio, haciendo clic en Import Dataset y luego haciendo clic en las carpetas hasta encontrar el archivo. Queremos poder escribir código en lugar de estar apuntando y haciendo clic. Las claves y los conceptos que necesitamos para aprender a hacer esto se describen en detalle en la parte del libro “Herramientas de productividad”. Aquí ofrecemos una descripción general de los conceptos básicos.

El principal reto de este primer paso es permitir que las funciones de R que realizan la importación sepan dónde buscar el archivo que contiene los datos. La forma más sencilla de hacer esto es tener una copia del archivo en la carpeta donde las funciones de importación buscan por defecto. Una vez que hagamos esto, solo tenemos que proveerle el nombre del archivo a la función de importación.

El paquete dslabs incluye una hoja de cálculo que contiene los datos de los asesinatos de EE. UU. Encontrar este archivo no es obvio, pero las siguientes líneas de código copian el archivo a la carpeta en la que R busca por defecto. A continuación explicamos cómo funcionan estas líneas.

filename <- "murders.csv"
dir <- system.file("extdata", package = "dslabs")
fullpath <- file.path(dir, filename)
file.copy(fullpath, "murders.csv")

Este código no lee los datos en R, solo copia un archivo. Pero una vez copie el archivo, podemos importar los datos con solo una línea de código. Aquí usamos la función read_csv del paquete readr, que forma parte del tidyverse.

library(tidyverse)
dat <- read_csv(filename)

Los datos se importan y almacenan en dat. El resto de esta sección define algunos conceptos importantes y ofrece una visión general de cómo escribimos código para que R pueda encontrar los archivos que queremos importar. Capítulo 38 ofrece más detalles sobre este tema.

5.1.1 El sistema de archivos

Pueden pensar en el sistema de archivos (filesystem en inglés) de su computadora como una serie de carpetas anidadas, cada una con otras carpetas y archivos. Los científicos de datos se refieren a las carpetas como directorios y a la carpeta que contiene todas las demás carpetas como el directorio raíz (root directory en inglés). El directorio en el que estamos ubicados actualmente se llama el directorio de trabajo (working directory en inglés). Por lo tanto, el directorio de trabajo cambia a medida que se muevan por las carpetas: considérenlo como su ubicación actual.

5.1.2 Las rutas relativas y completas

La ruta (path en inglés) de un archivo es una lista de nombres de directorios que se pueden considerar instrucciones sobre en qué carpetas hacer clic y en qué orden encontrar el archivo. Si estas instrucciones son para encontrar el archivo desde el directorio raíz, nos referiremos a ellas como la ruta completa (full path en inglés). Si las instrucciones son para encontrar el archivo desde el directorio de trabajo, nos referimos a ellas como una ruta relativa (relative path en inglés). Sección 38.3 ofrece más detalles sobre este tema.

Para ver un ejemplo de una ruta completa en su sistema, escriban lo siguiente:

system.file(package = "dslabs")

Las cadenas separadas por barras son los nombres de los directorios. La primera barra diagonal representa el directorio raíz y sabemos que esta es una ruta completa porque comienza con una barra diagonal. Si el primer nombre del directorio aparece sin una barra diagonal en el comienzo, entonces R supone que la ruta es relativa. Podemos usar la función list.files para ver ejemplos de rutas relativas:

dir <- system.file(package = "dslabs")
list.files(path = dir)
#>  [1] "data"        "DESCRIPTION" "extdata"     "help"       
#>  [5] "html"        "INDEX"       "Meta"        "NAMESPACE"  
#>  [9] "R"           "script"

Estas rutas relativas nos dan la localización de los archivos o directorios si comenzamos en el directorio con la ruta completa. Por ejemplo, la ruta completa al directorio help en el ejemplo anterior es: /Library/Frameworks/R.framework/Versions/3.5/Resources/library/dslabs/help.

Nota: Probablemente no harán mucho uso de la función system.file en su trabajo diario de análisis de datos. Lo presentamos en esta sección porque facilita el intercambio de hojas de cálculo al incluirlas en el paquete dslabs. Raras veces tendrán el lujo de tener datos incluidos en paquetes que ya han instalado. Sin embargo, con frecuencia necesitarán navegar por rutas completas y relativas e importar datos con formato de hoja de cálculo.

5.1.3 El directorio de trabajo

Recomendamos escribir solo rutas relativas en su código ya que las rutas completas son exclusivas de sus computadoras y es preferible que su código sea portátil. Pueden obtener la ruta completa de su directorio de trabajo sin escribirla explícitamente utilizando la función getwd:

wd <- getwd()

Si necesitan cambiar su directorio de trabajo, pueden usar la función setwd o pueden cambiarlo a través de RStudio haciendo clic en Session.

5.1.4 Cómo generar los nombres de ruta

Otro ejemplo de cómo obtener una ruta completa sin escribirla explícitamente se ofreció arriba cuando creamos el objeto fullpath de esta manera:

filename <- "murders.csv"
dir <- system.file("extdata", package = "dslabs")
fullpath <- file.path(dir, filename)

La función system.file provee la ruta completa de la carpeta que contiene todos los archivos y directorios relevantes para el paquete especificado por el argumento package. Al explorar los directorios en dir, nos encontramos con que extdata contiene el archivo que queremos:

dir <- system.file(package = "dslabs")
filename %in% list.files(file.path(dir, "extdata"))
#> [1] TRUE

La función system.file nos permite proveer un subdirectorio como primer argumento, para que podamos obtener la ruta completa del directorio extdata así:

dir <- system.file("extdata", package = "dslabs")

La función file.path se usa para combinar los nombres de directorios para producir la ruta completa del archivo que queremos importar.

fullpath <- file.path(dir, filename)

5.1.5 Cómo copiar los archivos usando rutas

La última línea de código que usamos para copiar el archivo en nuestro directorio de inicio usó la función file.copy. Esta toma dos argumentos: el nombre del archivo para copiar y el nombre que se usará en el nuevo directorio.

file.copy(fullpath, "murders.csv")
#> [1] TRUE

Si un archivo se copia exitosamente, la función file.copy devuelve TRUE. Tengan en cuenta que le estamos dando al archivo el mismo nombre, murders.csv, pero podríamos haberle dado cualquier nombre. También recuerden que al no iniciar la cadena con una barra diagonal, R supone que esta es una ruta relativa y copia el archivo al directorio de trabajo.

Deberían poder ver el archivo en su directorio de trabajo usando:

list.files()

5.2 Los paquetes readr y readxl

En esta sección presentamos las principales funciones de importación del tidyverse. Utilizaremos el archivo murders.csv del paquete dslabs como ejemplo. Para simplificar la ilustración, copiaremos el archivo a nuestro directorio de trabajo usando el siguiente código:

filename <- "murders.csv"
dir <- system.file("extdata", package = "dslabs")
fullpath <- file.path(dir, filename)
file.copy(fullpath, "murders.csv")

5.2.1 readr

El paquete readr incluye funciones para leer datos almacenados en hojas de cálculo. readr es parte del paquete tidyverse, o pueden cargarlo directamente así:

library(readr)

Las siguientes funciones están disponibles para leer hojas de cálculo:

Función Formato Sufijo típico
read_table valores separados por espacios en blanco txt
read_csv valores separados por comas csv
read_csv2 valores separados por punto y coma csv
read_tsv valores separados delimitados por tab tsv
read_delim formato de archivo de texto general, debe definir delimitador txt

Aunque el sufijo generalmente nos indica qué tipo de archivo es, no hay garantía de que estos siempre coincidan. Podemos abrir el archivo para echar un vistazo o usar la función read_lines para ver algunas líneas:

read_lines("murders.csv", n_max = 3)
#> [1] "state,abb,region,population,total"
#> [2] "Alabama,AL,South,4779736,135"     
#> [3] "Alaska,AK,West,710231,19"

Esto también muestra que hay un encabezado. Ahora estamos listos para leer los datos en R. Del sufijo .csv y del vistazo al archivo, sabemos que tenemos que usar read_csv:

dat <- read_csv(filename)

Tengan en cuenta que recibimos un mensaje informándonos qué tipos de datos se utilizaron para cada columna. También observen que dat es un tibble, no solo un data frame. Esto es porque read_csv es un leedor (parser en inglés) del tidyverse. Podemos confirmar que los datos se han leído de la siguiente manera:

View(dat)

Finalmente, recuerden que también podemos usar la ruta completa para el archivo:

dat <- read_csv(fullpath)

5.2.2 readxl

Pueden cargar el paquete readxl usando:

library(readxl)

El paquete ofrece funciones para leer formatos de Microsoft Excel:

Función Formato Sufijo típico
read_excel detectar automáticamente el formato xls, xlsx
read_xls formato original xls
read_xlsx nuevo formato xlsx

Los formatos de Microsoft Excel le permiten tener más de una hoja de cálculo en un archivo. Estos se conocen como hojas (sheets en inglés). Las funciones enumeradas anteriormente leen la primera hoja por defecto, pero también podemos leer las otras. La función excel_sheets nos da los nombres de todas las hojas en un archivo de Excel. Estos nombres entonces se pueden pasar al argumento sheet en las tres funciones anteriores para leer hojas distintas a la primera.

5.3 Ejercicios

1. Utilice la función read_csv para leer cada uno de los archivos que el siguiente código guarda en el objeto files:

path <- system.file("extdata", package = "dslabs")
files <- list.files(path)
files

2. Observe que el último, el archivo olive, nos da una advertencia. Esto se debe a que a la primera línea del archivo le falta el encabezado de la primera columna.

Lea la página de ayuda para read_csv para aprender cómo leer el archivo sin leer este encabezado. Si omite el encabezado, no debería recibir esta advertencia. Guarde el resultado en un objeto llamado dat.

3. Un problema con el enfoque anterior es que no sabemos qué representan las columnas. Escriba:

names(dat)

para confirmar que los nombres no son informativos.

Utilice la función readLines para leer solo la primera línea (luego aprenderemos cómo extraer valores del output).

5.4 Cómo descargar archivos

Otro lugar común donde residen los datos es en el internet. Cuando estos datos están en archivos, podemos descargarlos y luego importarlos, o incluso leerlos directamente de la web. Por ejemplo, notamos que como nuestro paquete dslabs está en GitHub, el archivo que descargamos con el paquete tiene una URL:

url <- "https://raw.githubusercontent.com/rafalab/dslabs/master/inst/
extdata/murders.csv"

El archivo read_csv puede leer estos archivos directamente:

dat <- read_csv(url)

Si quieren tener una copia local del archivo, pueden usar la función download.file:

download.file(url, "murders.csv")

Esto descargará el archivo y lo guardará en su sistema con el nombre murders.csv. Pueden usar cualquier nombre aquí, no necesariamente murders.csv. Recuerden que al usar download.file deben tener cuidado ya que sobrescribirá los archivos existentes sin previo aviso.

Dos funciones que a veces son útiles al descargar datos del internet son tempdir y tempfile. La primera crea un directorio con un nombre aleatorio que es muy probable que sea único. Igualmente, tempfile crea una cadena de caracteres, no un archivo, que probablemente sea un nombre de archivo único. Entonces pueden ejecutar un comando, como el siguiente, que borra el archivo temporero una vez que importe los datos:

tmp_filename <- tempfile()
download.file(url, tmp_filename)
dat <- read_csv(tmp_filename)
file.remove(tmp_filename)

5.5 Las funciones de importación de base R

La base R también provee funciones de importación. Estos tienen nombres similares a esas del tidyverse, por ejemplo read.table, read.csv y read.delim.

dat2 <- read.csv(filename)

5.5.1 scan

Al leer hojas de cálculo, muchas cosas pueden salir mal. El archivo puede tener un encabezado multilíneal, pueden faltar celdas, o puede usar una codificación inesperada17. Les recomendamos que lean esta publicación sobre problemas comunes18.

Con experiencia, aprenderán a manejar los diferentes retos. Además, les ayudará leer detenidamente los archivos de ayuda para las funciones que discutimos aquí. Con scan pueden leer cada celda de un archivo, como vemos aquí:

path <- system.file("extdata", package = "dslabs")
filename <- "murders.csv"
x <- scan(file.path(path, filename), sep=",", what = "c")
x[1:10]
#>  [1] "state"      "abb"        "region"     "population" "total"     
#>  [6] "Alabama"    "AL"         "South"      "4779736"    "135"

Noten que el tidyverse incluye read_lines, una función igualmente útil.

5.6 Archivos de texto versus archivos binarios

En la ciencia de datos, los archivos generalmente se pueden clasificar en dos categorías: archivos de texto (también conocidos como archivos ASCII) y archivos binarios. Ya han trabajado con archivos de texto. Todos sus scripts de R son archivos de texto igual que los archivos de R markdown utilizados para crear este libro. Las tablas csv que han leído también son archivos de texto. Una gran ventaja de estos archivos es que podemos “mirarlos” fácilmente sin tener que comprar ningún tipo de software especial o seguir instrucciones complicadas. Se puede usar cualquier editor de texto para examinar un archivo de texto, incluyendo los editores disponibles gratuitamente como RStudio, Notepad, textEdit, vi, emacs, nano y pico. Para ver esto, intenten abrir un archivo csv con la herramienta de RStudio Open file. Deberían poder ver el contenido directamente en su editor. Sin embargo, si intentan abrir, digamos, un archivo Excel xls, jpg o png, no podrán ver nada inmediatamente útil. Estos son archivos binarios. Los archivos de Excel son carpetas comprimidas con varios archivos de texto dentro de ellas. Pero la principal distinción aquí es que los archivos de texto se pueden examinar fácilmente.

Aunque R incluye herramientas para leer archivos binarios ampliamente utilizados, como archivos xls, en general es mejor encontrar sets de datos almacenados en archivos de texto. Del mismo modo, al compartir datos, es mejor que estén disponibles como archivos de texto siempre que el almacenamiento no sea un problema (los archivos binarios son mucho más eficientes para ahorrar espacio en su disco). En general, los formatos de texto facilitan el intercambio de datos, ya que no requieren software comercial para trabajar con los datos.

Extraer datos de una hoja de cálculo almacenada como un archivo de texto es quizás la forma más fácil de llevar datos de un archivo a una sesión R. Desafortunadamente, las hojas de cálculo no siempre están disponibles y el hecho de que puedan ver los archivos de texto no necesariamente implica que extraer datos de ellos sea sencillo. En la parte del libro “Wrangling de datos”, aprendemos a extraer datos de archivos de texto más complejos, como los archivos HTML.

5.7 Unicode versus ASCII

Un problema en la ciencia de datos es suponer que un archivo es un archivo de texto ASCII cuando en actualidad es otra cosa que puede parecerse mucho a un archivo de texto ASCII: un archivo de texto Unicode.

Para entender la diferencia entre estos, recuerden que todo en una computadora necesita convertirse eventualmente en 0s y 1s. ASCII es una codificación (encoding en inglés) que define una correspondencia entre caracteres y números. ASCII usa 7 bits (0s y 1s) que resulta en \(2^7 = 128\) elementos únicos, suficientes para codificar todos los caracteres en un teclado en inglés. Sin embargo, otros idiomas, como el español, usan caracteres no incluidos en esta codificación. Por ejemplo, las tildes no están codificadas por ASCII. Por esta razón, se definió una nueva codificación que utiliza más de 7 bits: Unicode. Cuando se utiliza Unicode, se puede elegir entre 8, 16 y 32 bits abreviados UTF-8, UTF-16 y UTF-32 respectivamente. RStudio usa la codificación UTF-8 por defecto.

Aunque no entraremos en detalles sobre cómo lidiar con las diferentes codificaciones aquí, es importante que sepan que existen diferentes codificaciones para que pueden diagnosticar bien un problema si lo encuentran. Una forma en que se manifiestan los problemas es cuando surjen caracteres de “aspecto extraño” que no esperaban. Esta discusión de StackOverflow es un ejemplo: https://stackoverflow.com/questions/18789330/r-on-windows-character-encoding-hell.

5.8 Cómo organizar datos con hojas de cálculo

Aunque este libro se enfoca casi exclusivamente en el análisis de datos, el manejo de datos también es una parte importante de la ciencia de datos. Como explicamos en la introducción, no cubrimos este tema. Sin embargo, los analistas de datos frecuentemente necesitan recopilar datos, o trabajar con otros que recopilan datos, de manera que la forma más conveniente de almacenarlos es en una hoja de cálculo. Aunque completar una hoja de cálculo a mano es una práctica que no recomendamos y preferimos que el proceso se automatice lo más posible, a veces no queda otro remedio. Por lo tanto, en esta sección, ofrecemos recomendaciones sobre cómo organizar los datos en una hoja de cálculo. Aunque hay paquetes R diseñados para leer hojas de cálculo de Microsoft Excel, generalmente queremos evitar este formato. Recomendamos Google Sheets como una herramienta de software gratuita. Abajo resumimos las recomendaciones hechas en una publicación de Karl Broman y Kara Woo19. Favor de leer el artículo completo para más detalles importantes.

  • Sea coherente - Antes de empezar a ingresar datos, tenga un plan. Una vez lo tenga, sea consistente y sígalo.
  • Elija buenos nombres para las cosas: Los nombres que elije para los objetos, los archivos y los directorios deben ser memorables, fáciles de deletrear y descriptivos. Este es un equilibrio difícil de lograr y requiere tiempo y reflexión. Una regla importante a seguir es no usar espacios; en su lugar, usen guiones bajos _ o guiones -. Además, evite los símbolos; es mejor utilizar las letras y los números.
  • Escriba fechas como AAAA-MM-DD - Para evitar confusión, recomendamos utilizar el estándar global ISO 8601.
  • Evite las celdas vacías - Llene todas las celdas y use un código común para los datos faltantes.
  • Ponga solo una cosa en cada celda - Es mejor añadir columnas para almacenar la información adicional en vez de tener más de una pieza de información en una celda.
  • Hazlo un rectángulo - La hoja de cálculo debe ser un rectángulo.
  • Cree un diccionario de datos - Si necesita explicar cosas, por ejemplo cuáles son las columnas o cuáles son las etiquetas utilizadas para las variables categóricas, hágalo en un archivo separado.
  • No haga cálculos en los archivos de datos sin procesar - Excel le permite realizar cálculos. No haga esto parte de su hoja de cálculo. El código para los cálculos debe estar en un script.
  • No use color o resaltado como datos - La mayoría de funciones de importación no pueden importar esta información. En cambio, codifique esta información como una variable.
  • Respalde su información: Respalde sus datos frecuentemente.
  • Utilice la validación de datos para evitar errores - Aproveche las herramientas en su software de hoja de cálculo para que el proceso sea lo más libre posible de errores y de lesiones por estrés repetitivo.
  • Guarde los datos como archivos de texto - Guarde los archivos para compartir en formato delimitado por comas o tabs.

5.9 Ejercicios

1. Elija una medida que pueda tomar regularmente. Por ejemplo, su peso diario o cuánto tiempo le toma correr 8 kilometros. Mantenga una hoja de cálculo que incluya la fecha, la hora, la medición y cualquier otra variable informativa que considere valiosa. Haga esto por 2 semanas. Luego haga un gráfico.