Lo que nadie nos enseñó sobre R

Luis D. Verde Arregoitia

Temas de este bloque:

– Entornos de trabajo y configuración
– Iteración y vectorización para evitar repetición
– Trabajando con listas
– Manejo de matrices
– Atajos y herramientas para mayor eficiencia
– Errores comunes y cómo buscar soluciones


Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union

Personalizando el entorno de trabajo

Personalización

Nadie nos va a tomar en serio en la cafetería si no programamos con un fondo oscuro

-Jared Lander
📼 R: Then and now

  • Fuentes y texto - 🔗 Nerd Fonts

  • Disposición de los páneles

Personalizando el arranque en R

El archivo .Rprofile file contiene código que se ejecuta cada que arrancamos R.


.Rprofile generalmente vive en nuestro directorio de inicio

Podemos modificarlo con usethis::edit_r_profile()

Usar con precaución para no perder reproducibilidad

Arranque

  • Saludos o recordatorios con cowsay
#>  ----- 
#> No olviden tomar mucha agua 
#>  ------ 
#>     \   
#>      \
#>   ><((((º>  ><((((º>  ><((((º>  ><((((º>  ><((((º>
#>       
  • Ayuda con errores de dedo con fcuk
> lenght(1:12)
Error in lenght(1:12) : could not find function "lenght"
> fcuk::init_error_tracker()
> lenght(1:12)
Error in lenght(1:12) : could not find function "lenght"
Did you mean : length or ...length ?

Iteración

Aplicando una función varias veces

Copiar/pegar código para editarlo en análisis repetitivos agrega pasos innecesarios, pierde tiempo, y aumenta el riesgo de introducir errores


Nick Holt (2017)
Function Iterations in R

Ejercicio - futbol

El archivo tabla_futbol.csv contiene la clasifición en la tabla global de la FIFA de los primeros 20 países de 1994 a 2022. Agrupa paises en diferentes confederaciones.


¿De qué confederación fue el equipo 20 cada año?

ej. para 1994 Zambia fue #20 y su confederación es “CAF”

Copiando, pegando, y editando

ranking1994 <- fifa20esp[fifa20esp$periodo=="1994-06-14",]
pais201994 <- ranking1994[ranking1994$posicion==20,]$pais
pais201994
ranking1995 <- fifa20esp[fifa20esp$periodo=="1995-06-13",]
pais201995 <- ranking1995[ranking1995$posicion==20,]$pais
pais201995

Siguiendo así seguramente introducimos algún error poco evidente y difícil de detectar

Datos agrupados

La mayoría de nuestras tareas se pueden desarrollar siguiendo el paradigma “dividir-aplicar-combinar” ( “split-apply-combine”):

  • dividir los datos en grupos
  • aplicar alguna función a cada grupo
  • combinar los resultados

dplyr::group_by()

  • Define grupos según una o más variables
  • Estratifica un data frame
  • equivalente a aggregate() y al argumento ‘by =’ de data.table

Manipulación de datos en R con dplyr - Rubén Sánchez

Trabajando con datos agrupados

Con la versión agrupada de nuestra tabla, las funciones de dplyr trabajan sobre cada grupo por separado y después se combinan los resultados.


Opciones para datos agrupados

  • resumir valores (media, mediana, etc. por grupo)
  • extraer las primeras o últimas n filas por grupo
  • identificar valores máximos o mínimos
  • eliminar filas repetidas
  • contar observaciones, etc.

Datos msleep

Rasgos de 83 especies de mamíferos y sus horas de sueño. derivados de Savage & West (2007) e incluidos con ggplot2.

