You are on page 1of 25

CAPÍTULO 01 - “Introduction”

Subsequent chapters of the book go into more details about each package component.
They’re roughly organised in order of importance:

 R code, chapter 6: the most important directory is R/, where your R code lives. A
package with just this directory is still a useful package. (And indeed, if you stop reading
the book after this chapter, you’ll have still learned some useful new skills.)

 Package metadata, chapter 7: the DESCRIPTION lets you describe what your


package needs to work. If you’re sharing your package, you’ll also use
the DESCRIPTION  to describe what it does, who can use it (the license), and who to
contact if things go wrong.

 Documentation, chapter 8: if you want other people (including future-you!) to


understand how to use the functions in your package, you’ll need to document them.
We’ll show you how to use roxygen2 to document your functions. We recommend
roxygen2 because it lets you write code and documentation together while continuing to
produce R’s standard documentation format.
 Vignettes, chapter 9: function documentation describes the nit-picky details of
every function in your package. Vignettes give the big picture. They’re long-form
documents that show how to combine multiple parts of your package to solve real
problems. We’ll show you how to use Rmarkdown and knitr to create vignettes with a
minimum of fuss.
 Tests, chapter 10: to ensure your package works as designed (and continues to
work as you make changes), it’s essential to write unit tests which define correct
behaviour, and alert you when functions break. In this chapter, we’ll teach you how to
use the testthat package to convert the informal interactive tests that you’re already
doing to formal, automated tests.
 Namespace, chapter 11: to play nicely with others, your package needs to define
what functions it makes available to other packages and what functions it requires from
other packages. This is the job of the NAMESPACE file and we’ll show you how to use
roxygen2 to generate it for you. The NAMESPACE is one of the more challenging parts of
developing an R package but it’s critical to master if you want your package to work
reliably.

 External data, chapter 12: the data/ directory allows you to include data with your
package. You might do this to bundle data in a way that’s easy for R users to access, or
just to provide compelling examples in your documentation.

 Compiled code, chapter 13: R code is designed for human efficiency, not


computer efficiency, so it’s useful to have a tool in your back pocket that allows you to
write fast code. The src/ directory allows you to include speedy compiled C and C++
code to solve performance bottlenecks in your package.
 Other components, chapter 15: this chapter documents the handful of other
components that are rarely needed: demo/, exec/, po/ and tools/.
The final chapters describe general best practices not specifically tied to one directory:

 Git and GitHub, chapter 16: mastering a version control system is vital to easily
collaborate with others, and is useful even for solo work because it allows you to easily
undo mistakes. In this chapter, you’ll learn how to use the popular Git and GitHub
combo with RStudio.
 Automated checking, chapter 17: R provides very useful automated quality
checks in the form of R CMD check . Running them regularly is a great way to avoid many
common mistakes. The results can sometimes be a bit cryptic, so we provide a
comprehensive cheatsheet to help you convert warnings to actionable insight.

 Release, chapter 18: the life-cycle of a package culminates with release to the


public. This chapter compares the two main options (CRAN and GitHub) and offers
general advice on managing the process.
CONVENCIONES
Throughout this book, we write foo() to refer to functions, bar to refer to variables and function
parameters, and baz/ for paths.
ARCHIVOS CREADOS CON DEVTOOLS

 .Rbuildignore lists files that we need to have around but that should not be included
when building the R package from source. More in 4.3.1.
 .Rproj.user , if you have it, is a directory used internally by RStudio.
 .gitignore anticipates Git usage and ignores some standard, behind-the-scenes files
created by R and RStudio. Even if you do not plan to use Git, this is harmless.
 DESCRIPTION provides metadata about your package . We edit this shortly.
 NAMESPACE declares the functions your package exports for external use and the
external functions your package imports from other packages. At the moment, it holds
temporary-yet-functional placeholder content.
 The R/ directory is the “business end” of your package . It will soon
contain .R files with function definitions.
 foofactors.Rproj  is the file that makes this directory an RStudio Project. Even if you
don’t use RStudio, this file is harmless. Or you can suppress its creation
with create_package(..., rstudio = FALSE) . More in 5.2.
CAPÍTULO 02 - “The whole game”

PASOS EN LA CREACIÓN DE UN PAQUETE DE “JUGUETE”


library(devtools)
library(tidyverse)
library(fs)
create_package("~/path/to/foofactors")
use_git()
#Write the first function.
fbind <- function(a, b) {
factor(c(as.character(a), as.character(b)))
}
use_r("fbind")
#> ● Edit 'R/fbind.R'
#The helper use_r() creates and/or opens a script below R/. 
load_all()
#> Loading foofactors
fbind(a, b)
#Note that load_all() has made the fbind() function available, although it does #not exist in
the global workspace.
exists("fbind", where = ".GlobalEnv", inherits = FALSE)
#> [1] FALSE
check()

RStudio exposes load_all() in the Build menu, in the Build pane via More > Load All, and in


keyboard shortcuts Ctrl + Shift + L (Windows & Linux) or Cmd + Shift + L (macOS).

RStudio exposes check() in the Build menu, in the Build pane via Check, and in keyboard


shortcuts Ctrl + Shift + E (Windows & Linux) or Cmd + Shift + E (macOS).

Use Ctrl + . in RStudio and start typing “DESCRIPTION” to activate a helper that makes it easy to open a
file for editing. In addition to a filename, your hint can be a function name. This is very handy once a
package has lots of functions and files below R/.

use_mit_license("Jane Doe")
#> ✔ Setting License field in DESCRIPTION to 'MIT + file LICENSE'
#> ✔ Writing 'LICENSE.md'
#> ✔ Adding '^LICENSE\\.md$' to '.Rbuildignore'
#> ✔ Writing 'LICENSE'
Like other license helpers, use_mit_license()  also puts a copy of the full license
in LICENSE.md and adds this file to .Rbuildignore. It’s considered a best practice to include a full
license in your package’s source, such as on GitHub, but CRAN disallows the inclusion of this
file in a package tarball.

