Introducción y objetivos

Introducción al uso de R como lenguaje de programación estadístico

El presente módulo introduce al participante en el manejo del software R, lo cual comprende la instalación y configuración del software necesario para el entorno de programación estadístico, la discusión de los conceptos del lenguaje de programación genéricos. Además, temas teórico-prácticos de la estadística, programación básica con el uso del script, manipulación de bases de datos, funciones y herramientas gráficas.

El objetivo del curso es actualizar-ampliar los conocimientos en la optimización de la gestión de información cuantitativa empoderando al participante de destrezas en el manejo del soft- ware R en data management, estadística descriptiva, gráficos, modelos lineales, clasificación, series de tiempo, con base a aplicaciones y casos prácticos.

  • Introducir al participante en el uso del software R como lenguaje de programación.
  • Mejorar las habilidades de gestión de información del participante.
  • Incrementar el conocimiento de modelos y su aplicación.

Visión general de R: instalación RStudio y otros

Introducción

R es un sistema para análisis estadístico y gráficos creado por Robert Gentleman y Ross Ihaka, profesores del departamento de Estadística de University of Auckland - New Zealand.

Ventajas

  • Open Source (Costo nulo) Comunidad dinámica integrada por estadísticos de renombre(R User Group Ecuador, Stackoverflow, Comunidad R Hispano, R en español,. . . )
  • Multi-plataforma: Disponible para Windows, Mac, Linux y Android.
  • Es de código abierto.
  • Facilidad de enlace con LateX y generar reportes dinámicos.
  • Amplia bibliografía en la web y libros publicados por editoriales prestigiosas (Springer, Wiley, Chapman & Hall,. . . )
  • Lenguaje intuitivo para la lectura de funciones y algoritmos.

Desventajas

  • Por ser un programa libre, no posee garantía ni un departamento de atención al cliente.
  • R no posee una interfaz amigable, las tareas se llevan a través de líneas de código, lo cual puede ser incómodo para el usuario.
  • R particularmente no es un lenguaje de programación rápida.

Cómo funciona R


Back to Top

Instalación de R, RStudio y paquetes

Instalación de R

  1. Ingresar a https://www.r-project.org/
  2. Elegir el CRAN (Comprehensive R Archive Network)
  3. Escoger versión del sistema operativo.
  4. Instalar R por primera vez.


R como una calculadora

3*8
## [1] 24
2.8/6.8
## [1] 0.4117647
sqrt(25)
## [1] 5

Además, cada operación anterior puede ser almacenada en un “objeto”

a<-3*8
b<-2.8/6.8
D<-sqrt(25)

Instalación de RStudio

  1. Ingresar a https://www.rstudio.com/
  2. Productos
  3. Escoger versión según el Sistema Operativo



Instalación de paquetes

Además de las funciones básicas, R tiene un gran número de paquetes especializados.

Los paquetes se instalan una sola vez y deben ser cargados en cada inicio de sesión.

Se utiliza la siguiente función:

install.packages("dplyr",dependencies = TRUE)

Una vez instalado, debemos cargarlo con cualquiera de estos comandos:

require(dplyr)
library("dplyr")

Para instalar un paquete desde otro repositorio:

install.packages("survey", repos="http://r-forge.r-project.org", type="source")
library(survey)

Desde github y con otra forma de cargar una función de una librería:

install.packages("githubinstall")
githubinstall::githubinstall("twitter/AnomalyDetection")

Otra forma de cargar desde github:

source("https://install-github.me/r-lib/callr")
library("callr")

Para poder ver los paquetes instalados y disponibles podemos utilizar:

library()
installed.packages()
.packages(all.available=TRUE)
available.packages() 

Para saber cuál fue el último paquete instalado utilizamos:

(.packages())

Es importante saber que funciones tiene cada paquete, para esto utilizamos:

ls("package:dplyr")

Back to Top

Data management, parte I

Estructuras de Datos

Las estructuras de datos en R se organizan por: Dimensionalidad y Homogeneidad o heterogeneidad.

R no tiene estructuras 0d (tipo escalar). Los números y strings individuales son considerados como vectores de longitud 1.

# no mostrar advertencias
options(warn = -1) 
x <- 9
x
## [1] 9

El texto luego de # es un comentario (no es interpretado por R). Para crear un objeto se utiliza el operador de asignación <-, =, ->.

y="SSh"
y
## [1] "SSh"

Vectores

La estructura de datos básica de R son los vectores, estos se dividen en Vectores atómicos y listas.

Propiedades:

Tipo: ¿Qué es?

typeof(x)
## [1] "double"

Longitud: Número de elementos.

length(x)
## [1] 1

Atributos: Características.

attributes(x)
## NULL

Vectores Atómicos

Los elementos de un vector atómico son del mismo tipo a diferencia de los elementos de una lista que pueden ser de diferente tipo. Los tipos comunes son:

  • double (numeric)
  • integer
  • character
  • logical

Función combinar

Un vector es creado mediante la función c( ) (combinar).

vec <- c(1, 2)
vec
## [1] 1 2

Tipos de Vectores Atómicos:

Vector double;

dbl_vec <- c(3.5, 2, -1)

Vector entero: Use el sufijo L para crear un vector entero;

int_vec <- c(3L, 7L, 1L)

Vector caracter: Use “ ” para crear un vector caracter;

chr_vec <- c("R",  "Users", "Group - Ecuador")

Vector lógico: Use TRUE y FALSE o T y F para crear un vector lógico.

log_vec <- c(FALSE, TRUE, F, T)

Para determinar si un vector vec es atómico utilizamos is.atomic(vec).

vec <- c(3.5, 2, -1)
is.atomic(vec)
## [1] TRUE

Para determinar el tipo de un vector vec utilizamos typeof(vec).

