10  Empaquetando funciones

10.1 Objetivos de aprendizaje

  • Identificar cuándo y por qué crear un paquete R.
  • Conocer y utilizar los paquetes R devtools y usethis para automatizar y agilizar muchas de las tareas de desarrollo de paquetes.
  • Aprende a crear un nuevo paquete R utilizando usethis::create_package().
  • Describir y explicar la finalidad de las carpetas y archivos de un paquete de R.
  • Aprender cómo y por qué puedes añadir datos a un paquete de R.

10.2 ¿Por qué crear un paquete R?

El objetivo principal del desarrollo de software es simplificar alguna tarea o un conjunto de tareas para vos y para los demás (como tu equipo, u otras personas que usen tu trabajo). Esto también se aplica al desarrollo de software en R. Crear un paquete R es una de las formas más potentes de simplificar tareas, independientemente de lo sencillas o complejas que sean.

A lo largo de esta sección mostraremos que crear y desarrollar un programa R no es tan difícil como parece a primera vista. Pero antes de hacer un paquete, tenes que definir algunas cosas. Por ejemplo, ¿cómo determinar si tiene sentido hacer un paquete R? Respondé a las siguientes preguntas:

  • ¿Creaste alguna vez una función, por sencilla que sea?
  • ¿Utilizaste esa función más de una vez en más de un proyecto o archivo, ya sea copiándola y pegándola o utilizando el archivo que que la contiene?

Si respondiste afirmativamente a estas dos preguntas, entonces deberías crear un paquete R para esa función. Pero puede que te preguntes, ¿por qué hacer un paquete con una sola función? Porque nunca se acaba con sólo una función, es muy probable sumes otras a tu trabajo. Aparte de empaquetar las funciones de R, si tienes conjuntos de datos pequeños o medianos que utilizas en varios proyectos o archivos, puedes incluso empaquetar los datos.

Además, hacer un paquete de R ahora es mucho más fácil que en el pasado. Esto se debe en gran parte a otros paquetes de R como devtools y usethis que están diseñados para simplificar el desarrollo de paquetes. A esto se suman recursos gratuitos como libros y blogs y páginas en Internet para aprender a crear paquetes R y hacer desarrollo de software en R.

Crear un paquete R y publicarlo en GitHub o en CRAN como parate de trabajo científico, un proyecto o análisis ayuda a su reproducibilidad. Esto se debe a que hacer un paquete de R suele requerir un mayor nivel de rigor, tests, documentación y inspección del código, lo que significa que tú y los demás podrán confiar más en en los resultados. Y si está en GitHub, es mucho más fácil compartir tu trabajo. con otras pesonas y lo lograr que tu trabajo tenga mayor impacto en general.

10.3 ¿Qué es un paquete R?

Para entender qué es un paquete R, daremos un paso atrás y consideraremos lo que ocurre cuando interactuamos con R. El primer acercamiento a R es a través de la consola, donde escribís funciones en R para realizar tareas que que se imprimen en pantalla. Si no cambiaste la configuración inicial esa sesión de R correrar en tu carpeta raiz, normalmente algo parecido a /home/username/ en Linux, /Users/username/ para macOS, o C:\Users\username para Windows. Así que cualquier dato o gráfico que guardes o importes debe incluir la ruta del archivo a la ubicación correcta. Desde un punto de vista reproducible y modular esto va en contra de las buenas prácticas. Asimismo, el código de R qeu escribas en la consola no se guarda en ningún lado. Por tanto, no podés reutilizarlo o compartirlo fácilmente.

El siguiente nivel es guardar el código en un scriptde R (un archivo almacenado en cualquier lugar en el ordenador que termina en .R) y hacer que R ejecute este código en secuencia. En el pasado, la gente podía escribir scripts de R en editores de texto como vim, emacs o Notepad, y ejecutar manualmente el script en la consola de R. En la actualidad, la mayoría de la gente utiliza un Entorno de Desarrollo Integrado (IDE) como RStudio o VS Code. Este es el método más utilizado para realizar cualquier tipo de trabajo en R. Teóricamente, el código escrito de esta forma es reproducible y se puede compartir. Sin embargo, en la práctica, las personas escriben código de manera secuencial, resolviendo un problema luego del otro y trabajan con R de forma más interactiva que programáticamente. El directorio de trabajo de un script R en este caso no está definido, por lo que seguimos encontrando problemas similares a los que tenemos al usar la consola. Si bien se puede almacenar código o funciones de R en un script y cargarlas con source() desde otros scripts, esto implica hacer un seguimiento de los archivos con estas funciones y actualizarlos cuando corresponda.

Un paquete de R no es muy diferente de utilizar varios scripts. Existen ciertas expectativas y convenciones que deben seguirse para para que que el paquete se “instale” en tu computadora y quede disponible como paquete. Algunas de estas convenciones son:

  • Debe haber un archivo llamado DESCRIPTION que contiene los metadatos necesarios para que R sepa cómo instalar el paquete. Veremos qué debe incluir más adelante.

  • Debe haber una carpeta llamada R/. Normalmente sólo contendrá archivos .R y sólo incluirán las funciones que hayas creado. Veremos como incorporar las funciones que ya tenemos dentro de un paquete.

  • Debe haber un archivo NAMESPACE que contenga la lista de funciones de tu paquete que esten disponibles para ser usadas. Este archivo se gestiona automáticamente con funciones de devtools y roxygen2.

  • La carpeta que contiene todo, aunque no es obligatorio debería llamarse como el paquete. Por ejemplo, el paquete usethis tiene el nombre de carpeta usethis/. Esto no es un requisito explícito, pero es muy recomendable. R determina el nombre del paquete a partir del campo Package: en el archivo DESCRIPTION.

Nada de esto es algo de lo que tengas que preocuparte realmente porque los paquetes usethis y devtools están diseñados para hacer muchas de estas tareas de configuración de paquetes por ti, o al menos simplificarlas.

¿Cómo funciona la instalación de paquetes? Cuando le dices a R que instale un paquete, que es un conjunto de archivos y carpetas que siguen un convención específica, R toma la carpeta y la convierte en un formato especial. Luego R guarda este formato especial en una ubicación por defecto que es específica del sistema operativo, como macOS, Windows o Linux. Para ver dónde están instalados los paquetes, utiliza

