1. Introducción

La extracción de datos es muy importante cuando se trata del mundo de los negocios, ya que es necesaria para completar la investigación de mercado. Las empresas requieren extraer datos para estar al tanto de los cambios en el mercado, su público objetivo, para poder generar nuevas ideas para su negocio, mejorar su estrategia con respecto a la competencia, analizar promociones y publicidad, etc.

Este paso se puede hacer mediante el uso de servicios de rastreo web (web scraping), usando bases de datos complemetarias en distintos formatos (.sav, .dta, .xlsx, .csv, .txt, .json) o estructurando datos disponibles pero aún no explotados (documentos, audio, video). Es una práctica muy popular recopilar datos de la web (noticias, redes sociales) que pueden agregar gran valor para mejorar el rendimiento de marketing cuando hablamos de optimización de motires de busqueda, lanzamiento de nuevos productos, análisis del desempeño de anuncios y mucho más. A continuación revisaremos algunas técnicas de extracción de información según su formato y su fuente.

1.1. Datos estructurados:

Los datos estructurados tienen perfectamente definido la longitud, el formato y el tamaño de sus datos. Se almacenan en formato tabla, hojas de cálculo o en bases de datos relacionales.

1.2. Datos no estructurados:

Los datos no estructurados se caracterizan por no tener un formato específico. Se almacenan en múltiples formatos como documentos PDF o Word, correos electrónicos, ficheros multimedia de imagen, audio o video, etc.

1.3. Datos semiestructurados:

Los datos semiestructurados son una mezcla de los dos anteriores, no presentan una estructura perfectamente definida como los datos estructurados pero si presentan una organización definida en sus metadatos donde describen los objetos y sus relaciones, y que en algunos casos están aceptados por convención, como por ejemplo los formatos HTML, XML o JSON.

2. Importar archivos de datos estructurados

La función read.table es muy útil cuando se leen archivos que contienen datos rectangulares.

Esta función tiene dos argumentos, header y sep. Cuando el archivo contiene los nombres de las variables en la primera línea de datos, header=T. El argumento sep que esta por defecto es el espacio en blanco, pero este se puede cambiar dependiendo del archivo a subir.

Acontinuación veamos algunos ejemplos de datos con diferentes tipos de argumentos.

2.1. Archivo delimitado por espacio en blanco y con encabezado:
tabla.txt <- read.table("https://stats.idre.ucla.edu/wp-content/uploads/2016/02/test.txt", header=T)
tabla.txt
##    make   model mpg weight price
## 1   AMC Concord  22   2930  4099
## 2   AMC   Pacer  17   3350  4749
## 3   AMC  Spirit  22   2640  3799
## 4 Buick Century  20   3250  4816
## 5 Buick Electra  15   4080  7827
2.2. Archivo delimitado por comas y con encabezado:
tabla.csv <- read.table("https://stats.idre.ucla.edu/wp-content/uploads/2016/02/test-1.csv", header=T, sep=",")
tabla.csv
##    make   model mpg weight price
## 1   amc concord  22   2930  4099
## 2   amc   oacer  17   3350  4749
## 3   amc  spirit  22   2640  3799
## 4 buick century  20   3250  4816
## 5 buick electra  15   4080  7827

También se podría leer con la función read.csv , que fue escrita específicamente para este tipo de archivos.

tabla.csv1 <- read.csv("https://stats.idre.ucla.edu/wp-content/uploads/2016/02/test-1.csv", header=T, sep=",")
tabla.csv1
##    make   model mpg weight price
## 1   amc concord  22   2930  4099
## 2   amc   oacer  17   3350  4749
## 3   amc  spirit  22   2640  3799
## 4 buick century  20   3250  4816
## 5 buick electra  15   4080  7827
2.3. Archivo delimitado por punto y coma y con encabezado:

Por supuesto, también es posible utilizar la función read.table para leer archivos con otros delimitadores.

tabla.txt_pc <- read.table("https://stats.idre.ucla.edu/wp-content/uploads/2016/02/testsemicolon.txt", header=T, sep=";")
tabla.txt_pc
##    make   model mpg weight price
## 1   AMC Concord  22   2930  4099
## 2   AMC   Pacer  17   3350  4749
## 3   AMC  Spirit  22   2640  3799
## 4 Buick Century  20   3250  4816
## 5 Buick Electra  15   4080  7827
2.4. Archivo almacenado en formato xlsx:

La función write.table exporta archivos en el formato deseado.

write.table(tabla.csv1, "prueba.txt", row.names=F, quote=F)

Nombramos esta función en esta sección, ya que si tenemos algun archivo en un formato no deseado, podemos primero cambiar su extensión y luego leerlo.

write.table(tabla.csv1, "prueba1.xlsx")
2.5. Archivo almacenado en formato JSON:
library(rjson)

pob <- readLines("http://servicios.ine.es/wstempus/js/ES/DATOS_TABLA/2852?nult=5&tip=AM")
pob <- paste(pob, collapse = " ")
pob <- fromJSON(pob)
# pob

En la primera línea cargamos el paquete rjson . En las dos siguientes leemos la URL y colapsamos todas las líneas en una única cadena de texto, una exigencia de fromJSON.

2.6. Archivo almacenado en otras plataformas:

El paquete foreign contiene funciones que permiten importar datos de algunos de los software estadístico más utilizados, como: SAS, Stata, SPSS, Minitab, Weka, dBase y Systat.

library(foreign)
help(package=foreign)

Un ejemplo de un archivo con formato Stata.

tabla.stata <- read.dta("https://stats.idre.ucla.edu/stat/data/test.dta")
tabla.stata 
##    make   model mpg weight price
## 1   AMC Concord  22   2930  4099
## 2   AMC   Pacer  17   3350  4749
## 3   AMC  Spirit  22   2640  3799
## 4 Buick Century  20   3250  4816
## 5 Buick Electra  15   4080  7827

3. Importar archivos de datos no estructurados

Hay muchos datos en sitios web, pero no siempre existe la opción de descargarlos. web scraping es un proceso de extracción de datos no estructurados de sitios web en un formato estructurado.

El paquete rvest es un paquete creado para extraer información de páginas web. Está inspirado principalmente en la popular librería de Python, (beautiful soup).

Un ejemplo práctico, descargar las cotizaciones de “IBEX 35” en tiempo real.

library(rvest)
## Loading required package: xml2
url.ibex <- "http://www.bolsamadrid.es/esp/aspx/Mercados/Precios.aspx?indice=ESI100000000"
tmp <- read_html(url.ibex)
tmp <- html_nodes(tmp, "table")

La segunda línea descarga y preprocesa una página descargada de internet. El objeto tmp contiene una representación interna de la página. Una página web, en el fondo, no es otra cosa que un árbol del que penden nodos que son párrafos, imágenes, enlaces, tablas, etc. Sobre este árbol se pueden realizar distintos tipos de consultas, por ejemplo, extraer distintos tipos de nodos.

La función html_nodes captura los nodos que tienen determinadas características. En este ejemplo, como ocurre con mucha frecuencia, nos interesan los identificados como tablas (tables). De hecho, las tablas son tan interesantes que el paquete rvest proporciona una función auxiliar para convertir los nodos de tipo table en tablas de R: html_table .

En nuestro ejemplo, la página contiene varias tablas. Como consecuencia, tmp es una lista de nodos:

length(tmp)
## [1] 5

La página, aunque no lo parezca, tiene varias tablas. Eso se debe a que en HTML las tablas se utilizan en ocasiones, por abuso, no para almacenar datos tabulares sino para dar formato a las páginas. Sin embargo, es fácil detectar estas seudotablas por inspección. Para identificar la tabla de interés, la que contiene las cotizaciones, podemos examinarlas ejecutar:

sapply(tmp, function(x) dim(html_table(x, fill = TRUE)))
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   46    1    1    1   35
## [2,]  351    1    7    9    9

que nos indica que la quinta tabla tiene \(35\) filas, un indicio sólido de que es la que va a contener las cotizaciones de las \(35\) empresas del IBEX. Podemos entonces transformar este último nodo en una tabla de R:

ibex <- html_table(tmp[[5]])
# ibex

La información colgada en internet está pensada para ser consumida por humanos, no máquinas. Como consecuencia, los números están decorados con separadores de miles, unidades, porcentajes, etc.; los nombres de columnas tienen espacios y otros caracteres extraños, etc. Por eso, la información directamente descargada raramente se puede utilizar directamente: es necesario someterla aun proceso sencillo pero laborioso de limpieza.