¿Qué es R?

  • Un Lenguaje de programación dominio-específico para estadísticas y análisis de datos
  • Una colección de más de 15000 paquetes
  • Una comunidad grande y activa en la industria y el mundo académico
  • Una forma de hablar “directamente” a la computadora

Históricamente:

  • Basado en el lenguaje de programación S
  • 20 años (el linaje data de 1975 - hace casi 40 años)

 

Rstudio

Entorno de desarrollo integrado (IDE) para R. Incluye:

  • Una consola
  • Editor con resaltado de sintaxis que permite la ejecución directa de código
  • Herramientas para graficar, depurar y gestionar código con espacios de trabajo


Elementos del lenguaje R

  • Vectores
  • Listas
  • Matrices
  • Arreglos (arrays)
  • Marcos de datos (data frames)
  • Cuadros de datos (tables)
  • Funciones (incluidos los operadores)
  • Atributos

Estructura de datos

La estructura de datos básica en R es el vector. Hay dos tipos básicos de vectores: vectores atómicos y listas.

Tienen tres propiedades comunes:

  • Clase, class() (~ clase/modo)
  • Longitud, length() (número de elementos)
  • Atributos, attributes() (metadatos)

Difieren en los tipos de sus elementos: todos los elementos de un vector atómico deben ser del mismo tipo, mientras que los elementos de una lista pueden tener diferentes tipos.

 

pull request

 

R no tiene elementos de 0 dimensiones (escalares). Los números o cadenas individuales son en realidad vectores de longitud uno.

Vectores atómicos

Tipos de vectores atómicos:

  • Lógico (booleano)
  • Números enteros
  • Numérico (doble)
  • Caracteres

Los vectores se construyen usando c():

x <- 1
x1 <- c(1)

all.equal(x, x1)
## [1] TRUE
class(x)
## [1] "numeric"
y <- "something"

class(y)
## [1] "character"
w <- 1L

class(w)
## [1] "integer"
z <- TRUE

class(z)
## [1] "logical"
q <- factor(1)

class(q)
## [1] "factor"

 

Los vectores solo pueden contener entradas del mismo tipo. Los diferentes tipos serán obligados al tipo más flexible:

v <- c(10, 11, 12, 13)

class(v)
## [1] "numeric"
is.integer(v)
## [1] FALSE
y <- c("Amazona", "Ara", "Eupsittula", "Myiopsitta")

class(y)
## [1] "character"
is.integer(y)
## [1] FALSE
x <- c(1,2,3, "Myiopsitta")

x
## [1] "1"          "2"          "3"          "Myiopsitta"
class(x)
## [1] "character"

 

 

Ejercicio 1

  • Cree un vector de caracteres con los nombres de los 5 primeros meses del año

  • Cree un vector numérico que contenga números negativos y positivos

  • Cree un vector con números enteros. Verifíquelo con la función is.integer()

 

Los valores que faltan se especifican con NA, que es un vector lógico de longitud 1. NA siempre se fuerza a coincidir al tipo correcto de elemento si se usa dentro de c():


v <- c(10, 11, 12, 13, NA)

class(v)
## [1] "numeric"

v <- c(letters[1:3], NA)

class(v)
## [1] "character"

 

Listas

Puede contener objetos de diferentes clases y tamaños. Las listas se crean utilizando list():

l <- list(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, TRUE, FALSE, FALSE, FALSE))

l
## $ID
## [1] "a" "b" "c" "d" "e"
## 
## $size
## [1]  0.7162614 -1.4394273 -1.3071781 -1.6310807  0.1348704 -0.1924350
## 
## $observed
## [1] FALSE  TRUE FALSE FALSE FALSE
class(l)
## [1] "list"
str(l)
## List of 3
##  $ ID      : chr [1:5] "a" "b" "c" "d" ...
##  $ size    : num [1:6] 0.716 -1.439 -1.307 -1.631 0.135 ...
##  $ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE

 

… y dimensiones:

l <- list(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, TRUE, FALSE, FALSE, FALSE), l)

str(l)
## List of 4
##  $ ID      : chr [1:5] "a" "b" "c" "d" ...
##  $ size    : num [1:6] -0.122 2.723 0.399 2.14 -0.195 ...
##  $ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE
##  $         :List of 3
##   ..$ ID      : chr [1:5] "a" "b" "c" "d" ...
##   ..$ size    : num [1:6] 0.716 -1.439 -1.307 -1.631 0.135 ...
##   ..$ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE
l2 <- list(l, l)

str(l2)
## List of 2
##  $ :List of 4
##   ..$ ID      : chr [1:5] "a" "b" "c" "d" ...
##   ..$ size    : num [1:6] -0.122 2.723 0.399 2.14 -0.195 ...
##   ..$ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE
##   ..$         :List of 3
##   .. ..$ ID      : chr [1:5] "a" "b" "c" "d" ...
##   .. ..$ size    : num [1:6] 0.716 -1.439 -1.307 -1.631 0.135 ...
##   .. ..$ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE
##  $ :List of 4
##   ..$ ID      : chr [1:5] "a" "b" "c" "d" ...
##   ..$ size    : num [1:6] -0.122 2.723 0.399 2.14 -0.195 ...
##   ..$ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE
##   ..$         :List of 3
##   .. ..$ ID      : chr [1:5] "a" "b" "c" "d" ...
##   .. ..$ size    : num [1:6] 0.716 -1.439 -1.307 -1.631 0.135 ...
##   .. ..$ observed: logi [1:5] FALSE TRUE FALSE FALSE FALSE

 

Ejercicio 2

  • Haga una lista con los 3 vectores creados en el ejercicio 1

Atributos

Los objetos pueden tener atributos. Los atributos permiten almacenar metadatos sobre el objeto. Los atributos son una especie de listas con nombre. Se puede acceder a los atributos individualmente con attr() o todos a la vez (como una lista) con attributes():

y <- 1:10

mean(y)
## [1] 5.5
attr(y, "my_attribute") <- "This is not an apple"


attr(y, "my_attribute")
## [1] "This is not an apple"
str(y)
##  int [1:10] 1 2 3 4 5 6 7 8 9 10
##  - attr(*, "my_attribute")= chr "This is not an apple"

 

La mayoría de los atributos se pierden al modificar un vector:

attributes(y[1])
## NULL

 

Los únicos atributos que no se pierden son los tres más importantes:

  • Nombres, un vector de caracteres que da nombre a cada elemento
  • Dimensiones
  • Clase

w <- structure(c(a =1, b = 2), my_attribute = "Arequipa 2019")

class(w)
## [1] "numeric"
attributes(w)
## $names
## [1] "a" "b"
## 
## $my_attribute
## [1] "Arequipa 2019"
attributes(w[1])
## $names
## [1] "a"
class(w[1])
## [1] "numeric"

 

Nombres

Los vectores se pueden nombrar de tres maneras:

  • Al crearlo: x <- c(a = 1, b = 2, c = 3)
  • Al modificar un vector existente en su lugar: x <- 1:3; names(x) <- c("a", "b", "c") O: x <- 1:3; names(x)[[1]] <- c("a")
  • Al crear una copia modificada de un vector: x <- setNames(1: 3, c ("a", "b", "c"))
y <- c(a = 1, 2, 3)

names(y)
## [1] "a" ""  ""
v <- c(1, 2, 3)

names(v) <- c('a')

names(v)
## [1] "a" NA  NA
z <- setNames(1:3, c("a", "b", "c"))

names(z)
## [1] "a" "b" "c"

 

Ejercicio 3

  • Cree nuevamente los vectores del ejercicio 1, pero esta vez dándole nombre a cada uno de los elementos

  • Cree nuevamente la lista del ejercicio 2 dándole nombre a cada uno de los elementos

Factores