name genus vore order conservation sleep_total sleep_rem sleep_cycle awake brainwt bodywt
Cheetah Acinonyx carni Carnivora lc 12.1 NA NA 11.9 NA 50.000
Owl monkey Aotus omni Primates NA 17.0 1.8 NA 7.0 0.01550 0.480
Mountain beaver Aplodontia herbi Rodentia nt 14.4 2.4 NA 9.6 NA 1.350
Greater short-tailed shrew Blarina omni Soricomorpha lc 14.9 2.3 0.1333333 9.1 0.00029 0.019
Cow Bos herbi Artiodactyla domesticated 4.0 0.7 0.6666667 20.0 0.42300 600.000
Three-toed sloth Bradypus herbi Pilosa NA 14.4 2.2 0.7666667 9.6 NA 3.850

Máximo brainwt para cada orden

msleep %>% group_by(order) %>% 
  slice_max(brainwt,n=1)
# A tibble: 21 × 11
# Groups:   order [19]
   name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
   <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
 1 Tenrec Tenr… omni  Afro… <NA>                15.6       2.3      NA       8.4
 2 Cow    Bos   herbi Arti… domesticated         4         0.7       0.667  20  
 3 Gray … Hali… carni Carn… lc                   6.2       1.5      NA      17.8
 4 Pilot… Glob… carni Ceta… cd                   2.7       0.1      NA      21.4
 5 Commo… Phoc… carni Ceta… vu                   5.6      NA        NA      18.4
 6 Bottl… Turs… carni Ceta… <NA>                 5.2      NA        NA      18.8
 7 Big b… Epte… inse… Chir… lc                  19.7       3.9       0.117   4.3
 8 Giant… Prio… inse… Cing… en                  18.1       6.1      NA       5.9
 9 North… Dide… omni  Dide… lc                  18         4.9       0.333   6  
10 Phala… Phal… <NA>  Dipr… <NA>                13.7       1.8      NA      10.3
# ℹ 11 more rows
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

Muestrar una fila al azar de cada grupo

msleep %>% group_by(order) %>% 
  slice_sample(n=1)
# A tibble: 19 × 11
# Groups:   order [19]
   name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
   <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
 1 Tenrec Tenr… omni  Afro… <NA>                15.6       2.3      NA       8.4
 2 Roe d… Capr… herbi Arti… lc                   3        NA        NA      21  
 3 Arcti… Vulp… carni Carn… <NA>                12.5      NA        NA      11.5
 4 Pilot… Glob… carni Ceta… cd                   2.7       0.1      NA      21.4
 5 Littl… Myot… inse… Chir… <NA>                19.9       2         0.2     4.1
 6 Giant… Prio… inse… Cing… en                  18.1       6.1      NA       5.9
 7 North… Dide… omni  Dide… lc                  18         4.9       0.333   6  
 8 Potor… Poto… herbi Dipr… <NA>                11.1       1.5      NA      12.9
 9 Deser… Para… <NA>  Erin… lc                  10.3       2.7      NA      13.7
10 Rock … Proc… <NA>  Hyra… lc                   5.4       0.5      NA      18.6
11 Rabbit Oryc… herbi Lago… domesticated         8.4       0.9       0.417  15.6
12 Short… Tach… inse… Mono… <NA>                 8.6      NA        NA      15.4
13 Horse  Equus herbi Peri… domesticated         2.9       0.6       1      21.1
14 Three… Brad… herbi Pilo… <NA>                14.4       2.2       0.767   9.6
15 Macaq… Maca… omni  Prim… <NA>                10.1       1.2       0.75   13.9
16 Afric… Loxo… herbi Prob… vu                   3.3      NA        NA      20.7
17 Weste… Euta… herbi Rode… <NA>                14.9      NA        NA       9.1
18 Tree … Tupa… omni  Scan… <NA>                 8.9       2.6       0.233  15.1
19 Lesse… Cryp… omni  Sori… lc                   9.1       1.4       0.15   14.9
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

Resumiendo valores

msleep %>% group_by(order) %>% 
  summarize(mediana_slp = median(sleep_total),
            media_brainwt=mean(brainwt))
