class: center, middle, inverse, title-slide .title[ # Creando paquetes de R/Bioconductor para análisis transcriptómicos de célula única ] .author[ ### Andrés Arredondo Cruz
09 de agosto de 2023 ] --- class: center, middle # Documentación de funciones --- class: chapter-slide, center, middle ## ¿Que es la documentación en una función de R? ¿Por qué es importante? --- ## La documentación es un archivo de ayuda para el usuario 1. 🙇️ Es la información complementaria que el desarrollador escribe sobre una función y que se accede con `?` seguido el nombre de una función actual de un paquete p.ej. `?unafuncion`. 2. 📁 La documentación se almacena como un archivo .Rd ("R documentation) en la carpeta `man/`. 3. 🔎 La documentación usa una síntesis especial, que es distinta a la de r y que esta ligeramente basada en LaTeX 4. 📄 Se puede renderizar como html, pdf o texto sin formato según se necesite. --- ## Construyendo la documentación con ayuda de roxygen + ❌️En un paquete de r no editamos un documento `.Rd` manualmente. + 🙇Los archivos *.Rd* una síntesis parecida a LaTeX que puede ser fácil de estropear. + ⭐Usar roxygen nos permite usar comentarios especiales sobre el inicio de la función, esto nos da un par de ventajas: 1. ✅ La documentación y la función estarán en un mismo lugar, por lo que si editas la función será mas fácil recordar actualizar la documentación también. 2. 🎉 Puedes usar markdown en lugar de la síntesis especial para los archivos `.Rd`. --- ## Antes de empezar...✏️ Vamos a crear un función para nuestro paquete. Supongamos que para nuestro paquete necesitamos una función que calcule la moda. Esta es una forma sencilla de calcular la moda: ```r getmode <- function(serievector) { uniqv <- unique(serievector) uniqv[which.max(tabulate(match(serievector, uniqv)))] } ``` --- ## Explicacion de la función getmode() + `unique(serievector)`: Crea un vector que contiene únicamente los valores únicos de la serie de números serievector. + `match(serievector, uniqv)`: Encuentra la posición de cada valor de serievector en el vector único uniqv. + `tabulate(match(serievector, uniqv))`: Cuenta cuántas veces aparece cada valor en la serie serievector. + `which.max(tabulate(match(serievector, uniqv)))`: Encuentra el índice del valor máximo en el vector de frecuencias. + `uniqv[which.max(tabulate(match(serievector, uniqv)))]`: Devuelve el valor correspondiente al índice calculado, que es la moda. --- ## Creamos un ejemplo para ver que funcione: ```r serie_numeros <- c(1, 2, 2, 2, 2, 3, 3, 4, 4, 4) resultado <- getmode(serie_numeros) print(resultado) ``` ``` ## [1] 2 ``` Bien ahora si podemos podemos empezar a usar el paquete de roxygen para documentar nuestra función.. comencemos. --- class: chapter-slide, center, middle ## Bien ahora si podemos podemos empezar a usar el paquete de roxygen para documentar nuestra función.. comencemos. --- ### Comentarios de documentación del paquete roxygen. Insertamos un esqueleto de comentarios de roxygen para ver su síntesis. Colocamos el cursor en algún lugar de la definición de nuestra función y buscamos en la pestaña *Código > Insertar Roxygen Skeleton**. ```r #' Title #' #' @param serievector #' #' @return #' @export #' #' @examples ``` --- ## Los bloques de comentarios roxygen empiezan con un **#'** Ahora ya tenemos un esqueleto de la documentación que nos da una ventaja para su creación 🎉. Las líneas de comentarios de Roxygen siempre comienzan con el habitual **#** mas un **'**. ### Veamos los comentarios de uno por uno: --- ## El Titulo de la función Empezamos con el titulo. Se sugiere poner en el titulo las acciones principales que realiza la función, en este caso podemos usar __@title__: ```r #' @title Encontrar la Moda de una Serie de Números #' #' @param serievector #' #' @return #' @export #' #' @examples ``` --- ## La Descripción de la función El siguiente comentario que podemos ver es `@param`. Pero antes, vamos a añadir una pequeña descripción de la función y como usarla. Primero añadimos la pequeña descripción con **@description**: ```r #' @title Encontrar la Moda de una Serie de Números. #' #' @description Esta función lee una serie de números en forma #' de vector y encuentra el elemento que mas se repite, es #' decir la moda. #' @param serievector #' @return #' @export #' @examples ``` --- ## El uso de la función Ahora vamos a añadir el comentario **@usage** que nos indica como puedes mandar a llamar la función. ```r #' @title Encontrar la Moda de una Serie de Números #' #' @description Esta función lee una serie de números en forma de vector y #' encuentra el elemento que mas se repite, es decir la moda. #' @usage getmode(serievector) #' @param serievector #' @return #' @export #' @examples ``` --- ## Los argumentos de la función Ahora si vamos a añadir una pequeña descripción de nuestros argumentos. Si tuviéramos mas de un parámetro en nuestra función podríamos llamar las veces que sea necesario el comentario de parámetro con **@param**: ```r #' @title Encontrar la Moda de una Serie de Números #' #' @description Esta función lee una serie de números en forma de vector y encuentra el elemento que mas se repite, es decir la moda. #' @usage getmode(serievector) #' #' @param serievector Es una serie de números en forma #' de un vector simple de r. #' @return #' @export #' @examples ``` --- ## Los detalles de la función Después, podemos añadir un comentario de detalles de la función con **@details**. Por ejemplo, si en nuestro ejemplo tuviéramos ciertos valores no numéricos en nuestro vector de entrada, por ejemplo letras, ¿nuestra función podría leerlas?, o si le diéramos un vector sin caracteres ¿que pasaría?, veamos: ```r serie_numeros <- c(0,2,2,"d", "d","d") resultado <- getmode(serie_numeros) print(resultado) ``` ``` ## [1] "d" ``` --- ```r serie_numeros <- c() resultado <- getmode(serie_numeros) print(resultado) ``` ``` ## NULL ``` Entonces, esto es un ejemplo de lo que podríamos poner en **@details**. Hagámoslo describiendo esto. --- ## Los detalles de la función En esta parte podemos agregar detalles un poco mas específicos que en la descripción de la función. ```r #' @title Encontrar la Moda de una Serie de Números #' @description Esta función lee una serie de números en forma de vector y encuentra el elemento que mas se repite, es decir la moda. #' @param serievector Es una serie de números en forma de un vector simple de r. #' #' @details si tu vector de entrada puede ser interpretado alternando números y #' letras escritas entre comillas "". Si un vector esta vacío, dará como #' resultado un NULL. #' @return #' @export #' @examples ``` --- class: chapter-slide, center, middle ## Ya casi terminamos de llenar nuestra documentación, pero antes vamos a ver algunos otros comentarios que pudieran ser importantes. --- ## Importar funciones de otros paquetes 📥 Podemos importar funciones de otros paquetes en caso de que las necesitemos con los siguientes : 1. **@import** importa todas las funciones del paquete que solicites 2. **@importfrom** importa solo algunas funciones especificas. En nuestra función no necesitamos llamar funciones de otros paquetes puesto que todas las que usamos están en r base, pero imaginemos una situación en la que sí... --- ## Un ejemplo de importar funciones de otros paquetes 💭 Imaginemos que tu función, por ejemplo necesita leer un archivo _.tsv_ con la función _read_tsv_ del paquete readr y después reconvertir la tabla resultante en un archivo con _write.table_ pero solo necesitas esa función del paquete _utils_, entonces haríamos: ```r #' @title Encontrar la Moda de una Serie de Números #' @description Esta función lee una serie de números en forma de vector y encuentra el elemento que mas se repite, es decir la moda. #' @param serievector Es una serie de números en forma de un vector simple de r. #' @details si tu vector de entrada puede ser interpretado alternando números y #' letras escritas entre comillas "". Si un vector esta vacío, dará como resultado un NULL. #' #' @import readr #' @importFrom utils write.table ``` --- ## Importar funciones 🆗 Así podemos importar las funciones que necesitemos de otros paquetes y se incluirán en la documentación y se cargaran automáticamente al cargar tu paquete. ✔️ Para un correcto funcionamiento de tu paquete y al estar los paquetes necesarios incluidos en la documentación, no será necesario llamarlos de la forma "**library(apackage)**". --- ## Resultado de la función 👉 Llegamos a la sección **@return**, esta descripción le servirá al usuario del paquete para conocer cual sera el resultado de la función, que puede ser un archivo, una tabla, un numero, etc. Entonces retomando la función **getmode()** escribimos su resultado: ```r #' @title Encontrar la Moda de una Serie de Números #' @description Esta función lee una serie de números en forma de vector y encuentra el elemento que mas se repite, es decir la moda. #' @param serievector Es una serie de números en forma de un vector simple de r. #' @details si tu vector de entrada puede ser interpretado alternando números y letras escritas entre comillas "". Si un vector esta vacío, dará como resultado un NULL. #' #' @return El carácter con mas frecuencia de el vector de entrada. #' @export #' @examples ``` --- ## @Exportar la función a un archivo de ayuda de R ☑️ Por ultimo tenemos **@export** que es el encargado de convertir la documentación a un archivo pueda aparecer en la ventana de Ayuda (abajo a la derecha). Esta opción la dejamos para funciones principales que el usuario va a utilizar. 🚫 En el caso de que existan funciones internas que no nos interesa que el usuario vea, vamos a usar la opción **@noRd** para no crear el archivo de ayuda. --- ## Ejemplos ilustrativos Antes de terminar podemos incluir ejemplos de como funciona nuestra función para un mejor entendimiento, pongamos los que ya realizamos: ```r #' @title Encontrar la Moda de una Serie de Números #' @description Esta función lee una serie de números en forma de vector y encuentra el elemento que mas se repite, es decir la moda. #' @param serievector Es una serie de números en forma de un vector simple de r. #' @details si tu vector de entrada puede ser interpretado alternando números y letras escritas entre comillas "". Si un vector esta vacío, dará como resultado un NULL. #' @return El carácter con mas frecuencia de el vector de entrada. #' @export #' #' @examples #' serie_números <- c(1, 2, 2, 2, 2, 3, 3, 4, 4, 4) #' resultado <- getmode(serie_números) #' print(resultado) ``` --- ## Cargar las funciones del paquete 🕙 Ahora si, una vez teniendo listo el bloque de comentarios para la documentación, vamos a ejecutar **devtools::load_all()** para cargar nuestras funciones. --- ✅ y hecho esto, ejecutamos **devtools::document()** o presionamos *Ctrl/Cmd + Shift + D* para convertir los comentarios en archivo *.Rd* y poder renderizarlo. --- class: chapter-slide, center, middle 💯 Listo,tenemos nuestra documentación para una función. Así se verá cuando el paquete esté terminado. --- ## Otros campos de la documentación. + **@seealso** para indicar funciones relacionadas y facilitar la búsqueda de funciones. + **@references** añade algunas referencias. + **@author** para especificar el autor de la función. --- .pull-left[<br><br><br><br><br><br><br> .center[ # ¡Gracias! ] ] .pull-right[<br> <img src="data:image/png;base64,#css/xolo.png" width="80%" style="display: block; margin: auto;" /> ]