Los atributos se utilizan para definir factores. Un factor es un vector que puede contener solo valores predefinidos y se utiliza para almacenar datos categóricos.

Los factores se construyen sobre vectores enteros utilizando dos atributos:

  • Clase “factor”: hace que se comporten de manera diferente a los vectores enteros regulares
  • Niveles: define el conjunto de valores permitidos
x <- factor(c("a", "b", "b", "a"))
x
## [1] a b b a
## Levels: a b
levels(x)
## [1] "a" "b"
str(x)
##  Factor w/ 2 levels "a","b": 1 2 2 1

 

Los factores parecen vectores de caracteres, pero en realidad son enteros:

x <- factor(c("a", "b", "b", "a"))

c(x)
## [1] 1 2 2 1

 

Matrices

Todos los elementos son del mismo tipo:

m <- matrix(c(1, 2, 3, 11, 12, 13), nrow = 2)

dim(m)
## [1] 2 3
m
##      [,1] [,2] [,3]
## [1,]    1    3   12
## [2,]    2   11   13
class(m)
## [1] "matrix" "array"
m <- matrix(c(1, 2, 3, 11, 12,"13"), nrow = 2)
m
##      [,1] [,2] [,3]
## [1,] "1"  "3"  "12"
## [2,] "2"  "11" "13"

 

Se puede crear modificando el atributo de dimensión:

c <- 1:6

is.matrix(c)
## [1] FALSE
attributes(c)
## NULL
dim(c) <- c(3, 2)

c
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    6
is.matrix(c)
## [1] TRUE
attributes(c)
## $dim
## [1] 3 2

 

Ejercicio 4

  • Cree una matriz numérica con 5 filas y 5 columnas con los números del 1 al 25

  • Cree una matriz de caracteres de 13 filas y 2 columnas con los elementos del objeto ‘letters’

Marcos de datos (data frames)

Son un tipo especial de listas. Pueden contener elementos de diferentes tipos:

m <- data.frame(ID = letters[1:5], size = rnorm(5), observed = c(FALSE, TRUE, FALSE, FALSE, FALSE))

dim(m)
## [1] 5 3
m
##   ID       size observed
## 1  a -1.1050901    FALSE
## 2  b  0.4714385     TRUE
## 3  c -0.8037029    FALSE
## 4  d  0.3949338    FALSE
## 5  e -1.2140789    FALSE
class(m)
## [1] "data.frame"
is.data.frame(m)
## [1] TRUE
is.list(m)
## [1] TRUE
str(m)
## 'data.frame':    5 obs. of  3 variables:
##  $ ID      : chr  "a" "b" "c" "d" ...
##  $ size    : num  -1.105 0.471 -0.804 0.395 -1.214
##  $ observed: logi  FALSE TRUE FALSE FALSE FALSE

 

Pero los vectores deben tener la misma longitud:

m <- data.frame(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, TRUE, FALSE, FALSE, FALSE))
## Error in data.frame(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, : arguments imply differing number of rows: 5, 6

 

Nota: data.frame() convierte los vectores de caracteres en factores por defecto. Use stringsAsFactors = FALSE para suprimir este comportamiento:

m <- data.frame(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, TRUE, FALSE, FALSE, FALSE), stringsAsFactors = FALSE)
## Error in data.frame(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, : arguments imply differing number of rows: 5, 6
str(m)
## 'data.frame':    5 obs. of  3 variables:
##  $ ID      : chr  "a" "b" "c" "d" ...
##  $ size    : num  -1.105 0.471 -0.804 0.395 -1.214
##  $ observed: logi  FALSE TRUE FALSE FALSE FALSE

 

Ejercicio 5

  • Cree un marco de datos con los nombres de los 5 primeros meses del año en la primera columna, los números del 1 al 5 en la segunda columna y un vector lógico en la tercer columna
  • De nombre a las columnas del marco de datos

Extraer subconjuntos de datos

Indexación

Los elementos dentro de los objetos pueden ser llamados por indexación. Para extraer un subconjunto de un vector, simplemente llame la posición del elemento utilizando corchetes:

x <- c(1, 3, 4, 10, 15, 20, 50, 1, 6)

x[1]
## [1] 1
x[2]
## [1] 3
x[2:3]
## [1] 3 4
x[c(1,3)]
## [1] 1 4

 

Los elementos se pueden quitar de la misma manera:

x[-1]
## [1]  3  4 10 15 20 50  1  6
x[-c(1,3)]
## [1]  3 10 15 20 50  1  6

 

Matrices y marcos de datos requieren 2 índices [fila, columna]:

m <- matrix(c(1, 2, 3, 11, 12, 13), nrow = 2)

m[1, ]
## [1]  1  3 12
m[, 1]
## [1] 1 2
m[1, 1]
## [1] 1
m[-1, ]
## [1]  2 11 13
m[, -1]
##      [,1] [,2]
## [1,]    3   12
## [2,]   11   13
m[-1, -1]
## [1] 11 13
df <- data.frame(family = c("Psittacidae", "Trochilidae", 
                            "Psittacidae"), 
  genus = c("Amazona", "Phaethornis", "Ara"), 
    species = c("aestiva", "philippii", "ararauna"))

df
##        family       genus   species
## 1 Psittacidae     Amazona   aestiva
## 2 Trochilidae Phaethornis philippii
## 3 Psittacidae         Ara  ararauna
df[1, ]
##        family   genus species
## 1 Psittacidae Amazona aestiva
df[, 1]
## [1] "Psittacidae" "Trochilidae" "Psittacidae"
df[1, 1]
## [1] "Psittacidae"
df[-1, ]
##        family       genus   species
## 2 Trochilidae Phaethornis philippii
## 3 Psittacidae         Ara  ararauna
df[, -1]
##         genus   species
## 1     Amazona   aestiva
## 2 Phaethornis philippii
## 3         Ara  ararauna
df[-1, -1]
##         genus   species
## 2 Phaethornis philippii
## 3         Ara  ararauna
df[,"family"]
## [1] "Psittacidae" "Trochilidae" "Psittacidae"
df[,c("family", "genus")]
##        family       genus
## 1 Psittacidae     Amazona
## 2 Trochilidae Phaethornis
## 3 Psittacidae         Ara

 

Las listas requieren 1 índice entre dobles corchetes [[índice]]:

l <- list(ID = letters[1:5], size = rnorm(6), observed = c(FALSE, TRUE, FALSE, FALSE, FALSE))

l[[1]]
## [1] "a" "b" "c" "d" "e"
l[[3]]
## [1] FALSE  TRUE FALSE FALSE FALSE

 

Los elementos dentro de las listas también pueden ser extraídos en la misma linea de código:

l[[1]][1:2]
## [1] "a" "b"
l[[3]][2]
## [1] TRUE

 

Ejercicio 6

  • Use indexación para extraer las dos primeras filas de la base de datos ‘df’

  • Use indexación para extraer las columnas 1 y 3 de la base de datos ‘df’

  • Use el nombre del elemento de la lista ‘l’ que contiene las primeras 5 letras del abecedario para extraerlo (usando indexación)

Explorar objectos

str(df)
## 'data.frame':    3 obs. of  3 variables:
##  $ family : chr  "Psittacidae" "Trochilidae" "Psittacidae"
##  $ genus  : chr  "Amazona" "Phaethornis" "Ara"
##  $ species: chr  "aestiva" "philippii" "ararauna"
names(df)
## [1] "family"  "genus"   "species"
dim(df)
## [1] 3 3
nrow(df)
## [1] 3
ncol(df)
## [1] 3
head(df)
##        family       genus   species
## 1 Psittacidae     Amazona   aestiva
## 2 Trochilidae Phaethornis philippii
## 3 Psittacidae         Ara  ararauna
tail(df)
##        family       genus   species
## 1 Psittacidae     Amazona   aestiva
## 2 Trochilidae Phaethornis philippii
## 3 Psittacidae         Ara  ararauna
table(df$genus)
## 
##     Amazona         Ara Phaethornis 
##           1           1           1
str(df)
## 'data.frame':    3 obs. of  3 variables:
##  $ family : chr  "Psittacidae" "Trochilidae" "Psittacidae"
##  $ genus  : chr  "Amazona" "Phaethornis" "Ara"
##  $ species: chr  "aestiva" "philippii" "ararauna"
View(df)

 