# A tibble: 19 × 3
   order           mediana_slp media_brainwt
   <chr>                 <dbl>         <dbl>
 1 Afrosoricida           15.6      0.0026  
 2 Artiodactyla            3.9     NA       
 3 Carnivora              10.2     NA       
 4 Cetacea                 5.2     NA       
 5 Chiroptera             19.8      0.000275
 6 Cingulata              17.8      0.0459  
 7 Didelphimorphia        18.7     NA       
 8 Diprotodontia          12.4     NA       
 9 Erinaceomorpha         10.2      0.00295 
10 Hyracoidea              5.4      0.0152  
11 Lagomorpha              8.4      0.0121  
12 Monotremata             8.6      0.025   
13 Perissodactyla          3.1      0.414   
14 Pilosa                 14.4     NA       
15 Primates                9.9     NA       
16 Proboscidea             3.6      5.16    
17 Rodentia               12.9     NA       
18 Scandentia              8.9      0.0025  
19 Soricomorpha           10.3      0.000592

Bucles (for loops)

  • De gran utilidad
  • No siempre es necesario escribirlos de 0

Bucles

for (value in sequence){
   statement(s)
}

Executa una serie de enunciados (statements), una vez para cada elemento de un vector o lista. Se detiene al llegar al último elemento.

for (x in 1:7){
  print(x)
} 
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7

Ejercicio - loops

Escribir un bucle para imprimir en la consola cada letra del alfabeto, en minúscula y en orden descendiente (z,y,x,w…)

hay constantes preinstaladas en R que les pueden servir

Bucles y grupos

msleep %>% 
  group_by(order) %>% # para cada orden
  slice_sample(1) # declaración a ejecutar 

Todo se queda dentro del data frame

Vectorización

Operaciones que ocurren en paralelo en todos los elementos (de un vector, lista, etc.) y no uno por uno en cada elemento

¿Aquí qué pasa?

x <- c(1,3,12,4,7,8)
x > 5

Los operadores lógicos (entre muchos otros) son vectorizados

x <- c(1,3,12,4,7,8)
x > 5
[1] FALSE FALSE  TRUE FALSE  TRUE  TRUE

No hace falta teclear todo ésto o escribir un bucle

x[1]>5 ; x[2]>5
x[3]>5 ; x[4]>5
x[5]>5 ; x[6]>5

American Greetings

Cuando sí necesitemos iterar:

📦 purrr - Herramientas para programación funcional

  • funciones map que aplican una función a cada elemento de un input y devuelve un resultado de la misma longitud que el input
  • trabaja bien con listas
  • código legible y conciso

map(.x, .f, …)


para cada elemento de .x

aplica .f

... argumentos para .f

“Mapeando” funciones a datos


map(.x,.f)

.f se puede especificar como:

  • una función existente

  • una función anónima definida sobre la marcha

  • una fórmula: notación abreviada para funciones

  • una función anónima abreviada (shorthand) en versiones recientes de R

Funciones

Learn by Example.com

Definiendo funciones

usamos la función ‘function()

function( arglist ) expr


argumentos (arglist): valores para la función

expresión (expr): un objeto que representa una acción que R puede hacer

Las expresiones pueden tener una o maś declaraciones

Definiendo funciones

mi_funcion <- function(mi_argumento){
  mi_argumento+1 # declaración
}

mi_vector <- c(3,5,6,7)

mi_funcion(mi_argumento = mi_vector)
[1] 4 6 7 8

El cuerpo de la función (las declaraciones que se ejecutan al correr la función) se agrupa con llaves ({})

miFunc <- function(x) {
  x + 4 # cuerpo
}


miFunc(6)
[1] 10
miFunc(x=6)
[1] 10

Al ejecutar funciones es opcional especificar los nombres de los argumentos, pero en funciones con >1 argumentos, el orden importa

PERO no hacen falta llaves para funciones con una sola declaración

f <- function(x) x+4   
f(x=6)
[1] 10
f <- function(x) mean(x)/2   
f(c(6,43,12,5,7))
[1] 7.3

Las llaves rodean el cuerpo en funciones con dos o más declaraciones

f <- function(x)  y <- (x*0.2885) log(y) # ERROR  

Así sí funciona. Las declaraciones (statements) están en líneas separadas