[1] "C:/Users/tonin/AppData/Local/R/win-library/4.4"
[2] "C:/Program Files/R/R-4.4.0/library"            

Si escribes esto en tu Consola, lo que verás probablemente será un un poco diferente a esto. Si .libPaths() muestra más de una ruta, normalmente la primera contendrá todos los paquetes.

[1] 325
C:/Users/tonin/AppData/Local/R/win-library/4.4/abind
C:/Users/tonin/AppData/Local/R/win-library/4.4/agroclimatico
C:/Users/tonin/AppData/Local/R/win-library/4.4/askpass
C:/Users/tonin/AppData/Local/R/win-library/4.4/assertthat
C:/Users/tonin/AppData/Local/R/win-library/4.4/audio
C:/Users/tonin/AppData/Local/R/win-library/4.4/automap

Si queremos ver cómo almacena R los paquetes en su formato especial, podemos utilizar dir_tree() y el contenido de la instalación de devtools/.

primary_library_path <- .libPaths()[1]
fs::dir_tree(path(primary_library_path, "devtools"))
C:/Users/tonin/AppData/Local/R/win-library/4.4/devtools
├── DESCRIPTION
├── doc
│   ├── dependencies.html
│   ├── dependencies.Rmd
│   └── index.html
├── help
│   ├── aliases.rds
│   ├── AnIndex
│   ├── devtools.rdb
│   ├── devtools.rdx
│   ├── figures
│   │   ├── lifecycle-archived.svg
│   │   ├── lifecycle-defunct.svg
│   │   ├── lifecycle-deprecated.svg
│   │   ├── lifecycle-experimental.svg
│   │   ├── lifecycle-maturing.svg
│   │   ├── lifecycle-questioning.svg
│   │   ├── lifecycle-stable.svg
│   │   ├── lifecycle-superseded.svg
│   │   └── logo.svg
│   └── paths.rds
├── html
│   ├── 00Index.html
│   └── R.css
├── INDEX
├── LICENSE
├── MD5
├── Meta
│   ├── features.rds
│   ├── hsearch.rds
│   ├── links.rds
│   ├── nsInfo.rds
│   ├── package.rds
│   ├── Rd.rds
│   └── vignette.rds
├── NAMESPACE
├── NEWS.md
├── R
│   ├── devtools
│   ├── devtools.rdb
│   └── devtools.rdx
├── rstudio
│   └── addins.dcf
└── WORDLIST

Los archivos R/devtools.rdb y R/devtools.rdx son los archivos cons formatos especiales que contienen las funciones dentro de devtools que R buscará cuando carga el paquete. Cuando se instala un paquete en R, se crea una carpeta en .libPaths() con los archivos en el formato específico que necesita R. Así que cuando ejecutes library(devtools), R sabrá que debe buscar las funciones que se encuentran en la carpeta devtools/.

Por lo tanto, instalar tu propio paquete que sólo se encuentra en tu computadora (es decir, no está publicado en CRAN o en GitHub) no es no difiere de instalar un paquete de CRAN con install.packages() o desde GitHub con pak::pak(). La única diferencia es que los paquetes en CRAN o GitHub pueden ser utilizados por cualquiera que tenga acceso a internet.

Te habrás dado cuenta de que hemos utilizado la sintaxis nombrepaquete::nombrefuncion() unas cuantas veces. Esto le dice a R que utilice la función de un paquete concreto. Así que pak::pak() es decirle a R que utilice la función pak() del paquete pak. En desarrollo de paquetes en particular, utilizaremos esto en lugar de cargar las librerias con library(pak) porque queremos ser explícitos sobre qué función queremos utilizar y porque no necesitamos cargar todas las funciones del paquete cuando sólo queremos utilizar una o dos.

10.4 Nombrar un paquete

Crear un paquete no es complicado. Lo complicado es es nombrar el paquete. Crear un nombre significativo, que la gente recuerde y que se pueda buscar en Google es realmente difícil. No hay una manera fácil de y a menudo requiere varios días de pensar opciones. Pero además hay que asegurarse de que el nombre que estamos pensando usar no lo esté usando alguien más. Esto se puede hacer con el paquete pak. Por ahora para revisar el paso a paso para crear un paquete usaremos paqueteprueba como nombre. Revisemos si está disponible

╔══════════════════════════════════════════════════════════════════════════════╗
║                             –*– paqueteprueba –*–                            ║
╚══════════════════════════════════════════════════════════════════════════════╝
┌──────────────────────────────────────────────────────────────────────────────┐
│ ✔  valid name      ✔  CRAN            ✔  Bioconductor    ✔  not a profanity  │
└──────────────────────────────────────────────────────────────────────────────┘
┌ Wikipedia ───────────────────────────────────────────────────────────────────┐
│ Paqueteprueba No definition found                                            │
└──────────────────────────────────────────────────────────────────────────────┘
┌ Wiktionary ──────────────────────────────────────────────────────────────────┐
│ paqueteprueba No English definition found                                    │
└──────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ Sentiment: :| (0)                                                            │
└──────────────────────────────────────────────────────────────────────────────┘

En este caso paqueteprueba está disponible para que lo usemos.

10.4.1 Requisitos formales

Existen tres requisitos formales:

  1. El nombre sólo puede estar formado por letras, números y puntos, es decir, .
  2. Debe empezar por una letra.
  3. No puede terminar con un punto.

Lamentablemente, esto significa que no puede utilizar guiones ni guiones bajos, es decir, - o _, en el nombre del paquete. Desaconsejamos el uso de puntos en los nombres de paquetes, para evitar que se confunda con extensiones de archivos y métodos S3.

10.5 Estructura de un paquete

Ahora que tenemos un nombre, el siguiente paso es configurar la infraestructura básica para el paquete. Afortunadamente, el paquete usethis ayuda resolver gran parte del trabajo. Cuando usemosla función usethis::create_package() configurará los archivos y carpetas básicos que necesitamos para crear un paquete y que R lo instale como tal. Utilizaremos esta función para crear el paquete paqueteprueba.

usethis::create_package(path = "~/Documentos/Courses/paqueteprueba")

En este caso estamos creando el paquete en la carpeta Documentos, pero también podríamos crearlo en cualquier otra carpeta. Esta linea de código además se corre en la consola, no tendría sentido que corra en un script ya que no es algo que haremos todos los días. El resultado es el siguiente

