Acceso a Datos

datos
datos abiertos
API
Autor/a

Miguel Equihua

Fecha de publicación

Xalapa, Ver., 9 de julio, 2024

Datos en Mi equipo

Obviamente, la forma más sencilla de acceder a datos es cuando los tenemos en nuestro propio equipo. En este caso lo usual es que sea alguno de los formatos de Microsoft (Word o Excel) o algún formato genérico como los identificados como txt (texto plano) o csv (valores separados por comas). Puuede haber otras variantes de archivos de datos, como kml, GeoJson, GeoTIFF o shp (shape file) usuales en la gestión de datos geográficos. En Genómica está el formato fasta, que también cuenta con bibliotecas adecuadas en R. Hay una correspondiente variedad de recursos para leer todos estos tipos de datos en R así como para analizarlos y preparar resúmenes, modelos y gráficos de interés. A continuación veremos algunos ejemplos sencillos para tener una idea del proceso general.

Para nuestros fines didácticos ya hemos visto como podemos interactuar con documentos de tipo texto plano. Ahora quisiera que vieramos como leer datos de Excel y de Word.

Datos Excel

Tengo este archivo de datos obtenidos por D.L. Cunningham de la Universidad de Cornell. Son registros de masa corporal (g) de pollos de acuerdo con su posición en la jerarquía de picotazos. Veamos los datos.

Código
suppressPackageStartupMessages(library(tidyverse))
library(ggplot2)
library(readxl)
pollos_peso <- read_excel("datos/peck_odr.xls", skip = 2)

los datos están en un formato poco conveniente para un análisis general. Hagamos algunas operaciones para ponerlos en una forma más adecuada

Código
pollos_peso <- pollos_peso %>%
                 rename(jerarquia = `Jerarquía\npor picoteo`) %>% 
                 pivot_longer(cols = `Gallinero 1`:`Gallinero 7`, 
                              names_to = "gallinero",
                              values_to = "peso") %>% 
                 mutate(gallinero = factor(gallinero),
                        jerarquia = as.integer(jerarquia)) %>% 
                 arrange(gallinero)

ggplot(pollos_peso, aes(x = jerarquia, y = peso)) +
  geom_point(color = "orange")

¿qué análisis sugieres habría que hacer ahora?

Datos en word

Utilizo la bibliotec docxtractr para extraer las tablas contenidas en el documento Word (en versión docx). Hay que cargar el documento y luego extraer las tablas, una por una. Lo primero que recuperé es la tabla de Colonia Olmeca.

Código
library(flextable)

Attaching package: 'flextable'
The following object is masked from 'package:purrr':

    compose
Código
library(docxtractr)

docx <- list.files("datos/", pattern = "^A.*docx$", full.names = TRUE)
docx <- read_docx(docx)

# Olmeca
arboles <- docx_extract_tbl(docx = docx, tbl_number = 1, header = TRUE)

olmeca <- arboles %>% 
          assign_colnames(row = 1) %>% 
          mutate_at(2:6, as.numeric) %>% 
          filter(!row_number() %in% (length(arboles[[1]]) - 1))

nombre_vars <-c("sp", "alt", "dens_rel", "frec_rel", "cob_rel", "ivi") 
names(olmeca) <- nombre_vars

olmeca %>% 
  flextable() %>% 
  set_header_labels(sp = "\n\nEspecie", 
                    alt = "Altura\npromedio\n(m)",
                    dens_rel = "Densidad\nRelativa\n(%)",
                    frec_rel = "Frecuencia\nRelativa\n(%)",
                    cob_rel = "Cobertura\nRelativa\n(%)",
                    ivi = "Valor\nde Importancia\n(%)")



Especie

Altura
promedio
(m)

Densidad
Relativa
(%)

Frecuencia
Relativa
(%)

Cobertura
Relativa
(%)

Valor
de Importancia
(%)

Ocotea psychotrioides

4.53

35.19

12.68

5.86

53.73

Carpinus caroliniana

9.77

12.02

12.68

24.11

48.80

Quercus leiophylla

17.61

12.02

11.27

24.39

47.68

Quercus germana

22.58

5.15

11.27

17.98

34.40

Turpinia insignis

4.21

11.59

12.68

3.61

27.87

Beilschmiedia mexicana

5.17

6.01

8.45

2.92

17.38

Calyptranthes millspaughii

11.14

4.72

7.04

3.89

15.65

Liquidambar styraciflua var. mexicana

22.67

2.58

5.63

5.30

13.50

Mollinedia viridiflora

3.40

4.72

7.04

0.76

12.53

Zinowiewia integerrima

19.40

2.15

1.41

4.71

8.26

Quercus xalapensis

10.83

1.29

2.82

3.27

7.37

Annona cherimola

9.00

1.29

2.82

1.01

5.11

Clethra mexicana

20.00

0.43

1.41

0.98

2.82

Quercus corrugata

20.00

0.43

1.41

0.98

2.82

Citrus aurantifolia

4.00

0.43

1.41

0.23

2.07

Obtención de Datos Abiertos

Las fuentes de datos, especialmente hoy, pueden ser muy variadas. Desde los datos que conseguimos directamente en campo a partir de mediciones directas o encuestas, hasta los datos que podemos obtener de fuentes de datos abiertos. Considero que será de tu interés explorar las distintas formas de interacción que las fuentes de datos implican para nuestros procesos de producción científica reproducible.

Manejo de claves confidenciales