vec <- c("R",  "Users", "Group - Ecuador")
typeof(vec)
## [1] "character"

Para verificar si un vector vec es de un tipo en específico, se utilizan las funciones “is”:

is.character(vec)
## [1] TRUE
is.double(vec)
## [1] FALSE
is.integer(vec)
## [1] FALSE
is.logical(vec)
## [1] FALSE

Elementos de un vector atómico: La componente i de vec se obtiene mediante vec[i].

Componente 5 de vec:

vec <- c(6, 1, 3, 6, 10, 5)
vec[5]
## [1] 10

Para seleccionar varios elementos utilizamos vec[c(elementos)].

# elementos 2 y 4 
vec[c(2, 4)]
## [1] 1 6

Para omitir el elemento i de vec se utiliza vec[-i].

vec <- c(6, 1, 3, 6, 10, 5)
vec[-5]
## [1] 6 1 3 6 5

Para omitir varios elementos utilizamos vec[-c(elementos)].

# omitir los elementos 2 y 4
vec[-c(2, 4)]
## [1]  6  3 10  5

Generación de secuencias: El operador a:b genera el vector a, a+1, a+2, …, b.

1:10
##  [1]  1  2  3  4  5  6  7  8  9 10
5:-5
##  [1]  5  4  3  2  1  0 -1 -2 -3 -4 -5

La función seq( ) genera secuencias controlando: inicio, fin y salto.

seq(from = 1, to = 10, by = 0.5)
##  [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5
## [15]  8.0  8.5  9.0  9.5 10.0
seq(from = -4, to = 4, length = 5)
## [1] -4 -2  0  2  4

vec[c(TRUE, FALSE)] permite obtener determinados elementos:

# elementos 2, 4, 6
vec <- c(6, 1, 3, 6, 10, 5)
vec[c(FALSE, TRUE, FALSE, TRUE, FALSE, TRUE)]
## [1] 1 6 5

Equivalente a:

vec[c(2, 4, 6)]
## [1] 1 6 5

Operaciones con vectores

A continuación, se resumen las operaciones básicas con vectores atómicos:


Función all(x) retorna TRUE si todas las componentes de x son TRUE.

x <- c(TRUE, TRUE, TRUE)
all(x)
## [1] TRUE
y <- c(TRUE, FALSE, TRUE)
all(y)
## [1] FALSE

Función any(x) retorna TRUE si al menos una componente de x es TRUE.

x <- c(FALSE, FALSE, FALSE)
any(x)
## [1] FALSE
y <- c(FALSE, TRUE, FALSE)
any(y)
## [1] TRUE

Negación !x cambia las componentes de x de: TRUE a FALSE y de FALSE a TRUE:

x <- c(TRUE, FALSE, TRUE)
!x
## [1] FALSE  TRUE FALSE

Conjunción x & y retorna TRUE solo si las componentes de x & y son TRUE:

x <- c(TRUE, TRUE, FALSE) 
y <- c(FALSE, TRUE, TRUE)
x & y
## [1] FALSE  TRUE FALSE
x && y # conjuncion para escalares
## [1] FALSE

Disyunción x | y retorna TRUE si al menos una componente de x o y es TRUE

x <- c(TRUE, TRUE, FALSE) 
y <- c(FALSE, TRUE, TRUE) 
x | y
## [1] TRUE TRUE TRUE
x || y # disyuncion para escalares
## [1] TRUE

Dado un vector lógico x:

x <- c(TRUE, TRUE, FALSE, TRUE, FALSE)

sum(x). Cuenta el número de TRUE en x.

sum(x)
## [1] 3

mean(x). Muestra el porcentaje de TRUE en x.

mean(x)
## [1] 0.6
sum(x)/length(x)
## [1] 0.6

Test de igualdad y desigualdad

x <- c(3, 5, 2, 3, 1) 
x==3
## [1]  TRUE FALSE FALSE  TRUE FALSE
y <- x==3 # componentes iguales a 3
z <- x!=3 # componentes distintas a 3 
data.frame(x, y, z)
##   x     y     z
## 1 3  TRUE FALSE
## 2 5 FALSE  TRUE
## 3 2 FALSE  TRUE
## 4 3  TRUE FALSE
## 5 1 FALSE  TRUE
x[x!=3] # componentes de x distintas a 3
## [1] 5 2 1

Coerción: Si combinamos tipos diferentes, serán coercionados al tipo más flexible dado por la jerarquía:


Para coercionar un vector x a un determinado tipo, se utilizan las funciones “as”

as.character(x)
## [1] "3" "5" "2" "3" "1"
as.double(x)
## [1] 3 5 2 3 1
as.integer(x)
## [1] 3 5 2 3 1
as.logical(x)
## [1] TRUE TRUE TRUE TRUE TRUE
as.numeric(x) 
## [1] 3 5 2 3 1

Listas

Una lista es un vector que puede contener elementos de cualquier tipo y de distinta longitud.

Para crear una lista se utiliza la función list() en lugar de c().

lst <- list(c(1, 2), c(TRUE), c("a", "b", "c"))
lst
## [[1]]
## [1] 1 2
## 
## [[2]]
## [1] TRUE
## 
## [[3]]
## [1] "a" "b" "c"

Tests para una lista:

lst <- list(1:3, c("R",  "Users", "Group - Ecuador"), c(TRUE, FALSE), c(1.3, 4.5))
typeof(lst)
## [1] "list"
is.atomic(lst)
## [1] FALSE

Para probar si lst es una lista se utiliza:

is.list(lst)    
## [1] TRUE

Coerción de vector atómico lst a una lista

lst <- c("ssl", 4, 0.5)
as.list(lst)
## [[1]]
## [1] "ssl"
## 
## [[2]]
## [1] "4"
## 
## [[3]]
## [1] "0.5"