If you use RStudio, open R/fbind.R in the source editor and put the cursor somewhere in
the fbind() function definition. Now do Code > Insert roxygen skeleton. 

#' Bind two factors


#'
#' Create a new factor from two existing factors, where the new factor's levels
#' are the union of the levels of the input factors.
#'
#' @param a factor
#' @param b factor
#'
#' @return factor
#' @export
#' @examples
#' fbind(iris$Species[c(1, 51, 101)], PlantGrowth$group[c(1, 11, 21)])

document()
#> Updating foofactors documentation
#> Updating roxygen version in /tmp/RtmpsJ87ir/foofactors/DESCRIPTION
#> Writing NAMESPACE
#> Loading foofactors
#> Writing NAMESPACE
#> Writing fbind.Rd

RStudio exposes document() in the Build menu, in the Build pane via More > Document, and in


keyboard shortcuts Ctrl + Shift + D (Windows & Linux) or Cmd + Shift + D (macOS).
You’ll see a message like “Rendering development documentation for ‘fbind’”, which reminds that
you are basically previewing draft documentation. That is, this documentation is present in your
package’s source, but is not yet present in an installed package.
check() #AGAIN!

Since we have a minimum viable product now, let’s install the foofactors package into
your library via install():
install()

RStudio exposes similar functionality in the Build menu and in the Build pane via Install and


Restart.
First, we declare our intent to write unit tests and to use the testthat package for this,
via use_testthat() :
use_testthat()
#> ✔ Adding 'testthat' to Suggests field in DESCRIPTION
#> ✔ Creating 'tests/testthat/'
#> ✔ Writing 'tests/testthat.R'
#> ● Call `use_test()` to initialize a basic test file and open it for editing.
This initializes the unit testing machinery for your package. It adds  Suggests:
testthat  to DESCRIPTION , creates the directory tests/testthat/ , and adds the script test/testthat.R

The helper use_test() opens and/or creates a test file. You can provide the file’s basename
or, if you are editing the relevant source file in RStudio, it will be automatically
generated. Since this book is built non-interactively, we must provide the basename
explicitly:
use_test("fbind")
#> ✔ Increasing 'testthat' version to '>= 2.1.0' in DESCRIPTION
#> ✔ Writing 'tests/testthat/test-fbind.R'
This creates the file tests/testthat/test-fbind.R . Put this content in it:
test_that("fbind() binds factor (or character)", {
x <- c("a", "b")
x_fact <- factor(x)
y <- c("c", "d")
z <- factor(c("a", "b", "c", "d"))
RStudio exposes test() in the Build menu, in the Build pane via More > Test package, and in
keyboard shortcuts Ctrl + Shift + T (Windows & Linux) or Cmd + Shift + T (macOS).
expect_identical(fbind(x, y), z)
expect_identical(fbind(x_fact, y), z)
})

It is a good idea to use the covr package to track what proportion of your package’s source
code is exercised by the tests. More details can be found in chapter 10.
You will inevitably want to use a function from another package in your own package. Just as
we needed to export fbind(), we need to import functions from the namespace of other
packages. If you plan to submit a package to CRAN, note that this even applies to functions in
packages that you think of as “always available”, such as stats::median()  or utils::head() .

We’re going to add another function to foofactors that produces a sorted frequency table
for a factor. We’ll borrow some smarts from the forcats package, specifically the
function forcats::fct_count() .
First, declare your general intent to use some functions from the forcats namespace
with use_package() :
use_package("forcats")
#> ✔ Adding 'forcats' to Imports field in DESCRIPTION
#> ● Refer to functions with `forcats::fun()`
This adds the forcats package to the “Imports” section of DESCRIPTION. 

Initiate a new .R file below R/ with use_r():


use_r("fcount")
#> ● Edit 'R/fcount.R'
Observe cómo prefacio la llamada a funciones de forcats con forcats ::. Esto especifica que
queremos llamar a la función fct_count () desde el espacio de nombres forcats. Hay más de
una forma de llamar a funciones en otros paquetes y la que proponemos aquí se explica
completamente en el capítulo 11. OJO AQUÍ! LA FORMA DE LLAMAR FUNCIONES!
#' Make a sorted frequency table for a factor
#'
#' @param x factor
#'
#' @return A tibble
#' @export
#' @examples
#' fcount(iris$Species)
fcount <- function(x) {
forcats::fct_count(x, sort = TRUE)
}
load_all()
fcount(iris$Species)
document()

How would you connect your local foofactors package and Git repository to a companion
repository on GitHub?

Now that your package is on GitHub, the README.md file matters. It is the package’s


home page and welcome mat, at least until you decide to give it a website
(see pkgdown), add a vignette (see chapter 9), or submit it to CRAN (see chapter 18).
The use_readme_rmd()  function initializes a basic, executable README.Rmd ready for you
to edit:
use_readme_rmd()
#> ✔ Writing 'README.Rmd'
#> ✔ Adding '^README\\.Rmd$' to '.Rbuildignore'
#> ✔ Writing '.git/hooks/pre-commit'

The use_readme_rmd()  function initializes a basic, executable README.Rmd ready for you


to edit:
use_readme_rmd()
#> ✔ Writing 'README.Rmd'
#> ✔ Adding '^README\\.Rmd$' to '.Rbuildignore'
#> ✔ Writing '.git/hooks/pre-commit'

Además de crear README.Rmd, esto agrega algunas líneas a .Rbuildignore y crea un enlace
de precompromiso de Git para ayudarlo a mantener README.Rmd y README.md
sincronizados.

README.Rmd ya tiene secciones que:


Solicitarle que describa el propósito del paquete.
Proporcione el código para instalar su paquete.
Le pedirá que muestre un poco de uso.
¿Cómo poblar este esqueleto? Copie material generosamente de DESCRIPTION y cualquier
prueba formal o informal o ejemplos que tenga. Algo es mejor que nada. De lo contrario ...
¿espera que la gente instale su paquete y revise los archivos de ayuda individuales para
descubrir cómo usarlo? Probablemente no lo harán.

Nos gusta escribir el archivo README en R Markdown, por lo que puede incluir el uso real.
Cargará la versión actualmente instalada de su paquete, por lo que este es un buen momento
para "Instalar y reiniciar" en RStudio. O haga esto en R Console:
install()
Ejemplo: The README.Rmd we use is here: README.Rmd  and these are the contents:

Don’t forget to render it to make README.md! The pre-commit hook should remind you
if you try to commit README.Rmd but not README.md and also
when README.md appears to be out-of-date.
rmarkdown::render("README.Rmd") ## or use "Knit HTML" in RStudio

Let’s run check() again to make sure all is still well.

check()
install()

CAPÍTULO 03 - “System setup”

To get started, make sure you have the latest version of R (at
least 3.6.1, which is the version being used to render this book),
then run the following code to get the packages you’ll need:
install.packages(c("devtools", "roxygen2", "testthat", "knitr"))

Make sure you have a recent version of the RStudio integrated


development environment (IDE).

Example of how to simulate installing and loading a package,


during interactive development:
library(devtools)
load_all()

If that same functionality is used inside an R package, this is the


preferred call:
pkgload::load_all()

If you choose to specify the namespace, such as when working in a more programmatic style,
then access usethis functions directly: do usethis::use_testthat() instead of
devtools::use_testthat().

You can attach devtools like so:


library(devtools)
But it soon grows aggravating to repeatedly attach devtools in
every R session. Therefore, we strongly recommend attaching
devtools in your .Rprofile startup file, like so:
if (interactive()) {
suppressMessages(require(devtools))
}
For convenience, the function use_devtools() creates .Rprofile, if
needed, opens it for editing, and puts the necessary lines of code on
the clipboard and the screen. Another package you may want to handle
this way is testthat.

usethis consults certain options when, for example, creating R


packages de novo. This allows you to specify personal defaults
for yourself as a package maintainer or for your preferred
license. Here’s an example of a code snippet that could go
in .Rprofile:
options(
usethis.full_name = "Jane Doe",
usethis.description = list(
`Authors@R` = 'person("Jane", "Doe", email = "jane@example.com", role =
c("aut", "cre"),
comment = c(ORCID = "YOUR-ORCID-ID"))',
License = "MIT + file LICENSE",
Version = "0.0.0.9000"
),
usethis.protocol = "ssh"
)
The following code installs the development versions of devtools
and usethis, which may be important during the revision of the
book.
devtools::install_github("r-lib/devtools")
devtools::install_github("r-lib/usethis")

On Windows the collection of tools needed for building packages


from source is called Rtools.

Rtools is NOT an R package. It is NOT installed


with install.packages() . Instead, download it from https://cran.r-
project.org/bin/windows/Rtools/  and run the installer.
During the Rtools installation you may see a window asking you
to “Select Additional Tasks”.

 Do not select the box for “Edit the system PATH”. devtools and
RStudio should put Rtools on the PATH automatically when it is needed.
 Do select the box for “Save version information to registry”. It
should be selected by default.
 You can check that you have everything installed and
working by running the following code:
 # TODO: replace with whatever results from https://github.com/r-
lib/devtools/issues/1970
 library(devtools)
 has_devel()
 #> [1] TRUE
If everything is ok, it returns TRUE. Otherwise, it will reveal
some diagnostic info about the problem.
CAPÍTULO 04 - “Package structure and state”
Aprenderá sobre los diversos estados en los que puede estar un paquete y la diferencia entre un
paquete y una biblioteca (y por qué debería importarle).

Cuando crea o modifica un paquete, trabaja en su "código fuente" o "archivos fuente".

Los flujos de trabajo de desarrollo de paquetes tienen mucho más sentido si comprende los cinco
estados en los que puede estar un paquete R:

1. Source (Fuente)
2. Bundled (Incluido)
3. Binary (Binario)
4. Installed (Instalado)
5. in-memory (En - memoria)

Ya conoce algunas de las funciones que colocan paquetes en estos estados. Por ejemplo,
install.packages() y devtools::install_github() mueven un paquete desde los estados
fuente, empaquetado o binario al estado instalado. La función library() carga un paquete
instalado en la memoria, lo que lo hace disponible para uso inmediato y directo.

Source Package

Un paquete fuente es solo un directorio de archivos con una estructura específica. Incluye
componentes particulares, como un archivo DESCRIPTION, un directorio R/ que contiene archivos
.R , etc.

Muchos paquetes R se desarrollan al aire libre en GitHub (o GitLab o similar). El mejor de los casos
es que visite la página de inicio de CRAN del paquete, por ejemplo:

forcats: https://cran.r-project.org/package=forcats
readxl: https://cran.r-project.org/package=readxl

y una de sus URL enlaza con un repositorio en un servicio de alojamiento público, por ejemplo:

forcats: https://github.com/tidyverse/forcats
readxl: https://github.com/tidyverse/readxl

Bundled Package

Un paquete incluido es un paquete que se ha comprimido en un solo archivo. Por convención


(desde Linux), los paquetes de paquetes en R usan la extensión .tar.gz y a veces se los denomina
"tarballs de origen". Esto significa que varios archivos se han reducido a un solo archivo (.tar) y
luego se han comprimido usando gzip (.gz). Si bien un paquete no es tan útil por sí solo, es un
intermediario independiente del transporte y amigable con la plataforma entre un paquete fuente
y un paquete instalado.