Un tema importante a cuidar es preservar la confidencialidad de claves, tokens y otras formas de identificación personal que puede implicar el proceso de acceso a datos en línea. Así que veremos eso como primer asunto. Queda claro que debemos evitar por todos los medios evitar poner esa información en carpetas o código que pueden acabar siendo registradas en Github en nuestro repositorio público. Haberte vacunado con usethis::git_vaccinate() ayuda en gran medida, pero desde luego no es remplazo a estar atentos a lo que estamos haciendo. La estrategia de registro de datos confidenciales que te propongo es la biblioteca keyring. Esta biblioteca accede al sistema de almacenamiento de credenciales de tu máquina desde R. La describen como una API Independiente de la Plataforma para acceder al depósito de credenciales del sistema operativo de tu máquina. Este sitio explica que es una API (Application Programming Interface). Actualmente keyring soporta: Keychain en macOS, Credential Store wn Windows, the Secret Service API en Linux, soluciones simples (sin plataforma específica) desarrollados con variables de sistema o archivos encristalados e incluso ofrece la posibilidad de desarrollar algunas soluciones propias con sencillez. En nuestro caso, básicamente usaremos dos funciones de esta biblioteca. Primero y desde la pantalla de Consola ejecuta:

key_set(service = "[dale un nombre]", username = "[el que desees]")


Esto hará el registro de tus credenciales en tu máquina, fuera de la vista. A partir de ese momento y mientras no elimines el registro explícitamente, estarán disponibles los datos que hayas registrado y los podrás obtener con:

key_get(service = "[dale un nombre]", username = "[el que desees]")


Esta última línea recupera los datos confidenciales, así que deberás cuidar usar las credenciales de inmediato y procurar no guardarlas y menos desplegarlas o habilitar medios para mostrarlas, durante el proceso.

Veamos un primer ejemplo con INEGI. Te sugiero ir a https://www.inegi.org.mx/servicios/api_indicadores.html al constructor de consultas, en donde INEGI nos muestra un ejemplo de como acceder a los datos abiertos que compilan, mantienen y custodian. Deberás obtener un token personal, el mismo sitio de INEGI te dirá como obtenerlo. El ejemplo muestra como obtener datos de la serie histórica del indicador de la Población total de los Estados Unidos Mexicanos, en idioma español, en formato JSON. Una vez que los obtengamos mostraremos los datos en tablas y gráficas.

Lo primero que haremos es preparar el acceso a los datos con el token confidencial y obtenemos los datos, sin haber registrado la URL de acceso, pues como viste arriba, incluye tu token, así que habrá que manejarla con seguridad. El resultado de este código es una estruuctra de datos que ya no contiene información confidencial.

La siguiente tarea que haremos ahora es simplemente arreglar los datos y ponerlos de la manera que requiero. Los datos son actualmente una base de datos JSON, que es una estructura parecida a un diccionario jerárquico, que tiene una etiqueta seguida de los datos que le corresponden. Aquí te muestro un fragmento de los datos de INEGI que obtuvimos. Es la sección etiquetada como Header. Podemos ver que esta etiqueta tiene como contenido los datos Name y email, a su vez con sus respectivos datos.

Código
descrip <- fromJSON(datosGenerales[[1]])$Header
prettify(toJSON(descrip))
{
    "Name": "Datos compactos BISE",
    "Email": "atencion.usuarios@inegi.org.mx"
}
 


Ahora haremos algunas operaciones para arreglar los datos del JSON en una tabla de tipo data.frame (tibble si optamos por una variante actual) en R. Los datos que nos interesan son los que están en la etiqueta Series y dentro de estas Series están las listas de OBSERVATIONS, que en este caso son 15.

Código
# junta todo en un gran texto corrido
flujoDatos <- paste(datosGenerales, collapse = " ") 

# Obtiene la lista de observaciones 
flujoDatos <- fromJSON(flujoDatos) # Convierte al JSON a una lista de R
flujoDatos <- flujoDatos$Series # Toma la sublista Series 
flujoDatos <- flujoDatos[[1]]["OBSERVATIONS"]

cat("\nNúmero de observaciones: ", length(flujoDatos[[1]]),
    "\n\nDatos en cada observación:\n",
    paste("   ", names(flujoDatos[[1]][[1]]), collapse = "\n"), sep = "")

Número de observaciones: 15

Datos en cada observación:
    TIME_PERIOD
    OBS_VALUE
    OBS_EXCEPTION
    OBS_STATUS
    OBS_SOURCE
    OBS_NOTE
    COBER_GEO

Ahora convierto lista de listas en un tabla con los datos de población y año de censado.

Código
df1 <- flujoDatos[[1]] %>% 
      sapply(., c) %>% 
      t() %>% 
      as_tibble() %>% 
      select(TIME_PERIOD, OBS_VALUE) %>% 
      mutate(TIME_PERIOD = as.integer(TIME_PERIOD),
             OBS_VALUE = as.integer(OBS_VALUE))


df1 %>% flextable() %>% 
        colformat_int(j = 1, big.mark = "") %>% 
        set_header_labels(TIME_PERIOD = "Año", OBS_VALUE = "Población")

Año

Población

1910

15,160,369

1921

14,334,780

1930

16,552,722

1940

19,653,552

1950

25,791,017

1960

34,923,129

1970

48,225,238

1980

66,846,833

1990

81,249,645

1995

91,158,290

2000

97,483,412

2005

103,263,388

2010

112,336,538

2015

119,938,473

2020

126,014,024

Ahora podemos ver los datos como una gráfica

Código
plot(df1, type = "b")

Ahora con la biblioteca ggplot2

Código
library(ggplot2)

ggplot(df1, aes(x = TIME_PERIOD, y = OBS_VALUE / 1000000)) +
  geom_point(color = "red", size = 3, show.legend = FALSE) +
  geom_line(color = "blue", show.legend = FALSE) +
  ylab("Población (millones de habitantes)") +
  xlab("Año")

Contar historias con números

Esta es una tarea usualmente complicada. A lo mejor la lectura de lo que propone Stephen Few, nos puede ayudar a profundizar esta reflexión.