✔ Creating 'C:/Users/tonin/Documentos/paqueteprueba/'
✔ Setting active project to 'C:/Users/tonin/Documentos/paqueteprueba'
✔ Creating 'R/'
✔ Writing 'DESCRIPTION'
Package: paqueteprueba
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R (parsed):
    * First Last <first.last@example.com> [aut, cre] (YOUR-ORCID-ID)
Description: What the package does (one paragraph).
License: `use_mit_license()`, `use_gpl3_license()` or friends to
    pick a license
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.1
✔ Writing 'NAMESPACE'
✔ Writing 'paqueteprueba.Rproj'
✔ Adding '^paqueteprueba\\.Rproj$' to '.Rbuildignore'
✔ Adding '.Rproj.user' to '.gitignore'
✔ Adding '^\\.Rproj\\.user$' to '.Rbuildignore'
✔ Opening 'C:/Users/tonin/Documentos/paqueteprueba/' in new RStudio session
✔ Setting active project to '<no active project>

Donde sea que hayas creado el paquete ahora tendrás una carpeta llamada paqueteprueba con los archivos mínimos para instalar el paquete. Esta carpeta es al mismo tiempo un projecto de RStudio, es es porque estamos usando usethis y RStudio y viene con todas las ventajas que vimos. Sin embargo, no es impresindible que un paquete sea un proyecto al mismo tiempo. usethis tiene aún otra ventaja más, inicia automáticamente un repositorio. Esto es importantísimo, desarrollar software viene de la mano del control de versiones. Además, si estuvieramos creando un paquete de verdad, contectar este repositorio local con uno remoto en GitHub o GitLab es necesario para distribuir tu paquete y que lo puedan usar otras personas.