En el raro caso de que necesite hacer un paquete a partir de un paquete que está desarrollando
localmente, use devtools::build() . Bajo el capó, esto llama a pkgbuild::build() y, en última
instancia, R CMD build, que se describe más adelante en la sección de construcción de paquetes
de tarballs de Writing R Extensions.

Cada paquete CRAN está disponible en forma de paquete, a través del campo "Fuente del
paquete" de las páginas de destino individuales. Continuando con nuestros ejemplos anteriores,
puede descargar los paquetes forcats_0.4.0.tar.gz y readxl_1.3.1.tar.gz (o cualesquiera
que sean las versiones actuales). Podría desempaquetar dicho paquete en el shell (no en la
consola R) de esta manera:

tar xvf forcats_0.4.0.tar.gz


 .Rbuildignore

Controla qué archivos del paquete fuente llegan a los formularios posteriores.
Cada línea de .Rbuildignore es una expresión regular compatible con Perl que
coincide, sin importar el caso, con la ruta a cada archivo en el paquete
fuente.
Si la expresión regular coincide, ese archivo o directorio se excluye. Tenga
en cuenta que hay algunas exclusiones predeterminadas implementadas por R,
relacionadas principalmente con los sistemas y editores de control de
versiones clásicos, como SVN, Git y Emacs.

Para excluir un archivo o directorio específico (el caso de uso más común),
DEBE anclar la expresión regular. Por ejemplo, para excluir un directorio
llamado "notas", use ^notes$. Las notas de expresión regular coincidirán con
cualquier nombre de archivo que contenga notas, p. R/notes.R man/important-
notes.R, data/endnotes.Rdata, etc. La forma más segura de excluir un archivo o
directorio específico es usar usethis::use_build_ignore("notes"), que hace el
escape para tú.
.Rbuildignore es una forma de resolver algunas de las tensiones entre las
prácticas que respaldan su proceso de desarrollo y los requisitos de CRAN para
el envío y la distribución. Incluso si no planea lanzar CRAN, seguir estas
convenciones le permitirá hacer el mejor uso de las herramientas integradas de
R para la verificación e instalación de paquetes. Los archivos afectados se
dividen en dos clases amplias, semi-superpuestas:

 Archivos que lo ayudan a generar contenidos de paquetes mediante


programación. Ejemplos:
 Usando README.Rmd para generar un README.md. informativo y
actual.
 Almacenar .R para crear y actualizar datos internos o exportados.
 Archivos que impulsan el desarrollo, la verificación y la documentación
de paquetes, fuera del alcance de CRAN. Ejemplos:
 Archivos relacionados con el IDE RStudio.
 Usando el pkgdown package  para generar un sitio web.
 Archivos de configuración relacionados con la integración /
despliegue continuo y la cobertura de pruebas de monitoreo.

Aquí hay una lista no exhaustiva de entradas típicas en el archivo .Rbuildignore


para un paquete en el tidyverse:

^.*\.Rproj$ # Designates the directory as an RStudio Project


^\.Rproj\.user$ # Used by RStudio for temporary files
^README\.Rmd$ # An Rmd file used to generate README.md
^LICENSE\.md$ # Full text of the license
^cran-comments\.md$ # Comments for CRAN submission
^\.travis\.yml$ # Used by Travis-CI for continuous integration testing
^data-raw$ # Code used to create data included in the package
^pkgdown$ # Resources used for the package website
^_pkgdown\.yml$ # Configuration info for the package website
^\.github$ # Contributing guidelines, CoC, issue templates, etc.

Mencionaremos cuándo debe agregar archivos a .Rbuildignore cuando sea


importante. Recuerde que usethis::use_build_ignore() es una forma atractiva de
administrar este archivo.
Binary Package

Si desea distribuir su paquete a un usuario R que no tiene herramientas de


desarrollo de paquetes, deberá proporcionar un paquete binario. Al igual que un
paquete de paquetes, un paquete binario es un solo archivo. A diferencia de un
paquete incluido, un paquete binario es específico de la plataforma y hay dos
opciones básicas: Windows y macOS. (Por lo general, se requiere que los usuarios
de Linux tengan las herramientas necesarias para instalar desde archivos
.tar.gz).

Los paquetes binarios para macOS se almacenan como .tgz, mientras que los
paquetes binarios de Windows terminan en .zip. Si necesita hacer un paquete
binario, use devtools::build(binary = TRUE) en el sistema operativo relevante.
Bajo el capó, esto llama a pkgbuild::build(binary = TRUE) y, en última
instancia, R CMD INSTALL --build, que se describe con más detalle en la
sección Building binary packages de Writing R Extensions.

Para ser claros, el principal fabricante y distribuidor de paquetes binarios es


CRAN, no mantenedores individuales. Si su paquete está destinado al uso público,
la forma más efectiva de hacerlo ampliamente disponible es lanzarlo en CRAN.
Envía un paquete de paquetes y CRAN crea y distribuye los binarios del paquete.

Esto es, de hecho, parte de lo que generalmente sucede detrás de escena cuando
llamas a install.packages() .

Si descomprime un paquete binario, verá que la estructura interna es bastante


diferente de un paquete fuente o empaquetado. Estas son algunas de las
diferencias más notables:

 No hay archivos .R en el directorio R/; en cambio, hay tres archivos que


almacenan las funciones analizadas en un formato de archivo eficiente.
Esto es básicamente el resultado de cargar todo el código R y luego
guardar las funciones con save (). (En el proceso, esto agrega un poco de
metadatos adicionales para hacer las cosas lo más rápido posible).

 Un directorio Meta/ contiene varios archivos .rds. Estos archivos