f <- function(x) {
  y <- (x*0.2885) # una declaración
  log(y)          # otra declaración
}

f(5)
[1] 0.3663777

Funciones anónimas

Funciones para llevar (se crean y se ejecutan pero nunca se asignan a un objeto con nombre)

Sintaxis

(function(x) x * x + 3)(10)
[1] 103

La definición va entre paréntesis para separar la función de sus argumentos

(function(x) x + 3)(10)

Es lo mismo que:

f <- function(x) x + 3
f(10)
# o bien 
f <- function(x) {x + 3}
f(10)

Notation corta (desde R v4.1.0)

Reemplaza “function(x) {}” con “\(x){}

(\(x) x + 3)(10)
[1] 13
(\(x) x / 2)(10)
[1] 5

Russ Hyde (2021)
New features in R 4.1.0

Los desarroladores del tidyverse están migrando al uso de esta notación

Funciones anónimas

  • Útiles para aplicar una función personalizada a varios elementos a la vez

  • También conocidas como expresiones lambda

  • Autocontenidas

  • Comparables con métodos parecidos en Python

Por qué escribir nuestras propias funciones

  • Menos repetición

  • Mayor brevedad

  • Menor posibilidad de errores

  • Aprovechar las herramientas que nos dejan aplicar funciones a muchos elementos a la vez

Jenny Bryan - Stat545
Write your own R functions

Listas

Listas

Objetos que pueden contenter elementos de diferentes tipos como números, cadenas de texto, vectors, tablas, o incluso más listas

mi_lista <- list(
  un_numero = 7,
  un_vector = c("rata", "gato", "taco"),
  un_dataframe = data.frame(
    a = 1:3, b = c("K", "L", "M")))

Rebecca Barter (2019)
Learn to purrr

mi_lista
$un_numero
[1] 7

$un_vector
[1] "rata" "gato" "taco"

$un_dataframe
  a b
1 1 K
2 2 L
3 3 M

Podemos creas listas partiendo otros objetos

Separando una data frame agrupada en una lista de data frames, una para cada grupo.

gremios <- 
  msleep %>% group_by(vore) %>%
  group_split()

gremios
<list_of<
  tbl_df<
    name        : character
    genus       : character
    vore        : character
    order       : character
    conservation: character
    sleep_total : double
    sleep_rem   : double
    sleep_cycle : double
    awake       : double
    brainwt     : double
    bodywt      : double
  >
>[5]>
[[1]]
# A tibble: 19 × 11
   name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
   <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
 1 Cheet… Acin… carni Carn… lc                  12.1      NA        NA      11.9
 2 North… Call… carni Carn… vu                   8.7       1.4       0.383  15.3
 3 Dog    Canis carni Carn… domesticated        10.1       2.9       0.333  13.9
 4 Long-… Dasy… carni Cing… lc                  17.4       3.1       0.383   6.6
 5 Domes… Felis carni Carn… domesticated        12.5       3.2       0.417  11.5
 6 Pilot… Glob… carni Ceta… cd                   2.7       0.1      NA      21.4
 7 Gray … Hali… carni Carn… lc                   6.2       1.5      NA      17.8
 8 Thick… Lutr… carni Dide… lc                  19.4       6.6      NA       4.6
 9 Slow … Nyct… carni Prim… <NA>                11        NA        NA      13  
10 North… Onyc… carni Rode… lc                  14.5      NA        NA       9.5
11 Tiger  Pant… carni Carn… en                  15.8      NA        NA       8.2
12 Jaguar Pant… carni Carn… nt                  10.4      NA        NA      13.6
13 Lion   Pant… carni Carn… vu                  13.5      NA        NA      10.5
14 Caspi… Phoca carni Carn… vu                   3.5       0.4      NA      20.5
15 Commo… Phoc… carni Ceta… vu                   5.6      NA        NA      18.4
16 Bottl… Turs… carni Ceta… <NA>                 5.2      NA        NA      18.8
17 Genet  Gene… carni Carn… <NA>                 6.3       1.3      NA      17.7
18 Arcti… Vulp… carni Carn… <NA>                12.5      NA        NA      11.5
19 Red f… Vulp… carni Carn… <NA>                 9.8       2.4       0.35   14.2
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