Coerción de lista lst a vector atómico (reglas de coerción)

lst <- list(1:3, c("R",  "Users", "Group - Ecuador"), c(TRUE, FALSE), c(1.3, 4.5))
unlist(lst)
##  [1] "1"               "2"               "3"              
##  [4] "R"               "Users"           "Group - Ecuador"
##  [7] "TRUE"            "FALSE"           "1.3"            
## [10] "4.5"

Elementos de una lista: Para acceder al elemento i de la lista se utiliza x[i]. Para acceder al objeto que contiene el elemento i se utiliza x[[i]].

lst <- list(c(1, 2), c(TRUE), c("a", "b", "c"))
lst[1]
## [[1]]
## [1] 1 2
lst[[1]]
## [1] 1 2

En una lista con nombre podemos utilizar el simbolo $ para extraer determinados elementos:

lst <- list(v=1:3, w=c("R",  "Users", "Group - Ecuador"), x=c(TRUE, FALSE), y=c(1.3, 4.5))
lst$w
## [1] "R"               "Users"           "Group - Ecuador"

Utilizar lst$w resulta equivalente a utilizar lst[[2]]

lst[[2]]
## [1] "R"               "Users"           "Group - Ecuador"

Atributos

Los objetos en R poseen varios atributos tales como: names, class, dim, etc. La función attributes(x) muestra los atributos de un objeto x.

Vector atómico:

# Vector sin el atributo names 
vec <- c(3, 6, -1, 0.5) 
attributes(vec)
## NULL
# Vector con el atributo names 
vec <- c(a=3, b=6, c=-1, d=0.5) 
attributes(vec)
## $names
## [1] "a" "b" "c" "d"

Lista:

# Lista sin el atributo names
lst <- list(1:3, c("R",  "Users", "Group - Ecuador"), c(TRUE, FALSE))
attributes(lst)
## NULL
# Lista con el atributo names
lst <- list(nomb1=1:3, nomb2=c("R",  "Users", "Group - Ecuador"), nomb3=c(TRUE,FALSE))
attributes(lst)
## $names
## [1] "nomb1" "nomb2" "nomb3"

Matrices

Una matriz es un vector con el atributo dimensión dim. El atributo dim es un vector de longitud 2: c(nrow, ncol).

mtx <- matrix (1:12,nrow=3, ncol=4, byrow=FALSE)
# se construye por columnas por default (byrow=FALSE)
mtx
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12

dim() se usa para añadir el atributo dimensión a un vector, o para hallar la dimensión de una matriz.

mtx <- 1:12
mtx 
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12
dim(mtx) <- c(3,4)
mtx 
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
mtx <- matrix (1:12, nrow=3, ncol=4, byrow=FALSE)
dim(mtx)
## [1] 3 4

Elementos de una matriz:

(mtx <- matrix (1:12, nrow=3, ncol=4, byrow=FALSE))
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
mtx[1,2] # componente 1, 2
## [1] 4
mtx[,3] # columna 3
## [1] 7 8 9
mtx[1,] # fila 1
## [1]  1  4  7 10
mtx[,c(2,4)] # columnas 2 y 4
##      [,1] [,2]
## [1,]    4   10
## [2,]    5   11
## [3,]    6   12
mtx[c(1,3),] # filas 1 y 3
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    3    6    9   12
mtx[,c(FALSE, TRUE, TRUE, FALSE)] # columnas 2 y 4
##      [,1] [,2]
## [1,]    4    7
## [2,]    5    8
## [3,]    6    9
mtx[c(TRUE, FALSE, TRUE),] # filas 1 y 3
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    3    6    9   12

Factores

Es la estructura de datos utilizada para almacenar variables categóricas. ¿Por qué utilizar factores?

Un vector c(Femenino, Masculino) (factor) presenta mayor información que un vector c(1, 2).

Un vector character c(“Femenino”, “Masculino”) no pueden ser incluido en modelos de regresión, un factor c(Femenino, Masculino) si.

Un factor se crea mediante la función: factor()

Si se dispone de un vector integer:

vec <- c(1, 2, 2, 1, 2, 1, 2)
vec
## [1] 1 2 2 1 2 1 2

La función factor asigna labels a los levels (o categorías) de la variable. Los levels del vector vec son los valores 1, 2.

# Creación de un factor
fac <- factor(vec, levels=c(1,2), labels = c("Femenino", "Masculino"))
fac
## [1] Femenino  Masculino Masculino Femenino  Masculino Femenino  Masculino
## Levels: Femenino Masculino

Si se dispone de un vector character:

# Creación de un factor
vec <- c("Femenino","Masculino","Masculino","Femenino","Masculino", "Femenino","Masculino")
vec
## [1] "Femenino"  "Masculino" "Masculino" "Femenino"  "Masculino" "Femenino" 
## [7] "Masculino"

La función factor asigna labels a los levels (o categorías) de la variable. En este caso los levels del vector vec son los valores “Femenino”, “Masculino”.

# Creación de un factor
# por defecto labels = levels
fac <- factor(vec, levels= c("Femenino", "Masculino"), labels=c("FEM", "MASC"))
fac
## [1] FEM  MASC MASC FEM  MASC FEM  MASC
## Levels: FEM MASC

Para obtener los atributos de un factor utilizamos attributes().

vec <- c(1, 2, 2, 1, 2, 1, 2)
fac <- factor(vec, levels=c(1,2), labels = c("Femenino", "Masculino"))
# Atributos de un factor 
attributes(fac)
## $levels
## [1] "Femenino"  "Masculino"
## 
## $class
## [1] "factor"

Para considerar el vector entero utilizamos unclass().