fs::dir_tree("C:/Users/tonin/Documents/Courses/paqueteprueba/", all = TRUE)
C:/Users/tonin/Documents/Courses/paqueteprueba/
├── .git
│   ├── COMMIT_EDITMSG
│   ├── config
│   ├── description
│   ├── FETCH_HEAD
│   ├── HEAD
│   ├── hooks
│   │   └── README.sample
│   ├── index
│   ├── info
│   │   └── exclude
│   ├── logs
│   │   ├── HEAD
│   │   └── refs
│   │       ├── heads
│   │       │   └── master
│   │       └── remotes
│   │           └── origin
│   │               ├── gh-pages
│   │               └── master
│   ├── objects
│   │   ├── 02
│   │   │   └── 4b0f9c5bf211c6afc136da0576bf55edf62f71
│   │   ├── 03
│   │   │   └── bb3fc049ce3d6f6d582d27a760ac393a7cf3c2
│   │   ├── 05
│   │   │   └── 9a94e2fd7a6144d1496157ce0c21e39fcde121
│   │   ├── 07
│   │   │   └── bf23c79f450c347e76116619a47f41487dd812
│   │   ├── 09
│   │   │   └── 7b241637da023174b0f2e3715bd0291d9ded37
│   │   ├── 0c
│   │   │   └── 1b65dfc587a5ba5ffbd5556da30ba3fd827753
│   │   ├── 0d
│   │   │   └── 68164c22af0517a3ee797e694642f207406d5f
│   │   ├── 0e
│   │   │   └── caf06d8c625646dc8cf48d46e92b69e7e8ece0
│   │   ├── 0f
│   │   │   └── 01ceb3d5a8810e3850eef27dd1b539b2277b0a
│   │   ├── 11
│   │   │   └── 03f811ed80f17985ecf61e0d50e3359484244f
│   │   ├── 12
│   │   │   ├── 0fa614d537069670638395863804ba384d9f13
│   │   │   └── 392edc2990d79f77b9f142a692e5ac5459d629
│   │   ├── 13
│   │   │   └── 204ea60fce6d3f67688a97707d5afb6631bb99
│   │   ├── 14
│   │   │   └── b591ffc2fe502b9073e28488ecc6c3dd09b643
│   │   ├── 17
│   │   │   ├── f5b68f382167e8e8b68e06904c0dee35148a52
│   │   │   └── f70c9e31823307a2e94c2599e84937ea528fa7
│   │   ├── 1a
│   │   │   ├── 99c65f5c77074bca64513ec5a95f2b0d3a99e5
│   │   │   ├── aee56e290f0d5028ec350ed6f5327ebe6276b2
│   │   │   └── dd63c77c46e246a33119eac95574a406ab5480
│   │   ├── 1e
│   │   │   ├── 67f5dde50dd83bafe2e844ba95dd58a8fec3bd
│   │   │   ├── d98734ca47bc2ef75f6693e9f588c90ec70718
│   │   │   └── ea05338954a09dbb1f09bb067d7813e3d97b4b
│   │   ├── 20
│   │   │   ├── 55116a3922554f910f2f8665bc43bde3eb0d32
│   │   │   ├── 651d9fdcef2c0d4f41fa686df195c67c55070e
│   │   │   ├── a3582ac0a5849fa4e27b827fdf8d773b9030f6
│   │   │   └── c2086edeacc9a02b427baf6d25d8de568bbb08
│   │   ├── 23
│   │   │   └── b1c47ba29581512bbffdf82a9d88fb898faee6
│   │   ├── 24
│   │   │   ├── 1b7b116e75ded19c636ccec50f00fa2723e44c
│   │   │   └── 5106d5064051562de496a102323748713a42c5
│   │   ├── 2a
│   │   │   └── 892af5b363195d8c25c5990e24a76a47572fb0
│   │   ├── 2b
│   │   │   └── db1fa0fac0382c7cf0f618efb0d2ec1c1e5d88
│   │   ├── 2d
│   │   │   └── 19fc766d98a08d9d1437896bfb008a7b15f340
│   │   ├── 2e
│   │   │   └── f6af19c05d8621f5a8489bcef540e8e66b5318
│   │   ├── 30
│   │   │   └── f55b7435491ed4c2b11de8ab5e5c7e1e1ed669
│   │   ├── 34
│   │   │   ├── 0ec989d9d7e9bf488f2e3dada00d02f2ec8a9e
│   │   │   └── 3a75a68c2a1c89c2fb2f0ab178c70479ea79ad
│   │   ├── 38
│   │   │   └── 63da8b7fc1ff8bde216be07ac7da1afe39cf34
│   │   ├── 39
│   │   │   ├── 26dc5382a1bf8fa47cda2ed77d4d8794c01874
│   │   │   └── cc346e3658b39b6511f63b34cadc3ef8599ca9
│   │   ├── 3a
│   │   │   ├── 5a31bdbcdfc843ea305a385760feaf8f99998c
│   │   │   └── cfe81965cbe71a031cb0aed0774293b657b599
│   │   ├── 3c
│   │   │   └── 09f354b2f91522fb358c669fc047817626f0de
│   │   ├── 3d
│   │   │   └── 2cfe3d1a1115faf88f2cac754e53995cf4546b
│   │   ├── 3e
│   │   │   ├── 7abe15eec6831cec9b96a90cbc6c478f512d6c
│   │   │   └── eaa94dd310ba54d1787898858fcac48c18bc17
│   │   ├── 40
│   │   │   ├── 1aa37448f81927b0dfea09fc0d25fb3707071c
│   │   │   └── b0809ce077384027dcf5f8899a9baaa9e534b1
│   │   ├── 42
│   │   │   ├── 88df62f2996d76084c43b9048889fa9125cc10
│   │   │   └── d7e967fc408e5fe0b710576bda3c8bf434fdf4
│   │   ├── 43
│   │   │   └── 3069fda07b214edb5df87941130d5ca4aad906
│   │   ├── 44
│   │   │   ├── 3b1ea8301d0b6593c7a66b2db38b964fb86988
│   │   │   ├── 55e17cb7a2467313e227cde61e9e29ca47ac55
│   │   │   └── b7b6b302247fbe911cee3463f59603edf543f9
│   │   ├── 46
│   │   │   └── cb4aec80078d4bfc7e223b8c92640c5a8b478f
│   │   ├── 4b
│   │   │   ├── 825dc642cb6eb9a060e54bf8d69288fbee4904
│   │   │   └── bce7508094d25e785c53b2098872d5ab3edbdf
│   │   ├── 4c
│   │   │   ├── 02b4db750926281d04633a920d7f4ad093b8ae
│   │   │   └── 220a2d3090d217db4623a3890ac2070dc9c859
│   │   ├── 50
│   │   │   └── 34b64c2c7a23f7a44d77ecf7f56d1b582d1b37
│   │   ├── 54
│   │   │   └── 0d22fca2efaec6f08943117e68d591a2264466
│   │   ├── 59
│   │   │   └── 782d5f0c137bc7ef8f3405771335a11d99cd34
│   │   ├── 5a
│   │   │   ├── 266908f7d21b9c6aff48ba292e009909b650c0
│   │   │   ├── 4c2d86c3f62bd870ab04d841794f4373a19637
│   │   │   └── 66dc2ff56d5e3617f0116bf106f3d93c9d5c4e
│   │   ├── 5d
│   │   │   ├── 2d7c55fcec900cfe39c5b3ebd0f0fdfae1232b
│   │   │   └── 96aa0d0143d9b8dd74fa3e193b2f455cfe86bc
│   │   ├── 62
│   │   │   └── 12fd67e3361189cc6ed823f95d7d4022a79057
│   │   ├── 63
│   │   │   └── d4c8b6fcb6a596e9550ceb22e907d2a9b4bfbb
│   │   ├── 64
│   │   │   ├── 89ce3acb5381b762a2bf4b71d77cf1e8eb80d3
│   │   │   └── e4e8d83568eb017c001b576431e4ea1f03f11e
│   │   ├── 65
│   │   │   └── 028400c5df2a59eff4a6b8d5de3caef61019d4
│   │   ├── 66
│   │   │   └── 04a0677c226d850f94099c7f1be1bbba73c227
│   │   ├── 69
│   │   │   ├── 3c37abb3db7f239b8fa5679a28790332471748
│   │   │   ├── a910fd78851edd93184c5aebc5e0e1cb9ad6e6
│   │   │   └── fafd4b6dddad27500cfc67efb9fb16e86a96bd
│   │   ├── 6a
│   │   │   ├── cd4edd8f85d86f4b71f7aeaff2f32fd2d94df4
│   │   │   └── e926839dd1829f1016a96f766d970ff184ad97
│   │   ├── 6b
│   │   │   └── 7d31a1fd5c88b6c8ed38878086593168d899a9
│   │   ├── 6c
│   │   │   └── 091b2921449f18808bbe1f84c62162738a2b4b
│   │   ├── 6d
│   │   │   └── 7d732814d8d41f8df2d7ddf8495095a24fe546
│   │   ├── 6e
│   │   │   ├── 509c599e415c54a097d0eafa5a20366fe020ea
│   │   │   └── a495f23c05753f6e67a0861bcd74d836d3243b
│   │   ├── 72
│   │   │   └── e042c9105cf35e13f82e78783a13bdf6989332
│   │   ├── 7b
│   │   │   └── 33421211d440f5332d7c86f94bd6f6a02de887
│   │   ├── 7c
│   │   │   ├── 794aae41aff30b6f9d22e702313dc48d01232a
│   │   │   └── 8e6c4ee1418151694f21657bc647effa320fd4
│   │   ├── 7d
│   │   │   ├── 86eb1694970141b88b52f5b26e6b019f16b590
│   │   │   └── ef5985ba4d1f9ca70b651608588ba5fa6024b5
│   │   ├── 7f
│   │   │   └── c6d0bbd9653d6f3cda175262991505af98f370
│   │   ├── 80
│   │   │   └── a6fd9dcafc0a153d9e6f3710d8b408aab296c3
│   │   ├── 82
│   │   │   └── 62fae1126a912bf73b1c06c1b0dcf182e178ac
│   │   ├── 87
│   │   │   └── 15acca833283a24f8e2c590846450db63a9375
│   │   ├── 88
│   │   │   ├── ad82769b87f10725c57dca6fcf41b4bffe462c
│   │   │   └── b0367aae421f51483c07ad7ae3ebc5251e48e5
│   │   ├── 8a
│   │   │   ├── 480d9b1fef0ec5b862df5446201c25b3f420e1
│   │   │   └── a49e2107c7038436da5bb7add96cd83c832d52
│   │   ├── 8b
│   │   │   └── 137891791fe96927ad78e64b0aad7bded08bdc
│   │   ├── 8c
│   │   │   └── 176bd123aff5c9284e99ee19707de9a207daf7
│   │   ├── 8d
│   │   │   └── e16732e7a2e1158009dfcc65af71d644680634
│   │   ├── 90
│   │   │   ├── ab95739f46c7f5202451c7e3ca971fe54f7ee1
│   │   │   └── afca635b8b3c4676ce46297d00be72285537a1
│   │   ├── 94
│   │   │   ├── 3bf4d3c3b59ec04bf3ebbdbc1e2890eac9edd4
│   │   │   ├── 67125ae2ecfd0ebaffbd53eb30698058077cff
│   │   │   └── 68cb09e0b3de12cccaa1f39a0b3085d3273559
│   │   ├── 95
│   │   │   ├── 234dd7cb623464a636b3c6620830949730074c
│   │   │   └── 7cfbc786ea6015aa91d95020475e00d54d135a
│   │   ├── 98
│   │   │   └── 7c7b33785d1ab481b3903239eae8ead805ec1b
│   │   ├── 99
│   │   │   └── 2841a1da7be1dd643db9bcc358bdcc68cb5848
│   │   ├── 9a
│   │   │   └── fa4bd857183037055de4d228c05c0c4c77c2b3
│   │   ├── 9c
│   │   │   └── 54e298b552b6ff6d0d182f2aed7dcba6f97c49
│   │   ├── 9e
│   │   │   └── f14bba45271af9ffc0116c1692c0ae331564f1
│   │   ├── a0
│   │   │   └── c963f428735f56803c05d4a44896df8f9669dc
│   │   ├── a2
│   │   │   └── 8af7ede86eba31239091d601b351fc5e5011b8
│   │   ├── a3
│   │   │   └── ecf8e6744fb39ac1d9c62b9bd2b6f81de2891a
│   │   ├── a8
│   │   │   ├── 5953d1740fa1070bcaf89f7db7994b3c3600cc
│   │   │   └── b7b34cb8b9a47f348b319c079d4f7874e366f4
│   │   ├── ad
│   │   │   └── ab560857f2bbb371566d2c99f26a4d595a6f6b
│   │   ├── b3
│   │   │   └── 723d9f2fb0291775bc932158065e134259fc51
│   │   ├── b4
│   │   │   └── 5d150db4b24e1a9660e86aa3efc5cfe5e553de
│   │   ├── b8
│   │   │   └── f4cc8c0c0ff94c440ffeded0fc0eeb8c9ef3ee
│   │   ├── ba
│   │   │   └── 6cb258e0f33ffddffd24b18d7162a32cb9a6da
│   │   ├── bd
│   │   │   ├── 9764ec0ea99ad3694ec0baf14aefec38182dfa
│   │   │   └── b6e3ae8a9ff416478c914cc76ac97ace83f44f
│   │   ├── bf
│   │   │   └── 35a862a61dc06c397d3314c9417e5c89821e36
│   │   ├── c2
│   │   │   └── 0a3ed5c47572874db52de10f7ab2ae69a9c036
│   │   ├── c3
│   │   │   └── 762f95d1bb381b303174bfb5e1397043d9a603
│   │   ├── c4
│   │   │   └── c6022f2982e8dae64cebd6b9a2b59f2547faad
│   │   ├── c5
│   │   │   └── 6c4542893799969f95e74f2171edbaad8c3d26
│   │   ├── c6
│   │   │   └── 28326a8462060ea44e644f4963b8b911445ec1
│   │   ├── c7
│   │   │   └── 9589d83dd5569afad3a4bf7dd96d97cfd52e57
│   │   ├── c8
│   │   │   └── 992e4ae4fbbc62f73efe8c1fb2c79e00f3c169
│   │   ├── c9
│   │   │   └── 50d4b8d0f2187d0bfba3db0aecdae51b4982f8
│   │   ├── ca
│   │   │   ├── 574e765c6d53a4d68a90711000f8b6fd48da50
│   │   │   └── e04eee2cd61c5a360755cb098e9f9b891cac2a
│   │   ├── cb
│   │   │   └── 480a65e75aeab8ac9cf17ae5f3ee3e66479b71
│   │   ├── cd
│   │   │   └── ec4ef320c18f346f614f6e6058594e2d69d323
│   │   ├── ce
│   │   │   └── 768f160de5b76b421b5fc8ce31214113f25bee
│   │   ├── cf
│   │   │   └── fe7b1868e00b4ea736138bbe96f6a33f3ef7a6
│   │   ├── d4
│   │   │   └── d05f8091dbaf832e73fd9ca0d3af83379a4078
│   │   ├── d6
│   │   │   └── 3bb5aced0406eaa9aa243251972172ca08b8b3
│   │   ├── d8
│   │   │   ├── 6a73797b033a22ea2efb2b5d859059198e512f
│   │   │   └── 82262f5f00e536b7b74e534c6a8c7d56e1b701
│   │   ├── db
│   │   │   ├── f96b7350ae1beb121df26e5468a6cbded51403
│   │   │   └── fa4ead963a89c83a1320ff396a86974d7e7440
│   │   ├── dd
│   │   │   └── 6f7906bd70fb5a5c07184306e882777219122b
│   │   ├── de
│   │   │   └── 71cd16a8a7f37774639874067a6937aaf72026
│   │   ├── df
│   │   │   └── fb99cd84e225ab64812a27f1633700a5fe07c9
│   │   ├── e1
│   │   │   └── bf3870508c36f72abbca1941d0b44e29478e6a
│   │   ├── e2
│   │   │   └── c6865f46a0b8172f7d6f8f05643be5b52c7f44
│   │   ├── e4
│   │   │   └── 79fb29349a12b564516c40aa529276c6c5e12d
│   │   ├── e5
│   │   │   └── 22719058705a6094d2d0dbdf13e510f729201b
│   │   ├── e6
│   │   │   └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│   │   ├── e8
│   │   │   ├── 6bead16ef066b83252df90550888f45c32e85b
│   │   │   ├── 7b34cf484e7b509229e350ea701d49386a6be3
│   │   │   └── f21f703f7bb4e9ab84daca93c9ee1d5358a316
│   │   ├── e9
│   │   │   └── 592af0e0c8e49f1f7fb5ba598a05eff4a9c72c
│   │   ├── ea
│   │   │   └── 1376b06dd639efef62dd690734bea93cb9694e
│   │   ├── ee
│   │   │   └── 0eabf13419468bd9ed79850ca2fd8967884f6d
│   │   ├── ef
│   │   │   └── 02a18f3331fa060f26d0db80d716e56f08f1b8
│   │   ├── f0
│   │   │   └── 2c9d8d4c4e59a076b63ada67685d2ff127ace0
│   │   ├── f5
│   │   │   └── a6ad9616e2ac53d67b39a76d23b719bd006a3f
│   │   ├── f6
│   │   │   └── 247992514bb99f50c415dd3f999a43e9165210
│   │   ├── f7
│   │   │   └── 2c7449e26629c1f9c3c8ddd06290b0450821cb
│   │   ├── f8
│   │   │   └── c768b9e70870a672a01998a341c924cce247da
│   │   ├── fb
│   │   │   ├── 63a6a282a80d6e28dc9cfe1b29f3b7f135b8df
│   │   │   └── 9fae11fe9b2092b22569c357e384c3dfea5b53
│   │   ├── fc
│   │   │   └── 6c299b73e792ef288e785c22393a5df9dded4b
│   │   ├── fd
│   │   │   ├── 1afe79f18500b649de86566d6dfbf98fa7e0f9
│   │   │   └── 9c6cd0288dab9f576a7cb7ba65d8928313df02
│   │   ├── fe
│   │   │   └── 19835c616a361ff6e7c182fff0ab2119e818dc
│   │   ├── info
│   │   └── pack
│   ├── ORIG_HEAD
│   └── refs
│       ├── heads
│       │   └── master
│       ├── remotes
│       │   └── origin
│       │       ├── gh-pages
│       │       └── master
│       └── tags
├── .github
│   ├── .gitignore
│   └── workflows
│       └── pkgdown.yaml
├── .gitignore
├── .Rbuildignore
├── .Rhistory
├── .Rproj.user
│   ├── 35B631FD
│   │   ├── bibliography-index
│   │   ├── cpp-definition-cache
│   │   ├── ctx
│   │   ├── explorer-cache
│   │   ├── pcs
│   │   │   ├── debug-breakpoints.pper
│   │   │   ├── files-pane.pper
│   │   │   ├── source-pane.pper
│   │   │   ├── windowlayoutstate.pper
│   │   │   └── workbench-pane.pper
│   │   ├── persistent-state
│   │   ├── presentation
│   │   ├── profiles-cache
│   │   ├── rmd-outputs
│   │   ├── saved_source_markers
│   │   ├── sources
│   │   │   ├── per
│   │   │   │   ├── t
│   │   │   │   │   ├── 5FDF386F
│   │   │   │   │   ├── 5FDF386F-contents
│   │   │   │   │   ├── 622B348D
│   │   │   │   │   ├── 622B348D-contents
│   │   │   │   │   ├── DBBF10BC
│   │   │   │   │   └── DBBF10BC-contents
│   │   │   │   └── u
│   │   │   └── prop
│   │   │       ├── 08A28989
│   │   │       ├── 13693628
│   │   │       ├── 29F9BEB5
│   │   │       ├── 62AEF134
│   │   │       ├── 6F3DE3A8
│   │   │       ├── 7E0E449F
│   │   │       ├── A74D1CF1
│   │   │       ├── CB71F6D7
│   │   │       ├── D222BABD
│   │   │       └── INDEX
│   │   ├── tutorial
│   │   ├── viewer-cache
│   │   └── viewer_history
│   └── shared
│       └── notebooks
│           ├── ABFEDDB4-vinieta_prueba
│           │   └── 1
│           │       ├── 35B631FD5ae6f5b
│           │       │   └── chunks.json
│           │       └── s
│           │           └── chunks.json
│           ├── patch-chunk-names
│           └── paths
├── data
│   └── datos.rda
├── data_raw
│   └── crea_datos.R
├── DESCRIPTION
├── docs
│   ├── 404.html
│   ├── articles
│   │   ├── index.html
│   │   └── vinieta_prueba.html
│   ├── authors.html
│   ├── deps
│   │   ├── bootstrap-5.3.1
│   │   │   ├── bootstrap.bundle.min.js
│   │   │   ├── bootstrap.bundle.min.js.map
│   │   │   └── bootstrap.min.css
│   │   ├── data-deps.txt
│   │   └── jquery-3.6.0
│   │       ├── jquery-3.6.0.js
│   │       ├── jquery-3.6.0.min.js
│   │       └── jquery-3.6.0.min.map
│   ├── index.html
│   ├── link.svg
│   ├── pkgdown.js
│   ├── pkgdown.yml
│   ├── reference
│   │   ├── datos.html
│   │   ├── index.html
│   │   ├── Rplot001.png
│   │   └── suma.html
│   ├── search.json
│   └── sitemap.xml
├── LICENSE
├── LICENSE.md
├── man
│   ├── datos.Rd
│   ├── fahrenheit_a_centigrados.Rd
│   └── suma.Rd
├── NAMESPACE
├── paqueteprueba.Rproj
├── R
│   ├── data.R
│   ├── fahrenheit_a_centigrados.R
│   └── suma.R
├── README.md
├── README.Rmd
├── tests
│   ├── testthat
│   │   ├── test-fahrenheit_a_centigrados.R
│   │   ├── test-suma.R
│   │   └── _snaps
│   └── testthat.R
├── vignettes
│   ├── .gitignore
│   └── vinieta_prueba.Rmd
└── _pkgdown.yml