[[2]]
# A tibble: 32 × 11
   name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
   <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
 1 Mount… Aplo… herbi Rode… nt                  14.4       2.4      NA       9.6
 2 Cow    Bos   herbi Arti… domesticated         4         0.7       0.667  20  
 3 Three… Brad… herbi Pilo… <NA>                14.4       2.2       0.767   9.6
 4 Roe d… Capr… herbi Arti… lc                   3        NA        NA      21  
 5 Goat   Capri herbi Arti… lc                   5.3       0.6      NA      18.7
 6 Guine… Cavis herbi Rode… domesticated         9.4       0.8       0.217  14.6
 7 Chinc… Chin… herbi Rode… domesticated        12.5       1.5       0.117  11.5
 8 Tree … Dend… herbi Hyra… lc                   5.3       0.5      NA      18.7
 9 Asian… Elep… herbi Prob… en                   3.9      NA        NA      20.1
10 Horse  Equus herbi Peri… domesticated         2.9       0.6       1      21.1
# ℹ 22 more rows
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

[[3]]
# A tibble: 5 × 11
  name    genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
  <chr>   <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
1 Big br… Epte… inse… Chir… lc                  19.7       3.9       0.117   4.3
2 Little… Myot… inse… Chir… <NA>                19.9       2         0.2     4.1
3 Giant … Prio… inse… Cing… en                  18.1       6.1      NA       5.9
4 Easter… Scal… inse… Sori… lc                   8.4       2.1       0.167  15.6
5 Short-… Tach… inse… Mono… <NA>                 8.6      NA        NA      15.4
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

[[4]]
# A tibble: 20 × 11
   name   genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
   <chr>  <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
 1 Owl m… Aotus omni  Prim… <NA>                17         1.8      NA       7  
 2 Great… Blar… omni  Sori… lc                  14.9       2.3       0.133   9.1
 3 Grivet Cerc… omni  Prim… lc                  10         0.7      NA      14  
 4 Star-… Cond… omni  Sori… lc                  10.3       2.2      NA      13.7
 5 Afric… Cric… omni  Rode… <NA>                 8.3       2        NA      15.7
 6 Lesse… Cryp… omni  Sori… lc                   9.1       1.4       0.15   14.9
 7 North… Dide… omni  Dide… lc                  18         4.9       0.333   6  
 8 Europ… Erin… omni  Erin… lc                  10.1       3.5       0.283  13.9
 9 Patas… Eryt… omni  Prim… lc                  10.9       1.1      NA      13.1
10 Galago Gala… omni  Prim… <NA>                 9.8       1.1       0.55   14.2
11 Human  Homo  omni  Prim… <NA>                 8         1.9       1.5    16  
12 Macaq… Maca… omni  Prim… <NA>                10.1       1.2       0.75   13.9
13 Chimp… Pan   omni  Prim… <NA>                 9.7       1.4       1.42   14.3
14 Baboon Papio omni  Prim… <NA>                 9.4       1         0.667  14.6
15 Potto  Pero… omni  Prim… lc                  11        NA        NA      13  
16 Afric… Rhab… omni  Rode… <NA>                 8.7      NA        NA      15.3
17 Squir… Saim… omni  Prim… <NA>                 9.6       1.4      NA      14.4
18 Pig    Sus   omni  Arti… domesticated         9.1       2.4       0.5    14.9
19 Tenrec Tenr… omni  Afro… <NA>                15.6       2.3      NA       8.4
20 Tree … Tupa… omni  Scan… <NA>                 8.9       2.6       0.233  15.1
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

[[5]]
# A tibble: 7 × 11
  name    genus vore  order conservation sleep_total sleep_rem sleep_cycle awake
  <chr>   <chr> <chr> <chr> <chr>              <dbl>     <dbl>       <dbl> <dbl>