contienen metadatos en caché sobre el paquete, como qué temas cubren los
archivos de ayuda y una versión analizada del archivo DESCRIPTION. (Puede
usar readRDS() para ver exactamente qué hay en esos archivos). Estos
archivos hacen que la carga del paquete sea más rápida al almacenar en
caché cálculos costosos.

 El contenido de ayuda real aparece en help/ y html/ (ya no está en man/).

 Si tenía algún código en el directorio src/, ahora habrá un directorio


libs/ que contiene los resultados de compilar el código. En Windows, hay
subdirectorios para entornos de 32 bits (i386 /) y 64 bits (x64 /).

 Si tenía algún objeto en data/, ahora se ha convertido a una forma más


eficiente.
 El contenido de inst/ se mueve al directorio de nivel superior. Por
ejemplo, los archivos de viñeta ahora están en doc/.

 Se han descartado algunos archivos y carpetas, como README, build/,


tests/ y vignettes/.
Installed Package

Un paquete instalado es un paquete binario que se ha descomprimido en una


biblioteca de paquetes (descrita en 4.7). El siguiente diagrama ilustra las
muchas formas en que se puede instalar un paquete. ¡Este diagrama es complicado!
En un mundo ideal, la instalación de un paquete implicaría unir un conjunto de
pasos simples: source -> bundle, bundle -> binary, binary -> installed . En
el mundo real, no es tan simple porque a menudo hay accesos directos (más
rápidos) disponibles.

Es comprensible que a la mayoría de los usuarios les guste instalar paquetes


desde la comodidad de una sesión R y directamente desde CRAN. La función
incorporada install.packages()  satisface esta necesidad. Puede descargar el
paquete, en varias formas, instalarlo y, opcionalmente, atender la instalación
de dependencias.

devtools expone una familia de funciones install_*() para abordar algunas


necesidades más allá del alcance de install.packages() o para hacer que las
capacidades existentes sean más fáciles de acceder. Estas funciones se mantienen
en el remotes package y devtools las reexporta.

library(remotes)

funs <- as.character(lsf.str("package:remotes"))


grep("^install_.+", funs, value = TRUE)
#> [1] "install_bioc" "install_bitbucket" "install_cran"
#> [4] "install_deps" "install_dev" "install_git"
#> [7] "install_github" "install_gitlab" "install_local"
#> [10] "install_svn" "install_url" "install_version"
install_github() es el ejemplo principal de una subfamilia de funciones que
puede descargar un paquete desde una ubicación remota que no es CRAN y hacer lo
que sea necesario para instalarlo. El resto de las funciones devtools/remotes
install_*() están destinadas a hacer que las cosas que son técnicamente posibles
con herramientas básicas sean un poco más fáciles o más explícitas, como
install_version () que instala una versión específica de un paquete CRAN.

Análogo a .Rbuildignore, .Rinstignore le permite mantener los archivos


presentes en un paquete de paquetes fuera del paquete instalado. Sin embargo, en
contraste con .Rbuildignore, esto es bastante oscuro y rara vez se necesita.

In - memory Package

Finalmente llegamos a un comando familiar para todos los que usan R:

library(usethis)

Suponiendo que usethis está instalado, esta llamada hace que sus funciones estén
disponibles para su uso, es decir, ahora podemos hacer:

create_package("/path/to/my/coolpackage")

El uso de este paquete se ha cargado en la memoria y, de hecho, también se ha


adjuntado a la ruta de búsqueda. La distinción entre cargar y adjuntar paquetes
no es importante cuando escribe scripts, pero es muy importante cuando escribe
paquetes. Aprenderá más sobre la diferencia y por qué es importante en la ruta
de búsqueda.

library() no es una excelente manera de ajustar y probar de forma iterativa un


paquete que está desarrollando, ya que solo funciona para un paquete instalado.
En la sección 5.4, aprenderá cómo devtools::load_all() acelera el desarrollo al
permitirle cargar un paquete fuente directamente en la memoria.

Packages libraries

Acabamos de discutir la función library(), cuyo nombre está inspirado en lo que


hace. Cuando llama a la library(foo), R busca en las bibliotecas actuales un
paquete instalado llamado "foo" y, si tiene éxito, hace que foo esté disponible
para su uso.

En R, una biblioteca es un directorio que contiene paquetes instalados, algo así


como una biblioteca para libros. Desafortunadamente, en el mundo R, con
frecuencia encontrará un uso confuso de las palabras "biblioteca" y "paquete".
Es común que alguien se refiera a dplyr, por ejemplo, como una biblioteca cuando
en realidad es un paquete. Hay algunas razones para la confusión. Primero,
podría decirse que la terminología de R va en contra de las convenciones de
programación más amplias, donde el significado habitual de "biblioteca" está más
cerca de lo que entendemos por "paquete". El nombre de la función library() en
sí misma probablemente refuerza las asociaciones incorrectas. Finalmente, este
error de vocabulario a menudo es inofensivo, por lo que es fácil para los
usuarios de R caer en el hábito incorrecto y para las personas que señalan este
error parecer pedantes insufribles. Pero aquí está el resultado final:

Usamos la función library() para cargar un package.

La distinción entre los dos es importante y útil a medida que participa en el


desarrollo de paquetes.

Puede tener múltiples bibliotecas en su computadora. De hecho, muchos de ustedes


ya lo hacen, especialmente si están en Windows. Puede usar .libPaths() para ver
qué bibliotecas están actualmente activas. Así es como podría verse esto en
Windows:

# on Windows
.libPaths()
#> [1] "C:/Users/jenny/Documents/R/win-library/3.6"
#> [2] "C:/Program Files/R/R-3.6.0/library"

lapply(.libPaths(), list.dirs, recursive = FALSE, full.names = FALSE)