Además del los archivos DESCRIPTION, NAMESPACE y la carpeta R que ya presentamos, hay algunos archivos y carpetas ocultas. Conocés el .gitignore, pero .Rbuildignore y .Rproj.user son nuevos. El primero es parecido a .gitignore, incluye la lista de archivos y carpetas que R deberá ignorar al momento de construir el paquete, por ahora la lista es corta pero ira creciendo a medida que sumemos cosas al paquete. La carpeta .Rproj.user es algo que está en todo projecto de RStudio e incluye las configuraciones específicas del proyecto.

10.5.1 Completando el archivo DESCRIPTION

El archivo DESCRIPTION contiene los metadatos del paquete paquete y algunos parámetros de configuración que R utiliza al construirlo e instalarlo. El formato de los metadatos utiliza el patrón key: value. Así, por ejemplo, la clave Package tiene el valor paqueteprueba, que le dice a R cuál es el nombre del paquete. Asimismo, Title y Authors proporcionan un poco más de información sobre lo que hace el paquete y quién lo creó. Un archivo DESCRIPTION completo tiene muchas otros campos, alguns de los cuales no son importantes ya que son creadas automáticamente y usados internamente por R para propósitos generales durante la construcción del paquete. Otros, son bastante importantes. Específicamente, las claves Title, Authors, y Description deberían tener más valores más apropiados.