# eliminación del atributo class 
unclass(fac)
## [1] 1 2 2 1 2 1 2
## attr(,"levels")
## [1] "Femenino"  "Masculino"

Para realizar conteos por categoría, se utiliza la función table().

fac <- factor(vec, levels=c(1,2), labels = c("Femenino", "Masculino"))
# frecuencias table(fac)
# porcentaje 
prop.table(table(fac))
## fac
##  Femenino Masculino 
## 0.4285714 0.5714286

Data Frame

Es una lista en la cual todos los elementos tienen la misma longitud. A diferencia de las matrices, pueden almacenar vectores atómicos de cualquier tipo. Presenta varios atributos adicionales class, rownames, names. Es la estructura de datos más utilizada para almacenar data tabulada.

Para crear un data frame se utiliza la función data.frame(). Con los siguientes vectores atómicos:

dbl_vec <- c(1, 2, 3) 
chr_vec <- c("R", "S", "T") 
log_vec <- c(TRUE, FALSE, TRUE)

Creamos el data frame df:

df <- data.frame(dbl_vec, chr_vec, log_vec)
df
##   dbl_vec chr_vec log_vec
## 1       1       R    TRUE
## 2       2       S   FALSE
## 3       3       T    TRUE

Un data frame es una lista:

typeof(df) # Tipo de un data frame
## [1] "list"

Su clase es data.frame:

class(df)
## [1] "data.frame"

Atributos de un data frame:

attributes(df)
## $names
## [1] "dbl_vec" "chr_vec" "log_vec"
## 
## $row.names
## [1] 1 2 3
## 
## $class
## [1] "data.frame"

Nombres de las columnas de df:

names(df)
## [1] "dbl_vec" "chr_vec" "log_vec"

Nombres de las filas de df:

rownames(df)
## [1] "1" "2" "3"

Dimensión: Filas y columnas

dim(df)
## [1] 3 3

Número de filas y columnas

nrow(df)
## [1] 3

Elementos de un data frame:

Mediante df[i, j] se obtiene la componente i, j del data frame.

nomb <- c("John", "Paul", "George", "Ringo")
nac <- c(1940, 1941, 1943, 1940)
instr <- c("guitar", "bass", "guitar", "drums")

df <- data.frame(nomb, nac, instr)
df[2, c(2,3)]
##    nac instr
## 2 1941  bass
print(df)
##     nomb  nac  instr
## 1   John 1940 guitar
## 2   Paul 1941   bass
## 3 George 1943 guitar
## 4  Ringo 1940  drums
df[2, 2] # componente 2, 2
## [1] 1941
df[3, 1] # componente 3, 1
## [1] George
## Levels: George John Paul Ringo
df[c(1, 4), ] # filas 1, 4
##    nomb  nac  instr
## 1  John 1940 guitar
## 4 Ringo 1940  drums

Se pueden seleccionar ciertas filas mediante TRUE y FALSE.

df[c(TRUE, TRUE, FALSE, TRUE), ] # equivalente a df[c(1, 2, 4), ]
##    nomb  nac  instr
## 1  John 1940 guitar
## 2  Paul 1941   bass
## 4 Ringo 1940  drums

Importante: Reciclado:

df[c(TRUE, FALSE), ] # equivalente a df[c(1, 3), ]
##     nomb  nac  instr
## 1   John 1940 guitar
## 3 George 1943 guitar

Importante: Filtrado o subsetting:

df[ , 3]=="guitar" # columna 3 de df igual a "guitar"
## [1]  TRUE FALSE  TRUE FALSE
f_guitar <- df[ , 3]=="guitar"

Filas donde la columna 3 es igual a “guitar”

df[f_guitar, ]
##     nomb  nac  instr
## 1   John 1940 guitar
## 3 George 1943 guitar
df[ , c(1, 3)] # columnas 1, 3
##     nomb  instr
## 1   John guitar
## 2   Paul   bass
## 3 George guitar
## 4  Ringo  drums

Columna de nombre “nac”

df[ , "nac"] # equivalente a df[ , 2]
## [1] 1940 1941 1943 1940

Columnas de nombres “nomb y nac”

df[ , c("nomb", "nac")] # equivalente a df[ , c(1, 2)]
##     nomb  nac
## 1   John 1940
## 2   Paul 1941
## 3 George 1943
## 4  Ringo 1940

Se pueden seleccionar ciertas columnas mediante TRUE y FALSE:

df[ , c(TRUE, FALSE, TRUE)] # equivalente a df[ , c(1, 3)]
##     nomb  instr
## 1   John guitar
## 2   Paul   bass
## 3 George guitar
## 4  Ringo  drums

Importante: Reciclado

df[ , c(TRUE, FALSE)] # equivalente a df[ , c(1, 3)]
##     nomb  instr
## 1   John guitar
## 2   Paul   bass
## 3 George guitar
## 4  Ringo  drums

R Data Frames

R posee varios data frames en sus bases de datos internas, por ejemplo: mtcars

data(mtcars)

Visualización:

View(mtcars)
# n primeras filas 
head(mtcars,n = 2)
##               mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4      21   6  160 110  3.9 2.620 16.46  0  1    4    4
## Mazda RX4 Wag  21   6  160 110  3.9 2.875 17.02  0  1    4    4
# n últimas filas 
tail(mtcars,n = 2)
##                mpg cyl disp  hp drat   wt qsec vs am gear carb
## Maserati Bora 15.0   8  301 335 3.54 3.57 14.6  0  1    5    8
## Volvo 142E    21.4   4  121 109 4.11 2.78 18.6  1  1    4    2

Atributos del data frame:

attributes(mtcars)
## $names
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
## 
## $row.names
##  [1] "Mazda RX4"           "Mazda RX4 Wag"       "Datsun 710"         
##  [4] "Hornet 4 Drive"      "Hornet Sportabout"   "Valiant"            
##  [7] "Duster 360"          "Merc 240D"           "Merc 230"           
## [10] "Merc 280"            "Merc 280C"           "Merc 450SE"         
## [13] "Merc 450SL"          "Merc 450SLC"         "Cadillac Fleetwood" 
## [16] "Lincoln Continental" "Chrysler Imperial"   "Fiat 128"           
## [19] "Honda Civic"         "Toyota Corolla"      "Toyota Corona"      
## [22] "Dodge Challenger"    "AMC Javelin"         "Camaro Z28"         
## [25] "Pontiac Firebird"    "Fiat X1-9"           "Porsche 914-2"      
## [28] "Lotus Europa"        "Ford Pantera L"      "Ferrari Dino"       
## [31] "Maserati Bora"       "Volvo 142E"         
## 
## $class
## [1] "data.frame"

Nombres de las columnas:

names(mtcars)   
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"
colnames(mtcars)                        
##  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
## [11] "carb"

Nombres de las filas

rownames(mtcars)
##  [1] "Mazda RX4"           "Mazda RX4 Wag"       "Datsun 710"         
##  [4] "Hornet 4 Drive"      "Hornet Sportabout"   "Valiant"            
##  [7] "Duster 360"          "Merc 240D"           "Merc 230"           
## [10] "Merc 280"            "Merc 280C"           "Merc 450SE"         
## [13] "Merc 450SL"          "Merc 450SLC"         "Cadillac Fleetwood" 
## [16] "Lincoln Continental" "Chrysler Imperial"   "Fiat 128"           
## [19] "Honda Civic"         "Toyota Corolla"      "Toyota Corona"      
## [22] "Dodge Challenger"    "AMC Javelin"         "Camaro Z28"         
## [25] "Pontiac Firebird"    "Fiat X1-9"           "Porsche 914-2"      
## [28] "Lotus Europa"        "Ford Pantera L"      "Ferrari Dino"       
## [31] "Maserati Bora"       "Volvo 142E"

Dimensiones en un data frame:

# Dimensión 
dim(mtcars)
## [1] 32 11
# Número columnas 
ncol(mtcars)
## [1] 11
# Número filas 
nrow(mtcars)
## [1] 32

Función structure

La función str() (structure) presenta una descripción compacta de la estructura de datos. Usar View() es costoso computacionalmente.

str(mtcars)
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

Missing Values

Los valores perdidos en R se denotan por NA, NaN. NA Not Available. Dato perdido.

x <- c(NA, 3.2, NA, 5, NA)
x
## [1]  NA 3.2  NA 5.0  NA

NaN Not a Number. Resultado de una indeterminación:

y <- c(-1, 0/0, 0.8, 5, Inf*0)
y
## [1] -1.0  NaN  0.8  5.0  NaN

Inf representa infinito.

is.na(x) retorna TRUE para elementos NA de un vector atómico o lista.

x <- c(0, 3.2, NA, 5, NA)
is.na(x)
## [1] FALSE FALSE  TRUE FALSE  TRUE

is.nan(x) retorna TRUE para elementos NaN de un vector atómico.

y <- c(-1, 0/0, 5, Inf*0)
is.nan(y)
## [1] FALSE  TRUE FALSE  TRUE

Importación y Exportación de datos

Lectura de datos

R puede acceder a información almacenada en distintos formatos:

Archivos de excel .xls, .xlsx, .csv; Archivos de texto plano .txt; Archivos de spss .sav; Archivos de la web; Archivos de bases de datos, etc.

Directorio de trabajo

Working directory (wd). Es la dirección donde se almacenan, leen y escriben los archivos utilizados y generados mediante R. getwd() permite obtener el wd actual:

getwd()
## [1] "C:/Users/crbdl/Desktop"

setwd() permite setear un nuevo wd, por ejemplo:

setwd("C:/Documentos/R_users_group")

list.files() enlista los nombres de los archivos en el wd actual. El parámetro pattern se usa para enlistar los nombres de los archivos que contienen un determinado patrón.

list.files(pattern = ".R")

file.exists() verifica si existe una carpeta con un determinado nombre en el wd.

# Verifica si existe o no una carpeta con nombre "r_users"
file.exists("r_users")
## [1] FALSE

dir.create() permite crear nuevas carpetas en el wd.

# Crea una nueva carpeta con nombre "files" 
dir.create("files")

R sobreescribe una carpeta sobre otra, de ahí la importancia de utilizar previamente file.exists().

Back to Top

¿Cómo leer archivos en R?

Lectura de archivos .txt

Se requiere leer un archivo en formato txt: archivo.txt. Se utiliza la función read.table()

data_txt <- read.table(file = "archivo.txt",sep = "\t", dec = ",", header = TRUE)
str(data_txt)

Parámetros:

file: nombre del archivo (incluida extensión); sep: caracter utilizado para separar columnas (variables); dec: caracter utilizado para decimales; header: TRUE, si la primera fila contiene los nombres de las columnas.

str() describe la estructura de datos.

Por defecto R coerciona las variables categóricas a factor. El parametro stringsAsFactors=FALSE evita esta coerción.

data_txt <- read.table(file = "archivo.txt",sep = "\t", dec = ",", header = TRUE, stringsAsFactors = FALSE)

Lectura de archivos .csv

Se requiere leer un archivo en formato csv: archivo.csv, se utiliza las función read.csv que presenta por defecto los argumentos: sep = “,”, dec = “.”, , header = TRUE

data_csv <- read.csv(file = "archivo.csv")

read.csv2(): Se debe especificar los argumentos: sep, dec, header

data_csv2 <- read.csv2(file = "archivo.csv",sep = ",", dec = ".", header = TRUE)