#> [[1]]
#> [1] "abc" "anytime" "askpass" "assertthat"
#> ...
#> [145] "zeallot"
#>
#> [[2]]
#> [1] "base" "boot" "class" "cluster"
#> [5] "codetools" "compiler" "datasets" "foreign"
#> [9] "graphics" "grDevices" "grid" "KernSmooth"
#> [13] "lattice" "MASS" "Matrix" "methods"
#> [17] "mgcv" "nlme" "nnet" "parallel"
#> [21] "rpart" "spatial" "splines" "stats"
#> [25] "stats4" "survival" "tcltk" "tools"
#> [29] "translations" "utils"

En ambos casos vemos dos bibliotecas activas, consultadas en este orden:


 A user library
 A system-level or global library

Esta configuración es típica en Windows, pero es algo en lo que generalmente


debe optar en macOS.3 Con esta configuración, los paquetes de complementos
instalados desde CRAN (u otro lugar) o en desarrollo local se mantienen en la
user library. Arriba, el sistema macOS se usa como máquina de desarrollo
principal y tiene muchos paquetes aquí (~ 1000), mientras que el sistema Windows
solo se usa ocasionalmente y es mucho más espartano. El conjunto básico de
paquetes básicos y recomendados que se incluyen con R se encuentran en la
system-level library y son los mismos en macOS y Windows. Esta separación atrae
a muchos desarrolladores y facilita, por ejemplo, limpiar sus paquetes de
complementos sin perturbar su instalación de base R.

Si está en macOS y solo ve una biblioteca, no hay necesidad urgente de cambiar