Los campos Title y Description describen lo que hace el paquete. Sólo se diferencian en la longitud:

  • El título es una descripción del paquete en una línea, y a menudo se muestra en listados de paquetes. Debe ser texto plano (sin marcas), cada palabra en mayúsculas como un título, y NO terminar en un punto. Se breve: los listados suelen truncar el título a 65 caracteres.
  • La descripción es más detallada que el título. Puede utilizar varias frases, pero está limitado a un párrafo. Si la descripción abarca varias líneas (y así debe ser), cada una de ellas no debe superar los 80 caracteres. Deje 4 espacios entre las líneas siguientes.

Por ejemplo el título y la descripción de ggplot2 tienen esta pinta:

Title: Create Elegant Data Visualisations Using the Grammar of Graphics
Description: A system for 'declaratively' creating graphics,
    based on "The Grammar of Graphics". You provide the data, tell 'ggplot2'
    how to map variables to aesthetics, what graphical primitives to use,
    and it takes care of the details.

El campo Authors@R se utiliza para identificar al autoro autora del paquete, y a quién contactar si algo no funciona. Este campo es inusual porque contiene código R en lugar de texto plano. Este es un ejemplo:

Autores@R: person("Paola", "Corrales", email = "mimail@pao.com",
  role = c("aut", "cre"))