Lectura de archivos .xls, .xlsx

Se requiere leer un archivo en formato xls o xlsx: archivo.xlsx. Se utiliza la función read_excel() del paquete readxl

install.packages("readxl", dependencies = TRUE)
library(readxl)
ls("package:readxl")

Lectura del archivo archivo.xlsx:

data_xlsx <- read_excel("archivo.xlsx",sheet = "datos",col_names = TRUE, na="")
read.table("clipboard",sep = "\t",header = FALSE)

Parámetros:

sheet: Nombre de la hoja que contiene la data (recibe también el número de hoja); col_names: TRUE si la primera fila contiene los nombres de las columnas; na: los caracter que se coerciona a NA.

Lectura de archivos .sav

Se requiere leer archivos desde spss, es decir en formato .sav: archivo.sav. Se utiliza la función read.spss() del paquete foreign.

install.packages("foreign", dependencies = TRUE)
library(foreign)
ls("package:foreign")
data_sav <- read.spss(file="archivo.sav", use.value.labels = TRUE, to.data.frame = TRUE)

Parámetros:

file: nombre del archivo (incluida extensión); use.value.labels: TRUE, si se consideran las etiquetas de las variables; to.data.frame: TRUE, para coercionar el archivo leído a data frame.

Back to Top

Funciones

Introducción

Una función es un conjunto de instrucciones, que a partir de uno o más datos de entrada, permiten generar y retornar un detrminado resultado.

¿Porqué construir funciones?

Practicidad: Permiten ejecutar un conjunto de instrucciones en una sola línea de código. Ejemplo: La función sort , las instrucciones necesarias para ordenar un vector.

x <- c(3, 1, 6, 2)
x
## [1] 3 1 6 2
sort (x)
## [1] 1 2 3 6

Generalización: Permiten diseñar códigos para casos determinados y ajustarlos a casos generales.

Ejemplo: Hallar la media de 3 y 4

(3 + 4) / 2
## [1] 3.5

Para hallar el promedio de varios pares de números, creamos la función promedio.

promedio <- function(a, b) {
prom <- (a + b) / 2 
return (prom)
}

Estructura de una función

El comando function() tiene como tarea crear funciones a partir de ciertos argumentos que son proporcionados por el usuario.

No existe un límite en la cantidad de argumentos que una función puede recibir.

promedio_pond <- function(a, b, peso1, peso2) {
prom <- peso1*a + peso2*b 
return (prom)
}

Ejemplos:

promedio_pond(a=    1, b    = 5, peso1 = 0.8, peso2 =   0.2)
## [1] 1.8

Argumentos por default

Existen ocasiones que no se requieren ingresar ciertos argumentos para que la función pueda ejecutarse.

Estos valores por default deben colocarse en la función:

promedio_pond <- function(a, b, peso1 = 0.5, peso2 = 0.5) {
prom <- peso1*a + peso2*b 
return (prom)
}
promedio_pond(a = 1, b = 5)
## [1] 3

Lexical Scoping

Variable libre: Una variable en una función se dice libre si no ha sido definida o no es un argumento.

El lexical Scoping permite entender cómo R asocia un valor a una variable libre (crear un objeto).

f <- function(x, y) {
return(x^2 + y / z)
}

Argumentos: x, y. Variables libres: z.

f(x = 3, y = 6)
## [1] Inf  15  15 Inf  15

Considere la siguiente función:

z <- 10
f <- function(x) {
z <- 2
z^2 + g(x)
}
g <- function(x) {
x*z
}

Cuál es el valor de f(x = 3) ?

f(x = 3)
## [1] 34

Back to Top

Estructuras de Control


Son herramientas que permiten manejar de una forma mucho más estructurada el flujo de ejecución de un código. Las estructuras de control se clasifican en:

Condicionales: if, else (e ifelse). Loops o bucles: for, while.

Sentencia if

La sentencia if realiza una tarea para un determinado caso.

CONDICION: Vector lógico 1d TRUE/FALSE . Si condicion es TRUE se ejecuta la tarea. Forma de declarar la sentencia if:

x <- 2
if(x > 0) {
x <- x + 1
}
x 
## [1] 3

Sentencia else

La sentencia else trabaja conjuntamente con la sentencia if


Si la condición es TRUE se ejecuta la Tarea 1, caso contrario se ejecuta la Tarea 2.

Sentencia if else

Forma de declarar la sentencia if else :

x <- -1
if (x >= 0) {
print("El número es positivo")
} else {
print("El número es negativo")
}
## [1] "El número es negativo"

Sentencia for

La sentencia for permite repetir una acción un número determinado de veces.

Forma de declarar la sentencia for:

Ejemplo: Suma de filas/columnas: m: matriz de 4x3 de Poisson

m <- matrix(data = rpois(n = 12, lambda = 8), nrow = 4, ncol = 3)
m
##      [,1] [,2] [,3]
## [1,]    7    8    9
## [2,]   10   14    8
## [3,]    8   10    7
## [4,]    6   11    6
col_sumas <- numeric(ncol(m))
for (i in 1:4){
col_sumas[i] <- sum(m[i,])
}
col_sumas                                                                 
## [1] 24 32 25 23

Funciones loop tipo ”apply”

apply

Apply se utiliza para evaluar una función (a menudo anónima) sobre los márgenes de una matriz. Se utiliza con mayor frecuencia para aplicar una función a las filas o columnas de una matriz. Se puede usar con matrices generales, p. Tomando el promedio de una matriz de matrices no es realmente más rápido que escribir un bucle, pero funciona en una línea!

str(apply)
## function (X, MARGIN, FUN, ...)

X es una matriz