nada. Pero la próxima vez que actualice R, considere crear una biblioteca de
nivel de usuario. Por defecto, R busca una biblioteca de usuario que se
encuentra en la ruta almacenada en la variable de entorno R_LIBS_USER, que por
defecto es ~ / Library / R / x.y / library. Cuando instale, R x.y.z y antes de
instalar cualquier paquete adicional, use dir.create ("~ / Library / R / x.y /
library") para configurar una biblioteca de usuario. Ahora tendrá la
configuración de la biblioteca que se ve arriba. Alternativamente, puede
configurar una biblioteca de usuario en otro lugar y decirle a R sobre eso
configurando la variable de entorno R_LIBS_USER en .Renviron.

Las rutas de archivo para estas bibliotecas también dejan en claro que están
asociadas con una versión específica de R (3.6.x en el momento de la escritura),
que también es típica. Esto refleja y refuerza el hecho de que necesita
reinstalar sus paquetes de complementos cuando actualiza R de, digamos, 3.5 a
3.6, lo cual es un cambio en la versión menor. Por lo general, no necesita
volver a instalar paquetes de complementos para una versión de parche, por
ejemplo, pasar de R 3.6.0 a 3.6.1.

A medida que su uso de R se vuelve más sofisticado, es común comenzar a


administrar bibliotecas de paquetes con más intención. Por ejemplo, herramientas
como renv (y su predecesor packrat) automatizan el proceso de gestión de
bibliotecas específicas del proyecto. Esto puede ser importante para hacer que
los productos de datos sean reproducibles, portátiles y aislados entre sí. Un
desarrollador de paquetes puede anteponer la ruta de búsqueda de la biblioteca
con una biblioteca temporal, que contiene un conjunto de paquetes en versiones
específicas, con el fin de explorar problemas con compatibilidad hacia adelante
y hacia atrás, sin afectar otro trabajo diario. Las verificaciones de
dependencia inversa son otro ejemplo en el que gestionamos explícitamente la
ruta de búsqueda de la biblioteca.

Estas son las principales palancas que controlan qué bibliotecas están activas,
en orden de alcance y persistencia:

 Variables de entorno, como R_LIBS y R_LIBS_USER, que se consultan al


inicio.
 Llamar a .libPaths() con una o más rutas de archivo.
 Ejecutando pequeños fragmentos de código con una ruta de búsqueda de
biblioteca alterada temporalmente a través de withr::with_libpaths() .
 Argumentos a funciones individuales, como install.packages(lib =) y
library(lib.loc =).

Finalmente, es importante tener en cuenta que la library() NUNCA debe usarse


dentro de un paquete. Los paquetes y los scripts se basan en diferentes
mecanismos para declarar sus dependencias y este es uno de los mayores ajustes
que necesita hacer en su modelo mental y sus hábitos. Exploramos este tema
completamente en el Capítulo 11.

Para ver el conjunto de rutas de archivos que deberían estar en su radar,


ejecute dir(full.names = TRUE, recursive = TRUE, include.dirs = TRUE,
all.files = TRUE) en el directorio de nivel superior del paquete.

CAPÍTULO 05 - “Fundamental development workflows”


Muchos paquetes nacen de la frustración de una persona por alguna tarea común
que debería ser más fácil. ¿Cómo debe decidir si algo es digno de un paquete? No
hay una respuesta definitiva, pero es útil apreciar al menos dos tipos de
recompensa:

 Product: your life will be better when this functionality is implemented


formally, in a package.
 Process: greater mastery of R will make you more effective in your work.

Antes de poder crear su paquete, debe encontrar un nombre para él. ¡Esta puede
ser la parte más difícil de crear un paquete! Hay tres requisitos formales:

 El nombre solo puede consistir en letras, números y puntos.


 Debe comenzar con una letra.
 No puede terminar con un punto.
Recomendamos no usar puntos en los nombres de paquetes, debido a asociaciones
confusas con extensiones de archivo y métodos S3.

LINK, sobre qué hacer si decides cambiar el nombre de tu paquete (antes de


publicarlo en CRAN): https://www.njtierney.com/post/2017/10/27/change-pkg-name/

Es imposible cumplir con todas las sugerencias para nombrar un paquete, por lo
que obviamente deberá hacer algunas compensaciones (trade-offs). El  available
package tiene una función llamada available() que le ayuda a evaluar un nombre
de paquete potencial desde muchos ángulos:

library(available)

available("doofus")
#> Urban Dictionary can contain potentially offensive results,
#> should they be included? [Y]es / [N]o:
#> 1: 1
#> ── doofus
──────────────────────────────────────────────────────────────────
#> Name valid: ✔
#> Available on CRAN: ✔
#> Available on Bioconductor: ✔
#> Available on GitHub: ✔
#> Abbreviations: http://www.abbreviations.com/doofus
#> Wikipedia: https://en.wikipedia.org/wiki/doofus
#> Wiktionary: https://en.wiktionary.org/wiki/doofus
#> Sentiment:???

Una vez que haya encontrado un nombre, hay dos formas de crear el paquete.

 Llamar usethis::create_package().
 En rstudio, hacer File > New Project > New Directory > R Package. Esto
finalmente llama usethis::create_package(), así que realmente solo hay
una manera.
No use package.skeleton() para crear un paquete. Debido a que esta función
viene con R, es posible que tenga la tentación de usarla, pero crea un paquete
que arroja errores de inmediato con la compilación R CMD. Anticipa un proceso de
desarrollo diferente al que usamos aquí, por lo que reparar este estado inicial
roto simplemente hace un trabajo innecesario para las personas que usan devtools
(y, especialmente, roxygen2).

El argumento principal y único requerido create_package()es pathdónde vivirá su


nuevo paquete:

create_package("path/to/package/pkgname")

Recuerde que este es el lugar donde vive su paquete en su fuente de forma


(sección 4.2 ), no en su instalada forma (sección 4.5 ). 

devtools trabaja de la mano con RStudio, que creemos que es el mejor entorno de
desarrollo para la mayoría de los usuarios de R.

Recomendamos encarecidamente que cada paquete fuente sea también un proyecto


RStudio.

Para ver los atajos de teclado más útiles, presione Alt + Shift + K

Un directorio que es un proyecto RStudio contendrá un


archivo .Rproj. Un archivo .Rproj es solo un archivo de texto.

Version: 1.0

RestoreWorkspace: No
SaveWorkspace: No
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
Encoding: UTF-8

AutoAppendNewline: Yes
StripTrailingWhitespace: Yes

BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
PackageRoxygenize: rd,collate,namespace

# these should usually be the same (or unset)


proj_sitrep()
#> * working_directory: '/Users/jenny/rrr/readxl'
#> * active_usethis_proj: '/Users/jenny/rrr/readxl'
#> * active_rstudio_proj: '/Users/jenny/rrr/readxl'

A medida que desarrolle su paquete, estará ejecutando el código


R. Esta será una combinación de llamadas de flujo de trabajo (por
ejemplo, document()o test()) y llamadas ad hoc que lo ayudarán a
escribir sus funciones, ejemplos y
pruebas. Nosotros recomendamos  que deje el directorio de trabajo
de su aparato de proceso de I para el nivel superior del paquete fuente.

Los ayudantes de ruta como testthat::test_path() , fs::path_package() y


el paquete rprojroot  son extremadamente útiles para construir rutas
resistentes que se mantengan en toda la gama de situaciones que
surgen durante el desarrollo y el uso. Otra forma de eliminar las rutas
frágiles es ser riguroso en el uso de los métodos adecuados para
almacenar datos dentro de su paquete (Capítulo 12 ) y apuntar al
directorio temporal de la sesión cuando sea apropiado, como para los
artefactos de prueba efímeros (Capítulo 10 ).

load_all()  es
el paso clave en este ciclo de "espuma, enjuague,
repetición" del desarrollo del paquete:

1. Ajustar una definición de función.


2. load_all()
3. Pruebe el cambio ejecutando un pequeño ejemplo o algunas
pruebas.

devtools::load_all() es
una envoltura delgada pkgload::load_all() que
agrega un poco de facilidad de uso. Es poco probable que lo
use load_all()programáticamente o dentro de otro paquete, pero si lo
hace, probablemente debería usarlo pkgload::load_all() directamente.

CAPÍTULO 06 - “R code”
El primer principio de usar un paquete es que todo el código R va en R/.

La primera ventaja práctica de usar un paquete es que es fácil volver a cargar


su código. Puede ejecutar devtools::load_all(), o en RStudio presione Ctrl /
Cmd + Shift + L, que también guarda todos los archivos abiertos, ahorrándole una
pulsación de tecla.

Organising your functions

Si bien es libre de organizar las funciones en archivos como desee, los dos
extremos son malos: no coloque todas las funciones en un archivo y no ponga cada
función en su propio archivo separado. (Está bien si algunos archivos solo
contienen una función, particularmente si la función es grande o tiene mucha
documentación). Los nombres de los archivos deben ser significativos y terminar
en .R.

# Good
fit_models.R
utility_functions.R

# Bad
foo.r
stuff.r
Evite problemas al nunca usar nombres de archivo que difieran solo en
mayúsculas.

Mi regla general es que si no puedo recordar el nombre del archivo donde vive
una función, necesito separar las funciones en más archivos o darle un mejor
nombre al archivo. (Desafortunadamente no puedes usar subdirectorios dentro de R
/. Lo mejor que puedes hacer es usar un prefijo común, por ejemplo, abc - *.
R.).

 Haga clic en el nombre de una función en el código y presione F2.


 Presione Ctrl +. luego comienza a escribir el nombre

Code style

Si está trabajando en el código de otra persona, no imponga su propio estilo. En


cambio, lea su documentación de estilo y sígala lo más de cerca posible.

El paquete formatR, de Yihui Xie, facilita la limpieza del código mal


formateado. No puede hacer todo, pero puede obtener rápidamente su código de
terrible a bastante bueno. Asegúrese de leer las notas en el sitio web antes de
usarlo ( http://yihui.name/formatR/ ). Es tan fácil como:
install.packages("formatR")
formatR::tidy_dir("R")
Un enfoque complementario es utilizar una interfaz de código. En lugar de
solucionar automáticamente los problemas, un linter simplemente te advierte
sobre ellos. El paquete lintr de Jim Hester verifica el cumplimiento de esta
guía de estilo y le permite saber dónde se ha perdido algo. En comparación con
formatR, detecta más problemas potenciales (porque no necesita solucionarlos
también), pero aún verá falsos positivos.
install.packages("lintr")
lintr::lint_package()

 Nombres de objeto

Los nombres de las variables y funciones deben estar en minúsculas. Use un guión
bajo (_) para separar las palabras dentro de un nombre (reserve “.” para métodos
S3). En general, los nombres de las variables deben ser sustantivos y los
nombres de las funciones deben ser verbos. Esfuércese por nombres concisos y
significativos (¡esto no es fácil!).
# Good
day_one
day_1

# Bad
first_day_of_the_month
DayOne
dayone
djm1

 Espaciado

Coloque espacios alrededor de todos los operadores infijos (=, +, -, <-, etc.).
La misma regla se aplica cuando se utiliza = en llamadas a funciones. Siempre
ponga un espacio después de una coma, y nunca antes (como en el inglés normal).
# Good
average <- mean(feet / 12 + inches, na.rm = TRUE)

# Bad
average<-mean(feet/12+inches,na.rm=TRUE)

Hay una pequeña excepción a esta regla :, :: y ::: no necesitan espacios a su


alrededor.

Coloque un espacio antes del paréntesis izquierdo, excepto en una llamada de


función.
# Good
if (debug) do(x)
plot(x, y)

# Bad
if(debug)do(x)
plot (x, y)
El espacio adicional (es decir, más de un espacio en una fila) está bien si
mejora la alineación de signos o asignaciones iguales (<-).
list(
total = a + b + c,
mean = (a + b + c) / n
)

No coloque espacios alrededor del código entre paréntesis o corchetes (a menos


que haya una coma, en cuyo caso, consulte más arriba).
# Good
if (debug) do(x)
diamonds[5, ]

# Bad
if ( debug ) do(x) # No spaces around debug
x[1,] # Needs a space after the comma
x[1 ,] # Space goes after comma not before

 Llaves

Una llave de apertura nunca debe ir en su propia línea y siempre debe ir seguida
de una nueva línea. Una llave de cierre debe ir siempre en su propia línea, a
menos que le siga otra cosa.

Siempre sangra (indexación) el código dentro de llaves.


# Good

if (y < 0 && debug) {


message("Y is negative")
}

if (y == 0) {
log(x)
} else {
y ^ x
}

# Bad

if (y < 0 && debug)


message("Y is negative")

if (y == 0) {
log(x)
}
else {
y ^ x
}
Está bien dejar declaraciones muy cortas en la misma línea:

if (y < 0 && debug) message("Y is negative")


 Longitud de línea

Esfuércese por limitar su código a 80 caracteres por línea. Esto cabe


cómodamente en una página impresa con una fuente de tamaño razonable. Si se está
quedando sin espacio, esta es una buena indicación de que debe encapsular parte
del trabajo en una función separada.

 Sangría

Al sangrar su código, use dos espacios. Nunca use pestañas ni mezcle pestañas y
espacios. Cambie estas opciones en el panel de preferencias de código:
knitr::include_graphics("images/style-options.png")

La única excepción es si una definición de función se ejecuta en varias líneas.


En ese caso, sangra la segunda línea donde comienza la definición:
long_function_name <- function(a = "a long argument",
b = "another argument",
c = "another long argument") {
# As usual code is indented by two spaces.
}

 Asignación

Use <-, NO =, para la asignación.


# Good
x <- 5
# Bad
x = 5

 Directrices para comentar

Comenta tu código. Cada línea de un comentario debe comenzar con el símbolo de


comentario y un solo espacio: #. Los comentarios deben explicar el por qué, no
el qué. \index{comments}

Use líneas comentadas de - y = para dividir su archivo en fragmentos fácilmente


legibles.
# Load data ---------------------------

# Plot data ---------------------------

OJO: Use el styler package (LINK: http://styler.r-lib.org/ ).

TOP-LEVEL Code

Hasta ahora, probablemente ha estado escribiendo scripts, código R guardado en


un archivo que carga con source(). Hay dos diferencias principales entre el
código en scripts y paquetes:
 En un script, el código se ejecuta cuando se carga. En un paquete, el
código se ejecuta cuando se genera. Esto significa que el código de su
paquete solo debe crear objetos, la gran mayoría de los cuales serán
funciones.
 Las funciones de su paquete se utilizarán en situaciones que no imaginó.
Esto significa que sus funciones deben ser cuidadosas en la forma en que
interactúan con el mundo exterior.

Loading code

Cuando carga un script con source(), cada línea de código se ejecuta y los
resultados están disponibles de inmediato. Las cosas son diferentes en un
paquete, porque se carga en dos pasos. Cuando se construye el paquete (por
ejemplo, CRAN), se ejecuta todo el código en R/ y se guardan los resultados.
Cuando carga un paquete, con library() o require() los resultados almacenados
en caché están disponibles para usted. Si cargó scripts de la misma manera que
los paquetes, su código se vería así:

# Load a script into a new environment and save it


env <- new.env(parent = emptyenv())
source("my-script.R", local = env)
save(envir = env, "my-script.Rdata")

# Later, in another R session


load("my-script.Rdata")

Por ejemplo, tome x <- Sys.time(). Si coloca esto en un script, x le diría


cuándo fue el script source(). Pero si coloca ese mismo código en un paquete, x
le diría cuándo se creó el paquete.

Esto significa que nunca debe ejecutar código en el top-level de un paquete: el


código del paquete solo debe crear objetos, principalmente funciones.

Describa los paquetes que su código necesita en el archivo DESCRIPTION, como


aprenderá en las dependencias de paquetes:

( https://r-pkgs.org/description.html#dependencies )

You might also like