1 Vesper… Calo… <NA>  Rode… <NA>                 7        NA        NA      17  
2 Desert… Para… <NA>  Erin… lc                  10.3       2.7      NA      13.7
3 Deer m… Pero… <NA>  Rode… <NA>                11.5      NA        NA      12.5
4 Phalan… Phal… <NA>  Dipr… <NA>                13.7       1.8      NA      10.3
5 Rock h… Proc… <NA>  Hyra… lc                   5.4       0.5      NA      18.6
6 Mole r… Spal… <NA>  Rode… <NA>                10.6       2.4      NA      13.4
7 Musk s… Sunc… <NA>  Sori… <NA>                12.8       2         0.183  11.2
# ℹ 2 more variables: brainwt <dbl>, bodywt <dbl>

class(gremios)
[1] "vctrs_list_of" "vctrs_vctr"    "list"         

group_keys() regresa los grupos

msleep %>% group_by(vore) %>%
  group_keys()
# A tibble: 5 × 1
  vore   
  <chr>  
1 carni  
2 herbi  
3 insecti
4 omni   
5 <NA>   

‘Indexando’ listas

Hadley Wickam (2015) en Twitter

Accediendo a elementos de listas

Primer elemento ([[1]])

gremios[[1]] %>% 
  select(name,genus) %>% head
# A tibble: 6 × 2
  name                 genus        
  <chr>                <chr>        
1 Cheetah              Acinonyx     
2 Northern fur seal    Callorhinus  
3 Dog                  Canis        
4 Long-nosed armadillo Dasypus      
5 Domestic cat         Felis        
6 Pilot whale          Globicephalus

Segundo elemento

gremios[[2]] %>% 
  select(name,genus, vore, conservation) %>% 
  head
# A tibble: 6 × 4
  name             genus      vore  conservation
  <chr>            <chr>      <chr> <chr>       
1 Mountain beaver  Aplodontia herbi nt          
2 Cow              Bos        herbi domesticated
3 Three-toed sloth Bradypus   herbi <NA>        
4 Roe deer         Capreolus  herbi lc          
5 Goat             Capri      herbi lc          
6 Guinea pig       Cavis      herbi domesticated

Luis (2017)
Export Iteratively

¿Para qué usar listas?

  • Clase versatil para almanecir varios tipos de objetos

  • Fáciles de crear partiendo otros objetos

  • Cada elemento puede tener nombre

‘Mapeo’ de funciones a datos

  • Aplicar funciones iterativamente

  • Importar varios archivos en un solo comando

  • Modificar y/o exportar múltiples objetos

Aplicar funciones iterativamente

library(datos)
library(purrr)
# tres vectores (numéricos)
masa <- pinguinos$masa_corporal_g
pico <- pinguinos$largo_pico_mm
aleta <- pinguinos$largo_aleta_mm
# juntarlos en una lista
rasgos <- list(masa,pico,aleta)
# aplicar la función "mean" a cada elemento
map(rasgos,mean)
[[1]]
[1] NA

[[2]]
[1] NA

[[3]]
[1] NA

con argumentos adicionales

# aplicar la función "mean" a cada elemento
map(rasgos,mean,na.rm=TRUE)
[[1]]
[1] 4201.754

[[2]]
[1] 43.92193

[[3]]
[1] 200.9152

Aplicar funciones personalizadas iterativamente

# obtener min, max, y la diferencia
resumenMMR <- function(x){
  min_x <- min(x,na.rm = TRUE)
  max_x <- max(x,na.rm = TRUE)
  maxmin <- max_x - min_x
  c(min_x, max_x, maxmin)
}

Probar con vectores

resumenMMR(masa)
[1] 2700 6300 3600
resumenMMR(aleta)
[1] 172 231  59

map() para aplicar nuestra función a la lista

Solo usamos el nombre de la función

map(.x = rasgos, .f = resumenMMR)
[[1]]
[1] 2700 6300 3600