Estamos usando la función person() que viene con R base en el paquete utils.

person("Paola", "Corrales", email = "mimail@pao.com",
  role = c("aut", "cre"))
[1] "Paola Corrales <mimail@pao.com> [aut, cre]"

Esta función dice que Paola Corrales está a cargo de mantener el paquete (cre) y es autora (aut) y que su dirección de correo electrónico es mimail@pao.com. Es posible listar a más de una persona en este campo. La función person() tiene cuatro argumentos principales:

  • El nombre, especificado por los dos primeros argumentos, given y family. En la cultura occidental, given (nombre) va antes que family (apellido). En muchas otras culturas, esta convención no es válida. Para agregar una entidad, empresa u organización, como “R Core Team” o “Posit Software, PBC”, se usa el argumento given (y se omite family).

  • La dirección de email, es solo un requisito para quien mantiene el paquete. Es importante que uses una dirección de correo electrónico a la que tengas acceso permanente. La política de CRAN requiere que sea para una persona, en lugar de, por ejemplo, una lista de correo.

  • Uno o más códigos de tres letras especificando el role. Estos son los roles más importantes que hay que conocer:

    • cre: quien mantiene le paquete y la persona a la que deberías molestar si tenés problemas usandolo. A pesar de ser la abreviatura de «creator», este es el rol correcto para el mantenedor, incluso si no es la persona que inicialmente creó el paquete.

    • aut: autores, aquellas personas que han hecho contribuciones significativas al paquete.

    • ctb: contribuidores, aquellas personas que han hecho contribuciones menores, como parches.

    • cph: titular de los derechos de autor. Se utiliza para listar titulares de copyright adicionales que no son autores, normalmente empresas, como un empleador de uno o más de los autores.

    • fnd`: financiador, las personas u organizaciones que han proporcionado apoyo financiero para el desarrollo del paquete.

  • El argumento opcional comment se usa para incluir el identificador de ORCID. Y es particularmente útil en el ámbito académico.

Es momento de empezar a darle forma al paquete.

  1. Si aún no seguiste las instrucciones para crear el paqueteprueba, es el momento. No te preocupes por el nombre, este paquete es solo para practicar.
  2. Abrí el projecto/paquete.
  3. Abrí el archivo DESCRIPTION y completá los campos Title, Authors, y Description

10.6 Flujo de trabajo para el desarrollo de paquetes

Aunque hay varias formas de desarrollar un paquete R, un flujo de trabajo bien establecido y documentado gira en torno a hacer uso de usethis y devtools.

Los pasos típicos utilizados en este flujo de trabajo de desarrollo son:

  1. Cuando tengas una idea de una función o conjunto de funciones similares, por por ejemplo, sumar 2 números, es momento de iniciar un nuevo script. Para eso escribí en la consola usethis::use_r("suma"). Se creará un nuevo archivo R en la carpeta R/ y se abrirá en RStudio.

  2. En este nuevo archivo podrás empezar a crear y desarrollar la función, escribiendo los argumentos de entrada y la eventual salida. Por ahora llegamos hasta acá pero pronto veremos como documentar la función.

  3. Una vez que sienta que la función está lista para ser probada, podés probar la función ejecutándola en el mismo script, en la consola o en un archivo R Markdown. La otra alternativa para que la función esté disponible para R, es cargarla con Ctrl-Shift-L que ejecuta el comando load_all() (de devtools). Esto solo funciona porque estamos desarrollando un paquete.

  4. A menos que la función que creaste sea muy simple es muy improbable que funcione perfectamente la primera, lo más probable es que la función exactamente como esperabas o de un error. En ese caso tendrás que modificarla, cargarla nuevamente con load_all() y probarla nuevamenta tantas veces como sea neceasario hasta conseguir los resultados que necesitas. función.

Vamos a probar un poco de este flujo de trabajo haciendo una función de práctica. En la consola, escribí esta función:

usethis::use_r("funcion_prueba")

A continuación se abrirá el recientemente creado archivo R/funcion_prueba.R. Escribí la función y guardá los cambios en el archivo.

suma <- function(x, y) {
  x + y
}

Antes de hacer nada, escribe suma(2, 2) en la Consola y apretá enter para ejecutarlo. ¿Qué ocurre? Nada. Eso es porque R no sabe que la función existe. Tenemos que hacer que R la conozca ya sea ejecutando la función directamente desde el script (Ctrl-Enter para enviar a la Consola), usando source() en el script, instalando el paquete, o imitando la instalación del paquete con la función load_all(). Como estamos desarrollando un paquete usaremos la función load_all().

Vamos a probar la función load_all() con el atajo Ctrl-Shift-L. Ahora si, volvé a escribir suma(2, 2) en la consola. Ahora deberías ver que funciona.

Practiquemos el flujo de trabajo

Ya que usarás este flujo de trabajo cuando hagas paquetes en R, es hora de que lo practiques.

Realiza los siguientes cambios en la función. Con cada cambio, vuelva a cargarla (Ctrl-Shift-L en RStudio o load_all() en la Consola) para que las funciones actualizadas estén disponibles. Después de cada cambio probá que la función haga lo que debe hacer.

  • Agregá valores por defecto para los argumentos x e y. Probá correr la función sin pasarle argumentos: suma().

  • Modificá la función para que chequee que los argumentos sean numéricos. Probá la función con suma("1", 1)

  • Modifica nuevamente la función para que si x o y son negativos, la función devuelva “No puedo sumar negativos”.

10.6.1 Datos en paquetes

Muchos paquetes de R incluyen datos, en algunos casos porque son útiles para mostrar como usar las funciones que incluye, en otros casos porque es el objetivo principal de ese paquete. El paquete datos es el mejor ejemplo de esto último.

En la mayoría de los casos los datos en el paquete estarán disponibles para que las personas los usen. Guardaremos estos datos en la carpeta /data y el flujo de trabajo usando usethis tendrá esta pinta:

# Leer datos desde algún archivo
# o generar datos

# Manipular los datos para que tengan la pinta que necesitamos

datos <- sample(1000)
usethis::use_data(datos)

La función nos devolverá lo siguiente:

✔ Adding 'R' to Depends field in DESCRIPTION
✔ Creating 'data/'
✔ Setting LazyData to 'true' in 'DESCRIPTION'
✔ Saving 'datos' to 'data/datos.rda'
• Document your data (see 'https://r-pkgs.org/data.html')

Es decir, automáticamente crea la carpeta y guarda los datos con formato .rds (un tipo de archivo específico de R). En principio el código de arriba solo se correrá una vez a menos que sea necesario actualizar los datos. Sin embargo es una buena idea guarda el código y los datos crudos si los hubiera en data_raw. Esta carpeta además no debe incluirse cuando se construye el paquete por lo que hay que agregarla a Rbuildignore.

Ahora si apretamos Ctrl-Shift-L para cargar de nuevo el paquete de prueba y escribimos datos en la consola veremos los datos que creamos.

10.6.2 Construyendo un paquete de R paso a paso

Es hora de empezar a unir lo que hicimos. El objetivo de este ejercicio es crear la estructura de un paquete que lean y analice datos de estaciones meteorológicas. Pero además este será un trabajo colaborativo entre 2 personas para practicar como desarrollar software en equipo usando GitHub.

Crear el paquete

  1. Piensen un nombre para el paquete, debe seguir las reglas pero no importa si se repite en otro ámbito.

  2. El paquete debera estar en la cuenta de GitHub de una de las personas que integran el grupo. Decidan quien sera y realicen los siguientes pasos en la computadora de esa persona.

  3. Creen la estructura del paquete con usethis.

  4. Modifiquen el archivo DESCRIPTION con todo lo necesario.

Conectarlo con Git localmente

  1. Para crear el repositorio local corran la siguiente funcion de usethis en la consola de R con el proyecto del paquete abierto en RStudio en la maquina de la persona que seleccionaron para que tenga el repo en su cuenta:

usethis::use_git()

Esta funcion va a crear el repositorio y generara un commit inicial de todos los archivos que tiene el proyecto. Va a preguntarte si queres hacer esto. Contestale que si. Tambien va a reiniciar RStudio para que la pestaña de Git aparezca en nuestro proyecto. Va a preguntarte si queres hacer esto. Contestale que si.

Crear el repo remoto en GitHub

  1. Con el proyecto del paquete abierto en RStudio en la computadora de la persona que tendra el repo en GitHub, corran la siguiente funcion de usethis en la consola:

usethis::use_github()

Esta funcion hace lo siguiente:

  • Crea un nuevo repositorio en GitHub con el nombre del proyecto.
  • Configura ese nuevo repositorio como origen remoto para el repositorio local.
  • Configura tu branch local por defecto para realizar el mismo seguimiento en el origen y realiza un push inicial.
  • Abre el nuevo repositorio en tu navegador.

Te presenta algo similar a esto en la consola:


ℹ Defaulting to "https" Git protocol.
✔ Creating GitHub repository "yabellini/inventarioRRNN". 
✔ Setting remote "origin" to "https://github.com/yabellini/inventarioRRNN.git". 
✔ Adding "https://github.com/yabellini/inventarioRRNN" to URL. 
✔ Adding "https://github.com/yabellini/inventarioRRNN/issues" to BugReports. 
ℹ There is 1 uncommitted file: • DESCRIPTION !

Is it ok to commit it?

1: Absolutely not 
2: Not now 
3: Yes

Selection: 3 

✔ Adding files. 
✔ Making a commit with message "Add GitHub inks to DESCRIPTION". 
✔ Pushing "master" branch to GitHub and setting "origin/master" as upstream branch. 
✔ Opening URL <https://github.com/yabellini/inventarioRRNN>.
  1. Modificar la configuración del repositorio en GitHub para que la otra persona del grupo tenga permisos para hacer commits y push. Necesitarás sabes su nombre de usuario
    1. En GitHub.com, navega a la página principal del repositorio.

    2. Hacé clic en Settings.

      Captura de pantalla de un encabezado de repositorio en el que se muestran las pestañas. La pestaña “Configuración” está resaltada con un contorno naranja oscuro.
    3. En la sección “Access” de la barra lateral, haz clic en Colaborators.

    4. Hacé clik en el botón verde Add people.

    5. Comenzá a teclear el nombre de la persona que deseas invitar dentro del campo de búsqueda hasta que aparezca.

    6. Hacé clikc en Add NOMBRE to this repository.

    7. La persona recibirá un correo electrónico invitándole al repositorio. Una vez que acepte la invitación, tendrá acceso de colaborador a tu repositorio.

4. La otra persona del grupo ahora puede clonar el repo en su computadora, siguiendo los pasos que vimos en como trabajar individualmente.

  1. Modificá el README.md para indicar que el paquete es de prueba, que no está pensado para ser usado como tal.