Código
suppressPackageStartupMessages(library(tidyverse))
library(ggplot2)
library(readxl)
<- read_excel("datos/peck_odr.xls", skip = 2) pollos_peso
Miguel Equihua
Xalapa, Ver., 9 de julio, 2024
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.
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.
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
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?
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.
Attaching package: 'flextable'
The following object is masked from 'package:purrr':
compose
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(%)")
| Altura | Densidad | Frecuencia | Cobertura | Valor |
---|---|---|---|---|---|
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 |
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.
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:
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:
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.
{
"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.
# 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.
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
Ahora con la biblioteca ggplot2
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.