[[2]]
[1] 32.1 59.6 27.5

[[3]]
[1] 172 231  59

map() con salidas específicas

map() regresa listas

map_lgl() regresa un vector T/F

map_int() regresa un vector numérico

map_dbl() regresa un vector numércico (con decimales)

map_chr() regresa un vector de caracteres

map_df() junta todo en un data frame

# regresa una lista
map(rasgos, median, na.rm = TRUE)
[[1]]
[1] 4050

[[2]]
[1] 44.45

[[3]]
[1] 197
# aplana la lista en un vector
map_dbl(rasgos, median, na.rm = TRUE)
[1] 4050.00   44.45  197.00

map() con funciones anónimas

Funciones que podemos escribir dentro de map() sin definir

Mismo comportamiento

listaNums <- list(c(5:10),c(20:27))
# función anónima
map(listaNums, function(x) x+2)
# fórmula
map(listaNums, ~ .x + 2)
# notación 'nueva'
map(listaNums,\(x) x+2)

En notación de fórmula (usando ~):

.x siempre se refiere al elemento del vector o lista con el que estamos iterando

Internamente ~.x + 4 se vuelve function(x) x+4

Importando o escribiendo muchos archivos

map(.x,.f)

.x puede ser una lista o vector de rutas de archivo

.f puede ser una función que lee o escribe archivos

📄📄📄📄📄📄📄📄📄

Ejercicio

Crear una carpeta llena de archivos de texto

  • cargar el archivo resultados_21k.csv

  • agrupar los datos por localidad y crear una lista de data frames con una para cada localidad

  • crear un vector con los nombres de las localidades

😲 es posible iterar con dos inputs en paralelo

map() con dos inputs

map2(.x, .y, .f)

Ambas listas of vectores de entrada se le pasan como argumentos a la función .f

Altman et al. (2021)
Map with multiple inputs

Ejercicio - Carpeta con archivos

  • crear una carpeta “resultados21k”

  • usar here() para crear rutas estables y porátiles para cada localidad, por ejemplo: here("datos","resultados21k","Usaquen"), teniendo en cuante que here() es una función vectorizada

  • pasar la lista de data frames y el vector de rutas a write_csv de readr o write.csv de R base

🔥🏃🔥

Ejercicio - Importando varios archivos a la vez

  • usar dir_ls() para crear un vector con las rutas de los archivos creados en el paso anterior

  • importar cada elemento de este vector con map() y read_csv() de readr

  • usar funciones con regresos específicos para terminar con la tabla inicial

Atajos y herramientas para mayor eficiencia

Programando eficientemente

Ctrl == ⌘ Command && Alt == ⌥ Option

  • cursor multilinea (ctrl+alt+arriba) o (ctrl+alt+abajo)
  • quitar con esc

Atajos de teclado

  • panel de atajos (alt+shift+k)
  • insertar ‘pipe’ (ctrl+shift+m)
  • operador de asignación (alt+-)
  • arrastrar línea (alt+up) or (alt+down)
  • ejecutar línea (ctrl+enter)
  • indentar o ‘desindentar’ selección (tab y shift+tab)
  • convertir selección a comentario (ctrl + shift + c)

Atajos útiles

  • Cambiar enfoque entre paneles
    • (ctrl+1 hasta 8)
    • Maximizar paneles con (ctrl+shift+1 hasta 8)

Más atajos

Modificar selección ctrl+alt+shift+m

Para acceder a la documentación ? o F1

Abriendo objetos en el visualizador

ctrl + click

Abrir el directorio de trabajo

shell.exec(getwd()) en Windows y en Linux browseURL(getwd())

Práctica

Exploremos la diversidad de paquetes que hay en CRAN hoy mismo:

library(dplyr)
library(stringr)
p_db <- tools::CRAN_package_db()
p_db <- p_db %>% select(Package, Author, Description, Title)

📦 annotater

Agregar detalles sobre los paquetes que estamos mencionando en nuestros scripts