MARGIN es un vector entero que indica qué márgenes deben ser retenidos“. FUN es una función a ser aplicada para que otros argumentos sean pasados a FUN

x <- matrix(rnorm(200), 20, 10)
apply(x, 2, mean)
##  [1]  0.375680998 -0.386917588 -0.337469042 -0.253210969 -0.095369786
##  [6]  0.006149434 -0.262256608 -0.151185842  0.030029833 -0.262586216

col/row Sumas y Medias

Para las sumas y los medias de las dimensiones de la matriz, tenemos algunos atajos:

rowSums = apply(x,  1, sum)
rowMeans = apply(x,  1, mean)
colSums = apply(x,  2, sum)
colMeans = apply(x,  2, mean)

Las funciones de acceso directo son mucho más rápidas, pero no te darás cuenta a menos que estés usando una matriz grande.

Otras Formas de Aplicar

Quantiles de las filas de una matriz.

x <- matrix(rnorm(200), 20, 10)
apply(x, 1, quantile, probs = c(0.25, 0.75))
##           [,1]      [,2]       [,3]       [,4]       [,5]       [,6]
## 25% -0.9986528 -1.329281 -0.6930205 -0.4490333 -0.1848993 -0.5006163
## 75%  0.1255915  0.359086  0.8898816  0.6627382  0.7923025  0.3157985
##           [,7]       [,8]       [,9]      [,10]      [,11]      [,12]
## 25% -0.4413362 -1.0880216 -0.3640341 -0.8919106 -0.3917338 -1.0468530
## 75%  0.4240068  0.7934426  0.3140949  0.7787425  0.8882287  0.6145108
##          [,13]      [,14]      [,15]      [,16]      [,17]      [,18]
## 25% -1.0982383 -0.5216335 -0.8433666 -0.3522312 -0.9730085 -0.6937552
## 75% -0.1730996  0.4500281  0.7283369  0.6748745  0.3634782  0.9827490
##          [,19]      [,20]
## 25% -0.7897723 0.02118837
## 75%  0.4957886 1.21741085

Matriz media en una matriz

a <- array(rnorm(2 * 2 * 10), c(2, 2, 10))
apply(a, c(1, 2), mean)
##           [,1]        [,2]
## [1,] 0.2332499 -0.07410178
## [2,] 0.2385339  0.49606679

tapply

tapply se utiliza para aplicar una función sobre subconjuntos de un vector.

str(tapply)
## function (X, INDEX, FUN = NULL, ..., simplify = TRUE)

X es un vector INDICE es un factor o una lista de factores (o bien son coaccionados a factores) FUN es una función a ser aplicada contiene otros argumentos para ser evaluados FUN simplificar, ¿debemos simplificar el resultado?

Tomar grupos significa:

x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
f   
##  [1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
## Levels: 1 2 3

Tomar medias de grupos sin simplificación.

tapply(x, f, mean, simplify = FALSE)
## $`1`
## [1] -0.4014109
## 
## $`2`
## [1] 0.5845753
## 
## $`3`
## [1] 0.7220379

Encuentra rangos de grupo.

tapply(x, f, range)
## $`1`
## [1] -2.1083360  0.9654397
## 
## $`2`
## [1] 0.3911844 0.8530016
## 
## $`3`
## [1] -0.1659212  3.1330298

lapply y sapply

La escritura de while es útil cuando se programa pero no es especialmente fácil cuando se trabaja interactivamente en la línea de comandos. Hay algunas funciones que implementan bucles para facilitar la vida.

Lapply: Bucle sobre una lista y evaluar una función en cada elemento Sapply: Lo mismo que lapply pero intenta simplificar el resultado Apply: Aplicar una función sobre los márgenes de una matriz Tapply: Aplicar una función sobre subconjuntos de un vector Mapply: Versión multivariable de lapply

También es útil una división de función auxiliar, particularmente en conjunción con lapply.

lapply

Lapply toma tres argumentos: (1) una lista X; (2) una función (o el nombre de una función) FUN; (3) otros argumentos a través de su argumento. Si X no es una lista, será coaccionado a una lista usando as.list.

lapply
## function (X, FUN, ...) 
## {
##     FUN <- match.fun(FUN)
##     if (!is.vector(X) || is.object(X)) 
##         X <- as.list(X)
##     .Internal(lapply(X, FUN))
## }
## <bytecode: 0x0000000012af6640>
## <environment: namespace:base>

El bucle real se realiza internamente en código C.

Lapply siempre devuelve una lista, independientemente de la clase de la entrada.

x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
lapply(x, mean)
## $a
## [1] 2.5
## 
## $b
## [1] 0.6970291
## 
## $c
## [1] 1.138907
## 
## $d
## [1] 5.188079
x <- 1:4 
lapply(x, runif)
## [[1]]
## [1] 0.3899072
## 
## [[2]]
## [1] 0.6053326 0.2631529
## 
## [[3]]
## [1] 0.7674535 0.2481148 0.6048053
## 
## [[4]]
## [1] 0.9630127 0.6112869 0.3498528 0.5991059
x <- 1:4
lapply(x, runif, min = 0, max = 10)
## [[1]]
## [1] 5.099684
## 
## [[2]]
## [1] 6.049304 5.235927
## 
## [[3]]
## [1] 5.605220 9.718606 2.388543
## 
## [[4]]
## [1] 3.347105 6.844083 6.963573 1.313079

Lapply permite hacer un uso intensivo de funciones anónimas.

x <- list(a = matrix(1:4, 2, 2), b = matrix(1:6, 3, 2))
x
## $a
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## $b
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    6

Una función anónima para extraer la primera columna de cada matriz.

lapply(x, function(elt) elt[,1])
## $a
## [1] 1 2
## 
## $b
## [1] 1 2 3

Sapply

