library(tidyverse) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", out.width = "100%" ) set.seed(0)
El paquete se puede instalar desde GitHub:
# install.packages("devtools") devtools::install_github("jumanbar/siabox", build_vignettes = TRUE)
Nota: se puede instalar con la opción
build_vignettes = FALSE
, pero en ese caso no tendrá acceso a las viñetas, que son parte importante de la documentación. De todas formas, puede ver las viñetas en formato markdown, en la carpeta vignettes
Ver actualizaciones: log.md
Se trata de un paquete pensado para trabajar con datos del SIA, especialmente en realizar gráficos, tablas e informes, usando datos incluidos en el mismo, o descargados desde iSIA.
Incluye varias tablas (data.frames) con datos tomados directamente del SIA, que sirven para correr ejemplos. En principio, si estos ejemplos funcionan en los datos contenidos en el paquete, también lo harán con datos nuevos del SIA y, por lo tanto, servirán para confeccionar informes automatizados.
Para usar el paquete se recomienda el uso de tidyverse en general (algunos esos paquetes son necesarios, de hecho). Además, los ejemplos mostrados aquí y en las distintas viñetas, usan funciones de tidyverse
extensivamente.
En este documento se muestra lo básico del paquete. Se recomienda visitar las viñetas para profundizar:
vignette('graficos', package = 'siabox') vignette('datos-incluidos', package = 'siabox')
La idea es que el paquete trabaje en conjunto con la aplicación iSIA. En la práctica, el flujo puede tomar dos caminos:
Se puede trabajar con datos extraidos de la aplicación iSIA en el momento.
Se pueden usar datos que ya están en el paquete para analizar o hacer pruebas. El código así generado luego se puede utilizar para datos descargados desde iSIA.
Uno de los objetivos más importantes es que las herramientas del paquete sirvan para elaborar informes automatizados, mediante Rmarkdown. Hay un ejemplo (en construcción) con datos del programa Laguna Merín para tomar de referencia:
siabox::demo_lm() # HTML siabox::demo_lm('pdf') # PDF siabox::demo_lm('doc') # DOC
Nota: si no funciona el ejemplo, siempre se pueden acceder a los archivos del repositorio, en la carpeta inst/examples
El siguiente es un ejemplo que usa datos extraídos de iSIA (formato 'largo'):
Una vez que descargamos el archivo desde iSIA, que se podría llamar, por ejemplo extraccion_20210630.rds
, la forma de importarlos es con la función readRDS
de R:
d <- readRDS("extraccion_20210630.rds")
Afortunadamente, no es necesario descargar estos datos en particular, ya que se encuentran en el paquete mismo. Vamos a crear una data.frame llamada d
, usando la función filtrar_datos
, que simula los filtros de iSIA:
library(tidyverse) library(siabox) d <- filtrar_datos(datos_sia, id_programa = 10L, id_matriz = 6L, rango_fechas = c('2019-01-01', '2019-12-31'), tipo_punto_id = 1L, # 1 = Superficie; 2 = Fondo id_parametro = c(2098, 2101, 2099, 2097, 2102, 2032, 2018, 2090, 2021, 2017))
Se puede, por ejemplo, crear un gráfico de IET como el siguiente:
d %>% iet_tabla() %>% g_iet_pto()
Nota: estos datos fueron extraídos en noviembre de 2020, por lo que cualquier corrección o inclusión de datos que se haya hecho desde esa fecha hasta hoy, estarán ausentes.
En este caso se están usando las funciones iet_tabla
y g_iet_pto
del paquete. Aquí no se muestra, pero el paquete incluye una tercer función relacionada: iet
.
Hay otros cálculos frecuentes que ya están incluidos en el paquete. Uno de ellos es el del Amoníaco Libre. Para una tabla de datos como la mencionada, la función amoniaco_libre_add
permite agregar al parámetro NH3L (siempre y cuando hayan datos de T, pH y NH4):
# Agregar NH3L: d <- amoniaco_libre_add(d) # Se pueden ver algunos valores aquí: d %>% filter(id_parametro == 2091) %>% select(codigo_pto, fecha_muestra, param, valor) # Gráficos de nutrientes: g_mes_pto_all(d, id_parametro = c(2098, 2101, 2099, 2097, 2102, 2091), ncol = 3)
Para ver detalles del cálculo en sí, ver
?amoniaco_libre
.Las etiquetas del gráfico se pueden mejorar aún con la función
t_eti_add
(ver viñeta 'gráficos').
El paquete cuenta con otras funciones listas para crear gráficos de informes: ver ?g_mes_pto
o ?g_lon_pto
para más ejemplos, pero se recomienda especialmente leer la viñeta 'graficos':
vignette('graficos', package = 'siabox')
El paquete viene con dos conjuntos de datos extraídos del SIA: ver ?datos_sia
o ?datos_sia_sed
para acceder a la documentación de estas tablas, con datos de aguas superficiales y de sedimentos, respectivamente.
Dichas tablas tienen todos los datos encontrados en SIA, a la fecha en que fueron extraidos, para todos los programas y parámetros disponibles. El objetivo de estas tablas es el de hacer pruebas, ejemplos y código que luego se puede aplicar a datos más actualizados (extraídos con iSIA).
Dado que se trata de tablas de gran tamaño (datos_sia
tiene r nrow(datos_sia)
filas y r ncol(datos_sia)
columnas), es conveniente filtrarlos según el subconjunto de interés. Para esto es que el paquete cuenta con la función filtrar_datos
, que replica las funcionalidades de filtro de iSIA, como ya se mencionó.
El siguiente es un ejemplo datos similares al ejemplo usado anteriormente (la diferencia es el rango de fechas):
d <- filtrar_datos(datos_sia, id_programa = 10L, id_matriz = 6L, rango_fechas = c('2015-01-01', '2019-12-31'), tipo_punto_id = 1L, id_parametro = c(2098, 2101, 2099, 2097, 2102, 2032, 2018, 2090, 2021, 2017)) g_lon_pto(d, 2098, anio = 2019)
La idea de replicar la funcionalidad de iSIA es de poder hacer pruebas antes de descargar datos, incluso pensando en la automatización de reportes.
Para profundizar sobre los contenidos y usos de los datos incluidos en el paquete, se recomienda visitar la viñeta datos-incluidos
:
vignette('datos-incluidos', package = 'siabox')
El paquete cuenta con algunas funciones relativamente simples que son de ayuda para realizar cálculos frecuentes: iet
, iet_tabla
, amoniaco_libre
, amoniaco_libre_add
, media_geom
, raiz
y tsummary
.
La función iet
calcula el IET para valores de Fósforo Total (en microgramos por litro):
iet(c(25, 50, 75, 250)) PT <- seq(0, 300, by=5) plot(PT, iet(PT), ylab = "IET", xlab = "PT (ug/L)", pch = 20)
Agrupa valores de IET por estación de monitoreo (codigo_pto
), asignando categorías a los valores según su IET (Oligotrófico, Mesotrófico, etc...). Usa la media geométrica para agrupar los valores encontrados.
d <- filtrar_datos(datos_sia, id_programa = 10L, id_matriz = 6L, rango_fechas = c('2019-01-01', '2019-12-31'), tipo_punto_id = 1L, id_parametro = 2098) iet_tabla(d)
La función puede, además, agrupar por otras columnas, como por ejemplo, mes, año, etc...
d <- filtrar_datos(datos_sia, id_programa = 10L, id_matriz = 6L, rango_fechas = c('2017-01-01', '2019-12-31'), tipo_punto_id = 1L, id_parametro = 2098)
IET x Estación x Mes:
iet_tabla(d, mes)
IET x Estación x Año x Mes:
iet_tabla(d, anio, mes)
Esta función se puede combinar con herramientas de dplyr fácilmente (en el ejemplo también se usa tsummary
, de siabox):
iet_tabla(d, anio) %>% group_by(anio, categ) %>% tsummary(IET)
La función tsummary
, usada en el ejemplo anterior, es una ayuda para obtener cálculos similares a los de summary
, que permite agrupar según distintas variables (i.e.: columnas). Hay que tener en cuenta que sólamente puede hacer cálculos con variables numéricas.
Uso de tsummary para resumir datos de Clorofila-A en el programa Río Cuareim:
datos_sia %>% filter(param == 'Clo_a', id_programa == 5) %>% tsummary(valor)
Lo mismo, pero agrupando por estación de monitoreo:
datos_sia %>% filter(id_parametro == 2000, id_programa == 5) %>% group_by(codigo_pto) %>% tsummary(valor)
Notas: el primer ejemplo y el segundo difieren en 2 aspectos:
el agrupamiento (con la función
group_by
, de dplyr) yse filtra parámetro por nombre y luego por id (id_parametro).
Parámetros y otras categorías importantes (programas, estaciones, unidades, ...), tienen varias formas de ser identificados, siendo id la única permanente.
Otra función incluida en el paquete es raiz
, que calcula la raíz enésima de un valor dado, incluso cuando ese valor es negativo (en cuyo caso, n debe ser impar). La misma es usada, a su vez, por media_geom
(la Media Geométrica).
Cálculo de la raíz enésima:
tibble(x = c(4, -4, 4, -4), n = c(2, 2, 3, 3)) %>% mutate(raiz(x, n), x ^ (1 / n), abs(x) ^ (1 / n))
Cálculo de una media geométrica, usando valores aleatorios:
x <- rnorm(100, 8) mean(x) media_geom(x)
Al momento del lanzamiento de este paquete, el universo de funciones será limitado, naturalmente. Por esta razón es de interés considerar posibles aportes de usaries a la construcción del mismo.
Para esto hay que tener en cuenta que todo lo que se incorpore al paquete será en forma de tablas o funciones: código que sirva para un rango de situaciones.
Para aportar esta construcción, pueden haber infinidad de formas, desde comentarios sobre problemas, mejoras, etc, hasta aportes de código original. En este último caso me quiero concentrar. En principio se pueden imaginar dos formas 'extremas':
Aportes de código 'suelto', que debe ser convertido en una función, con todo lo que ello implica, e incorporada al paquete.
Aportes de funciones listas para incluir en el paquete, sin más que agregar.
El segundo caso es un ideal, seguramente poco realista, aunque deseable. A continuación paso a describir algunas posibles formas de contribuir, que estarían entre estos extremos.
Este caso sería simplemente enviando código que creado para hacer una gráfica o tabla, por ejemplo. Hay algunos detalles a tener en cuenta:
En primer lugar, el contexto. Para qué se utilizaría? En qué situaciones? Es para algún programa de monitoreo en particular? Etc. Es deseable que estas cosas se expresen con la mayor claridad posible.
También es importante estar atento a que lo enviado sea suficiente para tener un ejemplo mínimo reproducible, lo cual suele implicar datos, código, etc. En otras palabras: todo lo necesario para que otra persona pueda obtener exactamente el mismo resultado.
No solamente el código ejecutable aporta, sino que mejoras a la documentación siempre son bienvenidas. Esto puede ser con sugerencias a lás páginas de ayuda de las funciones o datos, sugerencias o texto para incluir en el README.Rmd del paquete (el documento que está leyendo en este momento), o incluso en las viñetas y ejemplos de informes automatizados.
Las funciones implican un incremento de abstracción en relación a lo que es el código suelto. Y además requiere pensar situaciones diferentes a las que llevaron a la creación del código original. Esto puede ser complejo, especialmente si se trata de creación de gráficos, aunque no necesariamente dificil.
Algunas preguntas importantes a tener en cuenta son:
Cuáles son los casos 'normales' de uso?
Cuáles son casos no contemplados y que deberían quedar explícitamente afuera del uso normal?
Cómo contempla la función el cambio de un parámetro, por ejemplo? (o la matriz, o el programa de monitoreo...)
Relativo a la anterior, se toman en cuenta cambios indirectos, como pueden ser las unidades de medida?
Si el gráfico incluye estaciones de monitoreo, las toma de una lista hecha a mano o las extrae de la tabla con los datos?
La misma idea que la pregunta anterior aplica a otras categorías, como departamentos, cuencas, etc...
Pueden ser muy importantes aportes para mejorar las funciones incluidas en el paquete. Para esto será necesario acceder al cuerpo de la función (i.e.: el ćodigo que tiene adentro) y crear un ambiente de desarrollo (es decir: reproducir todos los objetos que existen al momento en que se ejecuta la función, de forma que se puedan hacer pruebas y experimentos).
Para obtener el código de una función, se puede simplemente escibir el nombre de la función en la consola (sin paréntesis al final!) y dar enter:
iet
Otra opción es usar edit
:
edit(iet)
Incluso se puede ir directametne al código en el repositorio de Github (subcarpeta 'R'): https://github.com/jumanbar/siabox/blob/master/R/informes.R
Para lograr un ambiente de desarrollo, usualmente es necesario tener definidos objetos con los nombres de los argumentos, en nuestro espacio de trabajo. En el caso de iet
hay un único argumento, PT
, entonces con definir un vector numérico alcanza:
PT <- c(23, 44, 2.5) # Esta línea es equivalente a todo el cuerpo de la función: 10 * (6 - (0.42 - 0.36 * log(PT)) / log(2)) - 20
Generalmente las funciones que nos interesará modificar son mucho más complejas (mirar g_mes_pto
o g_lon_pto
por ejemplo). Al método de crear objetos con los nombres de los argumentos, que funciona perfectamente, se suman alternativas como debug
:
debug(g_lon_pto) g_lon_pto(d, 2098)
El uso de debug
es una opción bastante práctica y poderosa, pero no es recomendable si no se conoce el procedimiento! (siepre se puede aprender; dejamos aquí un video instructivo)
Este caso aplica para les desarrolladores más avanzados. Algunas consideraciones importantes:
require
o library
. Usar en cambio los operadores ::
o :::
.Ejemplo: dplyr::filter
. Eso evita afectar el ambiente de trabajo del usuario final (o sea, no hay que cargar todo el paquete siabox
para usar una única función; tsummary
es un ejemplo de función útil en sí misma). En este paquete las excepciones son ggplot2
y %>%
, ya que de otra forma el código se vuelve muy engorroso rápidamente.
En el caso de tablas internas de siabox
, es preciso usar ::
. Por ejemplo, la tabla sia_parametro
es llamada siempre así: siabox::sia_parametro
(por ejemplo, ver el codigo de unipar
).
La documentación es fundamental. El paquete roxygen2
facilita muchísimo esta tarea. En RStudio, el comando "Insert Roxygen Skeleton" (Ctrl+Alt+Shift+R) hace el camino más llano aún.
Es parte de la documentación, pero merece un lugar aparte: crear ejemplos que funcionen e ilustren el rango de funcionalidades, es siempre un gran aporte y facilita mucho al aprendizaje de les usuaries.
En un principio, recibiré contribuciones, críticas y comentarios al correo: juan.manuel.barreneche@ambiente.gub.uy. En principio es posible también usar Github para hacer aportes directamente desde allí, en el repositorio del paquete: https://github.com/jumanbar/siabox
(Sección que, al menos en parte, escribo para refrescar mi propia memoria.)
Este paquete se creó siguiendo de forma aproximada los consejos del libro R Packages de Hadley Wickham. El libro entero es importante para entender el desarrollo de paquetes (o la documentación original de CRAN), pero para referencia rápida de quien ya sabe la teoría y sólo tiene que recordar el flujo, ir directamente al capítulo 5: Fundamental development workflows.
Algunas notas:
Lo mismo para trabajar con los conjuntos de datos del paquete... Sucede que las funciones del paquete tienen asociado un NAMESPACE, así que cuando se llama a una función de siabox
desde el cuerpo de otra función de siabox
, se sobreentiende que el NAMESPACE del paquete está incluido en el camino de búsqueda de funciones. Pero esto no ocurre con los datasets (supongo que los creadores de R nunca lo consideraron necesario). Por esta razón, siempre que se, por ejemplo, sia_parametro
dentro de una función de siabox
, hay que escribir siabox::sia_parametro
.
La función devtools::load_all()
(Ctrl+Shift+L) sirve para "cargar" el paquete en la sesión, incluyendo funciones, viñetas, y otros códigos. Conviene correrlo cada vez que cambiamos alguna función y queremos probarla, por ejemplo.
La función devtools::document()
(Ctrl+Shift+D) sirve para actualizar los archivos de documentación.
Las viñetas compiladas no se incluyen en el repositorio github, ya que "doc" figura en el .gitignore
. La idea es instalar con archivo bundle o con la opción build_vignettes = TRUE
de devtools::install_github
, para que estén disponibles.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.