Fuente y versión

library(dplyr)   # CRAN v1.0.7
library(janitor) # CRAN v2.1.0

Título, fuente y versión

library(readr) # Read Rectangular Text Data, CRAN v2.0.2
  • También podemos anotar cuáles funciones o datos de c/ paquete estamos usando

📦 littleboxes

Cajas para títulos

##%##################################################%##
#                                                      #
####    Mi análisis en R ,  Luis, Oct 2022          ####
#                                                      #
##%##################################################%##

📦 packup

https://github.com/MilesMcBain/packup

Acomoda los llamados a library() al principio del archivo, quitando duplicados y ordenando alfabéticamente.

El orden alfabético puede no ser adecuado

Secciones de código y el esquema de documento

# Mi sección nueva ------------------------------------ 

Dividir un script en segmentos discretos

Las secciones se pueden colapsar y funcionan con el panel de navegación del editor de fuente.

  • Crear con cuatro guiones después de un comentario
  • Insertar con ctrl + shift + R

Utilidades geniales

📦 datapasta

Copiar y pegar datos desde y hacia R, manipular vectores

Errores comunes y como solucionarlos

1 - Resetear

Reiniciar R (limpia la ruta de búsqueda, “desprende” objetos, regresa opciones a sus valores predeterminados)

search path: los entornos que definen los objetos y funciones a los que podemos acceder desde el entorno de trabajo global

prueba

(e.g. Sys.setenv(LANGUAGE="ko"))

2 - Reprex (ejemplos reproducibles)

Crear el ejemplo más simple posible que genere el mismo error para poder confimar o resolver algún problema

Errores comunes

  • paquetes sin cargar o cargados en desorden (search path)
  • operadores cambiados, signos
  • espacios, paréntesis, o comas de más o de menos
  • pasos en desorden

Opciones útiles

  • Estudiar los mensajes de error más comunes

Emily Jennings-Dobbs (2021)
Common Errors in R

  • Correr los ejemplos disponibles con la ayuda y comparar con nuestro código

Buscando ayuda

Otras personas

Posit Community

Grupos de usuarios locales o de RLadies

StackOverflow

Twitter u otras redes sociales

GitHub - issues (cerrados o abiertos)

🧐 Modales!

Ejemplos reproducibles

  • ¿Podemos reproducir nuestro error con un ejemplo simple y concreto?
  • Ayudemos a otros a que nos puedan ayudar, permitiendo que otros puedan llegar al mismo problema en sus propias máquinas

  • Usar datos preinstalados o crear datos simples de 0

Un buen ‘reprex’

  • Proveer datos (mientras más simple mejor)
    • No ir más allá de lo mínimo necesario para recrear el problema
    • No truncar posibles fuentes de error
  • Mostrar qué paquetes se están usando
    • Incluir versiones puede ayudar
  • Se puede copiar, pegar y ejecutar fácilmente
  • No hace daño

📦 {reprex}

Muestra el input y su salida juntos

  • copiar código al portapapeleles
  • ejecutar reprex()
  • el ejemplo está listo para pegar en donde necesitmos compartir nuestra duda

La salida de reprex está diseñana para que la vean otras personas

Creando un reprex

library(ggplot2)
set.seed(23)
mis_datos <- data.frame(
  sitio= sample(c("A","B","C"),100,replace = TRUE),
  valor_A = rnorm(100),
  valor_B= rnorm(100,mean = 30,sd=10))

head(mis_datos)

ggplot(mis_datos)+
  geom_point(aes(medida_A,medida_B))

Búsquedas web

Nadie sabe todo de memoria y hay que saber buscar en línea

  • Aprender a usar funciones avanzadas en los buscadores populares “Google-fu”

  • Conocer la terminología general
    “R subset rows partial match”

  • Hacer búsquedas amplias (ej: no buscar partes de un mensaje que error que a nadie más le aparecerían)

Error: object ‘tesis_luis_23w-final’ not found

¿Cuáles soluciones son mejores útiles?