Funciones

Todas las funciones son creadas por la función function() y siguen la misma estructura:

* Modificado de Grolemund 2014  

R viene con muchas funciones que se pueden usar para realizar tareas sofisticadas:

# built in functions
bi <- builtins()

length(bi)
## [1] 1358
sample(bi, 10)
##  [1] ".primUntrace"     "Encoding<-"       ".External2"       "as.table.default"
##  [5] "[[<-.factor"      "undebug"          "isSymmetric"      ".libPaths"       
##  [9] "R_system_version" "merge.default"

 

Los operadores son funciones:

1 + 1
## [1] 2
'+'(1, 1)
## [1] 2
2 * 3
## [1] 6
'*'(2, 3)
## [1] 6

 

1 - 2
## [1] -1
1 + 2
## [1] 3
2 ^ 2
## [1] 4
2 ** 2
## [1] 4
5 %% 2
## [1] 1
5 %/% 2
## [1] 2

 

Operadores lógicos:

1 < 2 
## [1] TRUE
1 > 2 
## [1] FALSE
1 <= 2 
## [1] TRUE
1 == 2
## [1] FALSE
1 != 2
## [1] TRUE
1 > 2 
## [1] FALSE

 

La mayoría de las funciones están vectorizadas:

1:6 * 1:6

* Modificado de Grolemund & Wickham 2017

 

## [1]  1  4  9 16 25 36
1:6 - 1:6
## [1] 0 0 0 0 0 0

R recicla vectores de longitud desigual:

1:6 * 1:5

* Modificado de Grolemund & Wickham 2017

 

## Warning in 1:6 * 1:5: comprimento do objeto maior não é múltiplo do comprimento
## do objeto menor
## [1]  1  4  9 16 25  6
1:6 + 1:5
## Warning in 1:6 + 1:5: comprimento do objeto maior não é múltiplo do comprimento
## do objeto menor
## [1]  2  4  6  8 10  7

 


El estilo importa

Basado en la Guía de estilo de R de Google

 

Nombres de archivos

Los nombres de los archivos deben terminar en .R y, por supuesto, tener algún significado:

  - BUENO: predict_ad_revenue.R
  - MALO: foo.R

 

Nombres de objetos

Variables y funciones:

  • minúsculas
  • Utilice un guión bajo (_) (estilo HW)
  • Generalmente, sustantivos para variables y verbos para funciones
  • Usar nombres que sean concisos y significativos (no siempre fáciles)
  • Evitar el uso de nombres de funciones o de variables existentes
  - BUENO: day_one: day_1, mean.day(),
  
  - MALO: dayOne, day1, firstDay_of.month, mean <- function(x) sum(x), c <- 10

 

Syntaxis

Espaciado:

  • Usar espacios alrededor de los operadores y para argumentar dentro de una función
  • Siempre coloque un espacio después de una coma, y nunca antes (como en el inglés regular)
  • Coloque un espacio antes del paréntesis izquierdo, excepto en una llamada de una función
  - BUENO: 
          a <- rnorm(n = 10, sd = 10, mean = 1)
          tab.prior <- table(df[df$days.from.opt < 0, "campaign.id"])
          total <- sum(x[, 1])
          total <- sum(x[1, ])
          if (debug)
          mean(1:10)
          
  - MALO: 
         a<-rnorm(n=10,sd=10,mean=1)
         tab.prior <- table(df[df$days.from.opt<0, "campaign.id"])  # necesita espacio alrededor de '<'
         tab.prior <- table(df[df$days.from.opt < 0,"campaign.id"])  # necesita espacio despues de la coma
         tab.prior<- table(df[df$days.from.opt < 0, "campaign.id"])  # necesita espacio antes de '<-'
         tab.prior<-table(df[df$days.from.opt < 0, "campaign.id"])  # necesita espacio alrededor de '<-'
         total <- sum(x[,1])  # necesita espacio antes y despues de la coma
        if(debug) # necesita espacio antes del parentesis
         mean (1:10) # ) # espacio extra antes del parentesis

 