Sapply tratará de simplificar el resultado de lapply si es posible.

Si el resultado es una lista donde cada elemento es la longitud 1, entonces se devuelve un vector

Si el resultado es una lista donde cada elemento es un vector de la misma longitud (>1), se devuelve una matriz.

Y no puede calcular, se devuelve una lista

x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
lapply(x, mean)
## $a
## [1] 2.5
## 
## $b
## [1] -0.1764945
## 
## $c
## [1] 0.8521396
## 
## $d
## [1] 5.056278
sapply(x, mean)
##          a          b          c          d 
##  2.5000000 -0.1764945  0.8521396  5.0562784

mapply

Mapply es una aplicación multivariable de tipos que aplica una función en paralelo sobre un conjunto de argumentos.

str(mapply)
## function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)

FUN es una función para aplicar … contiene argumentos para aplicar MoreArgs es una lista de otros argumentos para FUN. SIMPLIFY indica si el resultado debe ser simplificado

El siguiente listado es tedioso digitar: list(rep(1, 4), rep(2, 3), rep(3, 2), rep(4, 1)) Por lo cual se puede hacer:

mapply(rep, 1:4, 4:1)
## [[1]]
## [1] 1 1 1 1
## 
## [[2]]
## [1] 2 2 2
## 
## [[3]]
## [1] 3 3
## 
## [[4]]
## [1] 4

Vectorizando una Función

noise <- function(n, mean, sd) {
rnorm(n, mean, sd)
}

Vectorización instantánea

mapply(noise, 1:5, 1:5, 2)
## [[1]]
## [1] 1.849743
## 
## [[2]]
## [1] 2.399712 4.371152
## 
## [[3]]
## [1] 4.999238 5.639152 1.006731
## 
## [[4]]
## [1] 6.835012 4.930839 3.930951 3.894547
## 
## [[5]]
## [1] 4.861750 5.494002 5.516326 4.588543 7.085203

Lo cual es lo mismo que:

list(noise(1, 1, 2), noise(2, 2, 2),    noise(3, 3, 2), noise(4, 4, 2), noise(5, 5, 2))
## [[1]]
## [1] -0.5319374
## 
## [[2]]
## [1]  5.017320 -2.580596
## 
## [[3]]
## [1] 2.426552 2.616396 2.785114
## 
## [[4]]
## [1] 3.581864 6.604843 6.517391 3.691458
## 
## [[5]]
## [1] 6.797958 8.984205 3.492458 4.071135 3.837592

split

split toma un vector u otros objetos y lo divide en grupos determinados por un factor o una lista de factores.

str(split)
## function (x, f, drop = FALSE, ...)

X es un vector (o lista) o un marco de datos F es un factor (o coaccionado a uno) o una lista de factores Drop indica si los niveles de factores vacíos deben ser eliminados

x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
split(x, f)
## $`1`
##  [1]  0.18546082  0.70710539 -0.40715155 -1.07120272  0.22565579
##  [6]  0.09808071  0.28057701 -0.25702616 -0.57604646  1.28589004
## 
## $`2`
##  [1] 0.8887993 0.9725940 0.3833292 0.1011196 0.2321548 0.3389057 0.9597877
##  [8] 0.9047762 0.8589763 0.6351879
## 
## $`3`
##  [1]  0.2020942  0.8242144  0.8620720  2.4277311 -0.9836047  1.2817231
##  [7]  1.7216647  2.8483862 -0.2665849  1.6397124

Una función común se divide seguido de un lapply.

lapply(split(x, f), mean)
## $`1`
## [1] 0.04713429
## 
## $`2`
## [1] 0.6275631
## 
## $`3`
## [1] 1.055741

División de un data frame

library(datasets)
head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
s <- split(airquality, airquality$Month)
lapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")]))
## $`5`
##    Ozone  Solar.R     Wind 
##       NA       NA 11.62258 
## 
## $`6`
##     Ozone   Solar.R      Wind 
##        NA 190.16667  10.26667 
## 
## $`7`
##      Ozone    Solar.R       Wind 
##         NA 216.483871   8.941935 
## 
## $`8`
##    Ozone  Solar.R     Wind 
##       NA       NA 8.793548 
## 
## $`9`
##    Ozone  Solar.R     Wind 
##       NA 167.4333  10.1800
sapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")]))
##                5         6          7        8        9
## Ozone         NA        NA         NA       NA       NA
## Solar.R       NA 190.16667 216.483871       NA 167.4333
## Wind    11.62258  10.26667   8.941935 8.793548  10.1800

División en más de un nivel

x <- rnorm(10) 
f1 <- gl(2, 5) 
f2 <- gl(5, 2)
f1
##  [1] 1 1 1 1 1 2 2 2 2 2
## Levels: 1 2

Interacciones pueden crear niveles vacios:

str(split(x, list(f1, f2)))
## List of 10
##  $ 1.1: num [1:2] 0.0735 0.0123
##  $ 2.1: num(0) 
##  $ 1.2: num [1:2] 1.508 -0.774
##  $ 2.2: num(0) 
##  $ 1.3: num -0.848
##  $ 2.3: num -0.671
##  $ 1.4: num(0) 
##  $ 2.4: num [1:2] 0.782 0.765
##  $ 1.5: num(0) 
##  $ 2.5: num [1:2] -1.18 -0.383

Se pueden eliminar niveles vacíos:

str(split(x, list(f1, f2), drop = TRUE))
## List of 6
##  $ 1.1: num [1:2] 0.0735 0.0123
##  $ 1.2: num [1:2] 1.508 -0.774
##  $ 1.3: num -0.848
##  $ 2.3: num -0.671
##  $ 2.4: num [1:2] 0.782 0.765
##  $ 2.5: num [1:2] -1.18 -0.383

Back to Top