Paréntesis curvos:

  • Una llave de apertura nunca debe ir en su propia línea (sola)
  • El cierre de la llave debe ir siempre en su propia línea
  • Puedes omitir llaves cuando un bloque consiste en una sola declaración
  - BUENO:
              if (is.null(ylim)) {
              ylim <- c(0, 0.06)
            }
                      
            if (is.null(ylim))
              ylim <- c(0, 0.06)
          
  - MALO:
            
         if (is.null(ylim)) ylim <- c(0, 0.06)
                    
         if (is.null(ylim)) {ylim <- c(0, 0.06)} 

         if (is.null(ylim)) {
           ylim <- c(0, 0.06)
           } 

 

Asignación:

  • Use <-, not =
  - BUENO:
         x <- 5 
          
  - MALO:
         x = 5

 

Pautas para comentar:

  • Comente su código
  • Las líneas completas comentadas deben comenzar con # y un espacio
  • Los comentarios cortos se pueden colocar después del código precedido por dos espacios, #, y luego un espacio
# Crear histograma de frecuencia de campañas
hist(df$pct.spent,
     breaks = "scott",  # metodo
     main   = "Histograma",
     xlab   = "la variable x",
     ylab   = "y la y")

 


 

Documentación en R

Documentación de los paquetes

 

Manuales de referencia

Los manuales de referencia son colecciones de la documentación de todas las funciones en un paquete (solo 1 por paquete):

 

Documentación de las funciones

Todas las funciones (predeterminadas o de paquetes cargados) deben tener una documentación que siga un formato estándar:

?mean

help("mean")

 

Esta documentación también se puede mostrar en Rstudio presionando F1 cuando el cursor está en el nombre de la función

 

Si no recuerda el nombre de la función pruebe con apropos():

apropos("mean")
##  [1] ".colMeans"     ".rowMeans"     "colMeans"      "kmeans"       
##  [5] "mean"          "mean.Date"     "mean.default"  "mean.difftime"
##  [9] "mean.POSIXct"  "mean.POSIXlt"  "rowMeans"      "weighted.mean"

 

Viñetas

Las viñetas son documentos ilustrativos o casos de estudio que detallan el uso de un paquete (son opcionales, pueden ser varios por paquete)

Las viñetas se pueden llamar directamente desde R:

vgn <- browseVignettes() 
vignette()

También deben aparecer en la página de CRAN del paquete

 

Demostraciones

Los paquetes también pueden incluir demostraciones de código extendido (‘demos’). Para hacer un listado de las demostraciones en un paquete ejecute demo("nombre del paquete"):

demo(package="stats")

demo("nlm")

 

vista de tareas de CRAN

Las vistas de tareas son compilaciones de paquetes relacionados con un tema específico:

[Vistas de tareas en CRAN] (https://cran.r-project.org/web/views/)

 

Para instalar automáticamente los paquetes en una vista, el paquete ctv necesita ser instalado:

install.packages("ctv")

library("ctv")

 

Las vistas se pueden instalar a través de install.views() o update.views() (que primero evalúa cuáles de los paquetes ya están instalados y actualizados):

install.views("ReproducibleResearch")

# o

update.views("ReproducibleResearch")

La informacion sobre los paquetes que conforman un ‘task view’ se encuentra en la página de internet de CRAN: https://CRAN.R-project.org/view=ReproducibleResearch


Referencias