Lo básico

Introducción

El objetivo de este documento es que el estudiante se familiarice con los conceptos básicos del lenguaje R. Gran parte de los ejemplos y la organización han sido tomados de The Book of R con lo cual se recomienda revisarlo para profundizar en lo presentado.

En particular, en esta parte se aprenderá sobre:

  1. Números, aritmética, assignment y vectores
  2. Matrices y arreglos
  3. Valores no numéricos
  4. Listas y DataFrame

¿Por qué utilizar un lenguaje de programación?

Una primera pregunta es la de porqué molestarnos en aprender un lenguaje de programación para realizar análisis de datos en vez de utilizar, quizás, algún software comercial. Existen varias razones que lo justifican.

Por ejemplo, al utilizar un lenguaje y trabajar con scripts el trabajo se hace reproducible, es decir, siempre y cuando tenga la información a ser analizada en un archivo diferente (un .csv, por ejemplo) y mis códigos que indican qué tipo de transformaciones estoy realizando, puedo reproducir la totalidad del documento. De hecho, cualquiera con los datos y el script podría.

Los lenguajes de programación (en particular open source), a diferencia del software comercial, son flexibles, en el sentido que, si el lenguaje tiene una comunidad de usuarios activa, muchos de estos usuarios contribuyen al lenguaje creando librerías para realizar análisis específicos, incrementando y potenciando la herramienta.

También, se puede decir que utilizar un lenguaje para realizar análisis de datos nos obliga a ser rigurosos con el razonamiento. En este sentido, se debe especificar correctamente lo que se desea realizar sobre el objeto correcto. Cuando se programa, al final, se está hablando con uno mismo y, cuando el programa “no corre” probablemente es por algún error de lógica interna. Esto no obliga a pensar detenidamente sobre lo que se está realizando.

¿Por qué utilizar R?

Una segunda pregunta es la de porqué utilizar R y no otro lenguaje. A criterio personal, R tiene una curva de aprendizaje menos empinada, es decir, no cuesta tanto aprender los rudimentos del lenguaje y comenzar a utilizarlo para nuestra tareas. Además, se pueden aprender las funcionalidades básicas del mismo y dejar los elementos más complejos para aprender en la medida que se vayan necesitando.

En segundo lugar, R tiene una comunidad de usuarios enfocada en el análisis de datos y la estadística. Esto en contraposición a lenguajes más generales como Python donde los usuarios principales suelen ser ingenieros de software o sistemas. La ventaja de esto es que las soluciones que existen y el ecosistema de librerías que se utilizan están orientados a abstraer lo más posible la lógica de programación, haciendo bastante fácil (pocas líneas de código) obtener los resultados que se necesitan.

¿Es R un sustituto de Microsoft Excel?

No. R es un lenguaje de programación mientras que Microsoft Excel es una hoja de cálculo.

Números, aritmética, assignment y vectores

En este capítulo se sientan las bases para entender el lenguaje, al menos en la forma en que R entiende las órdenes para realizar cálculos matemáticos.

R para matemática básica

2+3
## [1] 5
14/6
## [1] 2.333333
14/6+5
## [1] 7.333333
14/(6+5)
## [1] 1.272727
3^2 # ^: caret
## [1] 9
sqrt(x=9) 
## [1] 3
# y=f(x) o, de manera general: y=f(x,w,z,....) 
# donde, f()=sqrt() , x= entero positivo
# y = sqrt(x=9)
raiz <- sqrt(9)

sqrt(5.311)
## [1] 2.304561

Calculando la raíz cuadrada de un vector:

vec <- c(9,36, 25)

sqrt(x = vec)
## [1] 3 6 5
10^2+3*60/8-3
## [1] 119.5
5^3*(6-2)/(61-3+4)
## [1] 8.064516
2^(2+1)-4+64^((-2)^(2.25-1/4))
## [1] 16777220
(0.44*(1-0.44)/34)^0.5
## [1] 0.08512966

Aquí hay una función algo más compleja: $$\log_{3}(243) = 5$$

log(x=243) #La base es "e"
## [1] 5.493061
log(x=243,base=3)
## [1] 5
exp(5.493061)
## [1] 242.9999

¿Los resultados de la siguiente función son iguales?

log(243,3) # Logaritmo de 243 con base 3
## [1] 5
log(3,243) # Logaritmo de 3 con base 243
## [1] 0.2

No son iguales porque los argumentos no son los mismos.

log(x=243, base=3)
## [1] 5
log(base=3, x=243)
## [1] 5

En el caso de que no coloquemos los nombres explícitos de los argumentos de la función R va a tomarlos según la posición relativa de los mismos en la función original, en este caso log(x,base) toma primero x y luego base, en ese orden.

3^5
## [1] 243
log(x=243,base=3)
## [1] 5
log(x=100)
## [1] 4.60517
log(x=100,base=10)
## [1] 2
2342151011545931994564548
## [1] 2.342151e+24
0.0000002533
## [1] 2.533e-07

Asignar objetos

La idea de objeto se repetirá a lo largo del curso y es, en parte, definitoria del lenguaje que estamos utilizando. Un objeto es algo sobre lo cual se coloca información para ser reutilizada luego.

Hasta ahora, hemos utilizado el lenguaje para hacer cálculos sencillos que aparecen en la pantalla, sin embargo…

x <- 5
x
## [1] 5
x <- 4
x
## [1] 4
x <- x+7      #Esto sobre escribe el valor previo de x
print(x)
## [1] 11
mi_numero <- 45.12 #¿Qué sucede si me equivoco en el nombre de la variable? ¿Cómo lo corrijo?
print(mi_numero)
## [1] 45.12
x <-5
x
## [1] 5
y <- mi_numero*x
y
## [1] 225.6
ls()
## [1] "mi_numero" "raiz"      "vec"       "x"         "y"
remove(mi_numero)
ls()
## [1] "raiz" "vec"  "x"    "y"

Vectores

Una de las ventajas que tiene R sobre Excel es su velocidad para el procesamiento de la información. Para aprovechar esta ventaja, R utiliza vectores, que se crean mediante la función c().

¿Por qué son útiles los vectores? Imagine que un vector es simplemente una columna proveniente de una tabla con información. Por ejemplo, si se tienen almacenadas el número de tarjetas de crédito colocadas cada día de la anterior semana,el vector ventas podría ser:

tarjetas_colocadas <- c(20,30,15,18,25)
tarjetas_colocadas
## [1] 20 30 15 18 25

Se pueden utilizar los vectores para hacer cálculos de manera rápida:

x <- 2
x
## [1] 2
tarjetas_colocadas
## [1] 20 30 15 18 25
tarjetas_colocadas*x
## [1] 40 60 30 36 50

Además, se puede almacenar dichos cálculos:

tarjetas_x2 <- tarjetas_colocadas*x
tarjetas_x2
## [1] 40 60 30 36 50

Adicionalmente es importante entender cómo funciona la multiplicación de vectores.

x <- c(1,2,3)
y <- c(4,5,6)
x
## [1] 1 2 3
y
## [1] 4 5 6

¿Cuál es el resultado de multiplicar dichos vectores? Por álgebra sabemos que un vector $3\times1$ multiplicado por otro de igual tamaño se obtiene como:

$$ \begin{array}{c} x^{T}y = (x_{1}y_{1}+x_{2}y_{2}+x_{3}y_{3}) \\ \end{array} $$

Donde el resultado es un número. Esto es lo que se conoce como dot product, scalar product o inner product.

x*y
## [1]  4 10 18
y*x
## [1]  4 10 18

¿Qué sucede?

El problema es que R multiplica los vectores elemento por elemento.

Entender los vectores es fundamental en R debido a que son los ‘building blocks’ de todo lo que sigue. Muchos programadores se refieren a R como un lenguaje vectorizado (vector-oriented behavior).

¿Qué sucedería si, por ejemplo, se multiplican vectores de diferente tamaño?

x <- c(2,2,2,2)
y <- c(3,5)

x*y
## [1]  6 10  6 10
y*x
## [1]  6 10  6 10

Esta conducta se llama Recycling: se recicla el vector más pequeño las veces que sean necesarias para ser del mismo tamaño que el vector más grande.

Finalmente, ¿cómo se obtiene el dot product de:

$$x=(1,2,3)$$

y

$$y=(4,5,6)$$

Entonces:

$$ \begin{array}{c} x^{T}y = (14+25+3*6)= 32 \\ \end{array} $$

x <- c(1,2,3)
y <- c(4,5,6)
x%*%y
##      [,1]
## [1,]   32

Tarea: Crear dos vectores con 3 elementos cada uno, luego crear un vector adicional que contenga dichos vectores.

Una vez que se entienden los vectores es mucho más sencillo trabajar en R. Ahora vamos a ver algunas funciones que ‘funcionan’ (toman como inputs) vectores. Estas funciones nos van a ayudar a ordenar, contar, etc. todos los elementos de nuestros vectores.

tarjetas_colocadas <- c(20,30,15,18,25)
tarjetas_colocadas
## [1] 20 30 15 18 25
sqrt(tarjetas_colocadas)
## [1] 4.472136 5.477226 3.872983 4.242641 5.000000
length(tarjetas_colocadas) #Contar el numero de elementos del vector
## [1] 5
length(x=tarjetas_colocadas)
## [1] 5
mean(tarjetas_colocadas)
## [1] 21.6
tarjetas_colocadas2 <- c(4,NA,2,6,8)
tarjetas_colocadas3 <- c(4,0,2,6,8)
tarjetas_colocadas2
## [1]  4 NA  2  6  8
tarjetas_colocadas3
## [1] 4 0 2 6 8
mean(tarjetas_colocadas2,na.rm=TRUE)
## [1] 5
mean(tarjetas_colocadas3,na.rm=TRUE)
## [1] 4
tarjetas_colocadas
## [1] 20 30 15 18 25
sort(tarjetas_colocadas)
## [1] 15 18 20 25 30
tarjetas_colocadas
## [1] 20 30 15 18 25
sort(tarjetas_colocadas)
## [1] 15 18 20 25 30
sort(tarjetas_colocadas, decreasing=FALSE)
## [1] 15 18 20 25 30
sort(tarjetas_colocadas, decreasing=TRUE)
## [1] 30 25 20 18 15

Subsetting y extracción de elementos

Una parte importante del lenguaje es conocer cómo acceder a los elementos del vector.

tarjetas_colocadas = c(20,30,15,18,25)
tarjetas_colocadas
## [1] 20 30 15 18 25
tarjetas_colocadas[1]
## [1] 20
tarjetas_colocadas[2]
## [1] 30
tarjetas_colocadas[c(2,5)]
## [1] 30 25
tarjetas_colocadas[c(2:5)]
## [1] 30 15 18 25
c(4:10)
## [1]  4  5  6  7  8  9 10

Vamos a tomar el mínimo de este vector

tarjetas_colocadas
## [1] 20 30 15 18 25
sort(tarjetas_colocadas)
## [1] 15 18 20 25 30
sort(tarjetas_colocadas)[1] #stackoverflow
## [1] 15
min(tarjetas_colocadas)
## [1] 15
tarjetas_colocadas[3:5]
## [1] 15 18 25
length(tarjetas_colocadas)
## [1] 5
tarjetas_colocadas[length(tarjetas_colocadas)] #Toma el último elemento de mi vector
## [1] 25
tarjetas_colocadas[5]
## [1] 25
tarjetas_colocadas
## [1] 20 30 15 18 25
tarjetas_colocadas[-1]
## [1] 30 15 18 25
tarjetas_colocadas[-1:-3]
## [1] 18 25
tarjetas_colocadas
## [1] 20 30 15 18 25
tarjetas_colocadas[length(tarjetas_colocadas)-1]
## [1] 18
tarjetas_colocadas[1+1]==tarjetas_colocadas[2]
## [1] TRUE
d <- tarjetas_colocadas[length(tarjetas_colocadas)-2]
d
## [1] 15

Seleccionar, o eliminar componentes de un vector no lo modifica al menos que uno explícitamente ordene a R que sobrescriba el vector.

Matrices y arreglos (arrays)

Una matriz es simplemente una colección de vectores. Mientras que el tamaño de un vector es descrito por su longitud o length, el tamaño de una matriz es especificado por el número de filas y el número de columnas.

Definición de una matriz

Se define una matriz ${A}$ como de $m x n$, es decir $m$ filas y $n$ columnas. En total, la matriz tendrá $m\times n$ entradas y cada entrada $a_{i,j}$ será única dada su fila $i = 1,2,…,m$ y su columna $j = 1,2,…,n$.

c(1:9)
## [1] 1 2 3 4 5 6 7 8 9
A <- matrix(data=c(1:9),nrow=3)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
B <- matrix(data=c(5,18,4,99999),nrow=2,ncol=2,byrow=TRUE)
B
##      [,1]  [,2]
## [1,]    5    18
## [2,]    4 99999
A <- matrix(data= c(1:4),nrow=2, byrow = T)
A
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
B <- matrix(data = c(4:7), ncol = 2, byrow = T)
B
##      [,1] [,2]
## [1,]    4    5
## [2,]    6    7
A*B
##      [,1] [,2]
## [1,]    4   10
## [2,]   18   28
A%*%B
##      [,1] [,2]
## [1,]   16   19
## [2,]   36   43

Es importante darse cuenta que la matriz fue llenada columna por columna. Es posible cambiar dicha forma utilizando el argumento byrow en la función matrix().

matrix(data=c(1:9),nrow=3,ncol=3,byrow=TRUE)
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
## [3,]    7    8    9
matrix(data=c(1:9),nrow=3,ncol=3,byrow=FALSE) #Por default en R
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

Dos funciones importantes son rbind y cbind las cuales nos permiten combinar vectores (de igual tamaño) para formar matrices.

rbind se refiere a row o ‘por fila’ mientras que cbind hace referencia a column o columna.

a <- c(1,2,3)
b <- c(4,5,6)
c <- c(7,8,9)
print(a)
## [1] 1 2 3
print(b)
## [1] 4 5 6
print(c)
## [1] 7 8 9
matriz <- rbind(a,b,c)
print(matriz)
##   [,1] [,2] [,3]
## a    1    2    3
## b    4    5    6
## c    7    8    9
cbind(a,b,c)
##      a b c
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9

Adicionalmente, es posible conocer la dimensión de nuestra matriz

B <- matrix(c(1:12),nrow=2,ncol=6)
B
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    3    5    7    9   11
## [2,]    2    4    6    8   10   12
dim(B) # filas y columnas
## [1] 2 6
#nrow(B) # número de filas
#ncol(B) #número de columnas
dim(B)[1]
## [1] 2
dim(B)[2]
## [1] 6
dimensiones=dim(B)
dimensiones
## [1] 2 6
dimensiones[2]
## [1] 6

Adicionalmente, como una matriz es un conjunto de vectores, se pueden utilizar rbind y cbind para adicionar tanto filas como columnas, respectivamente.

print(B)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    3    5    7    9   11
## [2,]    2    4    6    8   10   12
print(cbind(B,c(0,0)))
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,]    1    3    5    7    9   11    0
## [2,]    2    4    6    8   10   12    0
print(cbind(B,c(0,0,3)))
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
## [1,]    1    3    5    7    9   11    0
## [2,]    2    4    6    8   10   12    0
print(rbind(B,c(1:6)))
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    3    5    7    9   11
## [2,]    2    4    6    8   10   12
## [3,]    1    2    3    4    5    6

Subsetting

Extraer elementos de una matriz es similar a extraerlos de un vector, con la única diferencia que ahora tenemos una dimensión adicional.

También se utilizarán los squared brackets [ ] con la diferencia de que ahora el orden viene como [fila,columna]

print(A)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
A[1,1] #Obtener el elemento de la fila 1 y columna 1
## [1] 1
A[2,2]
## [1] 4
#A[3,3]
A[2,1] #Obtener el elemento de la fila 2 y columna 1
## [1] 3

Además, es posible extraer toda la columna o toda la fila con un comando. Esto será especialmente útil cuando querramos seleccionar una columna específica de una base de datos. Por ejemplo, si tuviésemos un monto en Bs. y quisiésemos convertirlo en dólares.

print(A)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
A[,1] #Obtener todas las filas de la columna 1
## [1] 1 3
A[2,] #Obtener todas las columnas de la fila 2
## [1] 3 4

El resultado de estas extracciones son vectores del tamaño respectivo. Si la extracción es más compleja (por ejemplo, tomar dos columnas), el resultado será una matriz.

print(A)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
#print(A[3,])
print(A)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
#print(A[c(2,3),c(1,2)]) # Todas las filas de la matriz A y las columnas 2 y 3
x <- A[,c(1:2)]
print(x)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4

Adicionalmente se pueden obtener todos los elementos de la diagonal principal:

print(A)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
diag(x=A)
## [1] 1 4

Muchas veces lo que se quiere es eliminar alguna fila o columna. Esto se puede hacer de la siguiente manera.

A <- matrix(data=c(1:9),nrow=3,ncol=3)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
A[,-1]
##      [,1] [,2]
## [1,]    4    7
## [2,]    5    8
## [3,]    6    9
A
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
A <- A[,-1] #Eliminar la columna 1
A
##      [,1] [,2]
## [1,]    4    7
## [2,]    5    8
## [3,]    6    9
A <- matrix(data=c(1:9),nrow=3,ncol=3)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
A[-1,-c(2,3)]#Eliminar la fila 1 y las columnas 2 y 3
## [1] 2 3
A[c(2,3),1]
## [1] 2 3

Finalmente, también es posible sobrescribir partes o elementos de la matriz.

print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
C <- A #Creamos una copia de A que se llama C
C[,1] <- c(0,0,0) #Sustituimos la primer columna de C por un nuevo vector de ceros
print(C)
##      [,1] [,2] [,3]
## [1,]    0    4    7
## [2,]    0    5    8
## [3,]    0    6    9
diag(C) <- c(99,99,99)
print(C)
##      [,1] [,2] [,3]
## [1,]   99    4    7
## [2,]    0   99    8
## [3,]    0    6   99

Operaciones con matrices

Se pueden utilizar las matrices de R en dos sentidos:

  1. Como estructuras puramente computacionales para almacenar resultados o data.
  2. Por sus propiedades matemáticas, para realizar cálculos (por ejemplo, resolver de manera ‘mecánica’ un modelo de regresión lineal).

En esta parte se explicará brevemente esta segunda función.

Transposición de matrices

Para cualquier matriz $A$ de dimensiones $m \times n$, su transpuesta, $A^{T}$, $n\times m$ es obtenida al intercambiar sus filas por columnas y sus columnas por sus filas.

A <- matrix(c(1:12),nrow=2,ncol=6,byrow=F)
A
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    3    5    7    9   11
## [2,]    2    4    6    8   10   12
A_trans <- t(A)
A_trans
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
## [3,]    5    6
## [4,]    7    8
## [5,]    9   10
## [6,]   11   12

Matriz Identidad

Una matriz identidad es una en la cual los elementos de la diagonal principal son 1’s y los demás elementos son 0.

identidad <- diag(x=3)
identidad
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    1    0
## [3,]    0    0    1
identidad[1,3] <- 8
identidad
##      [,1] [,2] [,3]
## [1,]    1    0    8
## [2,]    0    1    0
## [3,]    0    0    1

Multiplicación escalar

A <- matrix(c(1:9),nrow=3,ncol=3,byrow=F)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
A*2
##      [,1] [,2] [,3]
## [1,]    2    8   14
## [2,]    4   10   16
## [3,]    6   12   18
a <- 4
A*a
##      [,1] [,2] [,3]
## [1,]    4   16   28
## [2,]    8   20   32
## [3,]   12   24   36

Suma y resta de matrices

B <- matrix(c(9:1),nrow=3,ncol=3,byrow=F)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
print(B)
##      [,1] [,2] [,3]
## [1,]    9    6    3
## [2,]    8    5    2
## [3,]    7    4    1
B-A
##      [,1] [,2] [,3]
## [1,]    8    2   -4
## [2,]    6    0   -6
## [3,]    4   -2   -8
A+B
##      [,1] [,2] [,3]
## [1,]   10   10   10
## [2,]   10   10   10
## [3,]   10   10   10
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
A - c(1,2)
##      [,1] [,2] [,3]
## [1,]    0    2    6
## [2,]    0    4    6
## [3,]    2    4    8

Multiplicación de matrices

Para multiplicar dos matrices, digamos $A$ y $B$ de tamaño m x n y p x q, respectivamente, la condición de conformidad es que n = p, es decir, que el número de columnas de $A$ sea igual al número de filas de $B$. La matriz resultante tendrá un tamaño de m x q.

Así, la matriz $AB$ es calculada multiplicando cada elemento de la fila i de $A$ por cada elemento de la columna j de $B$.

print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
print(B)
##      [,1] [,2] [,3]
## [1,]    9    6    3
## [2,]    8    5    2
## [3,]    7    4    1
dim(A)
## [1] 3 3
dim(B)
## [1] 3 3
AB <- A*B
print(AB)
##      [,1] [,2] [,3]
## [1,]    9   24   21
## [2,]   16   25   16
## [3,]   21   24    9

¿Qué sucedió aquí?

AB_2 <- A%*%B
AB_2
##      [,1] [,2] [,3]
## [1,]   90   54   18
## [2,]  114   69   24
## [3,]  138   84   30

Cuando se utiliza el operador de multiplicación (asterisco) las matrices se multiplican elemento por elemento. El operador con porcentajes, es necesario.

C <- matrix(c(-2:9),nrow=3,ncol=4) #Definimos una nueva matriz
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
print(C)
##      [,1] [,2] [,3] [,4]
## [1,]   -2    1    4    7
## [2,]   -1    2    5    8
## [3,]    0    3    6    9
dim(A)
## [1] 3 3
dim(C)
## [1] 3 4

La matriz $A$ tiene una dimensión de [3,3] mientras que $C$ es [3,4] entonces $AB$ es conformable para multiplicación y la matriz resultantes será una de [3,4].

AC <- A%*%C
AC
##      [,1] [,2] [,3] [,4]
## [1,]   -6   30   66  102
## [2,]   -9   36   81  126
## [3,]  -12   42   96  150

Inversión de matrices

Algunas matrices cuadradas pueden invertirse. Así, $$AA^{-1} = I_{m}$$ En R, es posible invertir matrices utilizando la función solve.

Adicionalmente, un requisito para la invertibilidad es que el determinante de la matriz sea distinto de cero (0). Si esto es cierto se dice que la matriz es no singular.

print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
((1*5*9)+(4*8*3)+(7*6*2))-((3*5*7)+(6*8*1)+(9*2*4))
## [1] 0
det(A)
## [1] 0
#solve(A)
B <- matrix(c(1,7,13,3,-1,6,9,5,-12),ncol=3,nrow=3)
print(B)
##      [,1] [,2] [,3]
## [1,]    1    3    9
## [2,]    7   -1    5
## [3,]   13    6  -12
det(B)
## [1] 924
B_inv <- solve(B)
B_inv
##             [,1]        [,2]        [,3]
## [1,] -0.01948052  0.09740260  0.02597403
## [2,]  0.16125541 -0.13961039  0.06277056
## [3,]  0.05952381  0.03571429 -0.02380952
round(B%*%B_inv,digits = 2)
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    1    0
## [3,]    0    0    1

Valores no numéricos

Hasta aquí hemos trabajado solo con valores numéricos, pero la programación estadística requiere también trabajar con variables categóricas y otros tipos. En esta sección se verán tres tipos de valores no numéricos:

  1. Valores lógicos
  2. Textos (characters)
  3. Factores

Valores lógicos

Son objetos que pueden tomar el valor verdadero (TRUE) o falso (FALSE), los cuales pueden ser interpretados como si/no, uno/cero, satisface/no satisface.

Entre sus usos están verificar si una condición se cumple o no, o si se debe o no incluir un parámetro en alguna función.

Como convención se pueden utilizar indistintamente los valores TRUE y FALSE o T y F, sin embargo no se deben nombrar objetos de esta manera para que siga siendo válido.

logic <- TRUE
num <- 6

class(logic)
## [1] "logical"
class(num)
## [1] "numeric"
logicall<- c(T,F,T,F,T,F,T,F,T)
logicall
## [1]  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE
length(logicall) #numero de elementos
## [1] 9
sum(logicall) #numero de verdaderos
## [1] 5
length(logicall) - sum(logicall) #numero de falsos
## [1] 4

También podemos crear matrices con dichos valores.

mat_log <- matrix(data=logicall, nrow=3,ncol=3)
mat_log
##       [,1]  [,2]  [,3]
## [1,]  TRUE FALSE  TRUE
## [2,] FALSE  TRUE FALSE
## [3,]  TRUE FALSE  TRUE

Resultado lógico: Operadores relacionales

Valores lógicos son comúnmente utilizados para revisar/comprobar relaciones entre valores.

Operador Descripción
== igual a
!= no es igual a
> mayor a
< menor a
>= mayor o igual a
<= menor o igual a
1==1
## [1] TRUE
1>2
## [1] FALSE
1!=(2*5)
## [1] TRUE

Estas comparaciones también pueden realizarse en vectores enteros (debido a que R está vectorizado). Más adelante se utilizarán estas condiciones como índices para decidir sobre qué valores se realizarán ciertas operaciones.

vec1<-c(3,2,6,8,9,-4)
vec2<-c(3,5,4,8,2,-4)

vec1==vec2
## [1]  TRUE FALSE FALSE  TRUE FALSE  TRUE
vec1 <= vec2
## [1]  TRUE  TRUE FALSE  TRUE FALSE  TRUE
vec1 < vec2+20
## [1] TRUE TRUE TRUE TRUE TRUE TRUE

Adicionalmente estas comparaciones se pueden extender a matrices.

A <- matrix(c(1:9),nrow=3,ncol=3,byrow=F)
B <- matrix(c(9:1),nrow=3,ncol=3,byrow=F)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
print(B)
##      [,1] [,2] [,3]
## [1,]    9    6    3
## [2,]    8    5    2
## [3,]    7    4    1
A<B
##      [,1]  [,2]  [,3]
## [1,] TRUE  TRUE FALSE
## [2,] TRUE FALSE FALSE
## [3,] TRUE FALSE FALSE
A==B 
##       [,1]  [,2]  [,3]
## [1,] FALSE FALSE FALSE
## [2,] FALSE  TRUE FALSE
## [3,] FALSE FALSE FALSE

Comparaciones múltiples

Regularmente nos vamos a fijar si varias condiciones se cumplen. R se basa en las palabras ‘and’ (&) y ‘or’ (|) para hacer las comparaciones. Además, podemos usar NOT (!).

Estos operadores funcionan solamente cuando se comparan boolean values, es decir, el resultado del cumplimiento o no de ciertas condiciones. Más adelante se verán ejemplos de esto.

Extracción y subsetting

Supongamos que tenemos el siguiente vector:

vector <- c(5,-2.3,4,4,4,6,8,10,40221,-8)
vector
##  [1]     5.0    -2.3     4.0     4.0     4.0     6.0     8.0    10.0 40221.0
## [10]    -8.0
length(vector)
## [1] 10
vector>10
##  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
#vector[9]
vector[vector>10]
## [1] 40221
vector[vector>2]
## [1]     5     4     4     4     6     8    10 40221
A <- matrix(c(1:9),nrow=3,ncol=3,byrow=F)
print(A)
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
A > 3 
##       [,1] [,2] [,3]
## [1,] FALSE TRUE TRUE
## [2,] FALSE TRUE TRUE
## [3,] FALSE TRUE TRUE
A[A>3]
## [1] 4 5 6 7 8 9
A[A>3] <- 9999
print(A)
##      [,1] [,2] [,3]
## [1,]    1 9999 9999
## [2,]    2 9999 9999
## [3,]    3 9999 9999
A == 9999 | A == 2
##       [,1] [,2] [,3]
## [1,] FALSE TRUE TRUE
## [2,]  TRUE TRUE TRUE
## [3,] FALSE TRUE TRUE
A[A==9999 | A ==2] <- 0
print(A)
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    0    0
## [3,]    3    0    0

Caracteres

Los caracteres (o letras/texto) sirven para especificar ubicaciones (path) de folders en la PC, como argumentos de funciones, para ayudar colocar títulos a gráficos, para trabajar con variables categóricas, etc.

Para crear un texto se utilizan doble comillas (" “):

texto <- "Este es un vector con texto!"
print(texto)
## [1] "Este es un vector con texto!"
length(texto)
## [1] 1
class(texto)
## [1] "character"
#sum(texto)
vec1 <- c(8,"econometrics rules")
length(vec1)
## [1] 2
class(vec1)
## [1] "character"
elem <- c("3","4")
class(elem)
## [1] "character"
#sum(elem)

¿Qué sucede aquí? R trata a dicho vector como si fuese una sola entidad. Para contar el número de letras se utiliza:

texto
## [1] "Este es un vector con texto!"
nchar(x=texto)
## [1] 28

Cualquier expresión entre comillas va a ser pasada como texto, incluso un número. Esto es importante ya que el comportamiento de R va a depender del tipo de data que tengamos almacenada.

num <- "25.8"
print(num)
## [1] "25.8"
num2 <- "4.2"
print(num2)
## [1] "4.2"
num+num2

Esto ocurre porque las operaciones esperan valores numéricos y no textos. Sin embargo, los textos pueden ser comparados. Esto va a ser importante cuando querramos filtrar información en función a datos textuales (por ejemplo, si la variable está almacenada como “CONSUMO”).

"texto"=="textos"
## [1] FALSE
"texto"=="texto"
## [1] TRUE
c("texto","CONSUMO","variable")=="CONSUMO"
## [1] FALSE  TRUE FALSE
sum(c("texto","CONSUMO","variable")=="CONSUMO")#Primero comparo el vector y luego sumo el resultado que es logico
## [1] 1

Concatenar

Concatenar significa “pegar”. Hay dos funciones cat y paste. La segunda es preferible ya que devuelve el resultado listo para ser utilizado, por ejemplo, como input en otra función.

qx <- c("lenguaje","R","es el mejor","del mundo")
print(qx)
## [1] "lenguaje"    "R"           "es el mejor" "del mundo"
length(qx)
## [1] 4
qx[3]
## [1] "es el mejor"
paste(qx[2],qx[3],qx[1],qx[4],"!")
## [1] "R es el mejor lenguaje del mundo !"

Adicionalmente, la función paste viene con un un argumento llamado sep el cual, por defautl, viene con un espacio.

paste(qx[2],qx[3],qx[1],qx[4],"!",sep=" ")
## [1] "R es el mejor lenguaje del mundo !"
paste(qx[2],qx[3],qx[1],qx[4],"!",sep="")
## [1] "Res el mejorlenguajedel mundo!"
paste(qx[2],qx[3],qx[1],qx[4],"!",sep="     ")
## [1] "R     es el mejor     lenguaje     del mundo     !"
paste(qx[2],qx[3],qx[1],qx[4],"!",sep="---")
## [1] "R---es el mejor---lenguaje---del mundo---!"

Adicionalmente, R puede coercionar como texto algunos objetos para ser utilizados luego, por ejemplo, en el reporte de datos.

a <- 10
b <- 5
print(a)
## [1] 10
print(b)
## [1] 5
paste("¿A cuánto equivale la suma de ",a," y ",b,"?","  Respuesta: ",a+b, sep="")
## [1] "¿A cuánto equivale la suma de 10 y 5?  Respuesta: 15"
paste("¿A cuánto equivale la suma de",a,"y",b,"?","Respuesta:",a+b,sep=" ")
## [1] "¿A cuánto equivale la suma de 10 y 5 ? Respuesta: 15"

Existen algunas formas para ’escapar’ de los textos (de las comillas). Es decir, cuando colocamos los siguientes caracteres dentro de nuestros textos no son reconocidos como textos:

Listas y DataFrame

Los vectores, matrices y arreglos (arrays) estructuras de almacenamiento efcientes en R pero tienen una gran limitación: sólo pueden almacenar un tipo de data (númerico, texto, etc.). R tiene dos estructuras que permiten combinar distintos tipos de información, además de que hacen posible realizar cálculos y análisis de manera más convenientes. Estos son las listas y data frames.

Listas de objetos

Las listas son estructuras bastante útiles que pueden ser utilizadas para agrupar distintas estructuras y objetos en R. Una lista podría contener una matriz, un array de valores lógicos, un vector con texto, etc.

Para crear una lista se debe hacer lo siguiente:

lista <- list(matrix(data=1:4,nrow=2,ncol=2),c(T,T,F,T),c("Hola a todos","!"))
print(lista)
## [[1]]
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## [[2]]
## [1]  TRUE  TRUE FALSE  TRUE
## 
## [[3]]
## [1] "Hola a todos" "!"
length(lista)
## [1] 3

Uno puede acceder a los componentes de una lista utilizando índices, solo que esta vez se necesitan dos paréntesis cuadrados:

lista[[2]]
## [1]  TRUE  TRUE FALSE  TRUE
lista[[1]]
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
lista[[3]][2]
## [1] "!"

Sin embargo, todavía es posible acceder a los elementos dentro de los objetos de la lista. Por ejemplo, supongamos que queremos los valores de la columna dos de la matriz inserta en la variable lista:

lista[[1]][1,2]
## [1] 3

O la última palabra en la expresión ‘Hola a todos!’ ubicada en la posición tres (3) de la lista:

lista[[3]][2]
## [1] "!"

¿Cómo podríamos seleccionar los primeros dos elementos de la lista?

print(lista)
## [[1]]
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## [[2]]
## [1]  TRUE  TRUE FALSE  TRUE
## 
## [[3]]
## [1] "Hola a todos" "!"
#Opción 1:
#lista[[c(1,2)]]
#Opción 2:
#lista[c(1,2)]
lista[[c(1,2)]]
## [1] 2
lista[c(1,2)]
## [[1]]
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## [[2]]
## [1]  TRUE  TRUE FALSE  TRUE

Para seleccionar varios elementos de la lista sólo se utiliza un paréntesis cuadrado (y no los dos).

Una forma alternativa de extraer los elementos de la lista es colocándoles nombres y luego utilizándolos para hacer la extracción:

names(lista)<- c("matriz","logicos","texto")
print(lista)
## $matriz
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## $logicos
## [1]  TRUE  TRUE FALSE  TRUE
## 
## $texto
## [1] "Hola a todos" "!"

Ahora se puede hacer la extracción utilizándo el símbolo de dólar ($):

lista$matriz
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
#lista[[1]]
lista$matriz[,2]
## [1] 3 4
lista$texto[1]
## [1] "Hola a todos"

Finalmente, a la hora de crear la lista se pudieron haber asignado nombre de la siguiente manera:

lista2 <- list(matriz2=matrix(data=1:4,nrow=2,ncol=2),logicos2=c(T,T,F,T),texto2=c("Hola a todos","!"))
print(lista2)
## $matriz2
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## $logicos2
## [1]  TRUE  TRUE FALSE  TRUE
## 
## $texto2
## [1] "Hola a todos" "!"

Un tema adicional es las listas de lista. Sin embargo, salvo que se quieran hacer cómputos muy complejos (iterar sobre distintos objetos o base de datos), no son de interés inmediato.

Data Frame

El Data Frame es tal vez la estructura más importante para el análisis de datos, es menos general que las listas pero suficientemente general como para permitirnos trabajar con distintos tipos de variables. Para los usuarios de excel, es lo más parecido a una hoja/planilla de la herramienta.

A diferencia de otras estructuras, para formar un data frame los vectores que lo componen (ya sean texto, numéricos, etc) deben tener el mismo tamaño (length):

dataframe <- data.frame(persona=c("Pedro","Luis","María","Christian","Esteban"),
edad=c(42,40,17,14,1),sexo=c("M","F","F","M","M"))

print(dataframe)
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    F
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M

Nota: Regularmente (y lo veremos luego), nosotros vamos a importar algún archivo con información (texto, excel, stata, spss, etc…), el cual se almacena como data frame. Sin embargo, primero debemos familiarizarnos con la estructura.

dataframe
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    F
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M

¿Qué sucede? Si nos fijamos en la estructura de las variables, tanto persona como sexo están almacenadas como fct, una abreviación para el tipo de data factor, el cual tiene algunas propiedades interesantes para el análisis de datos las cuales no estamos cubriendo en este curso. Sin embargo no necesitamos dichas propiedades en este momento…

dataframe <- data.frame(persona=c("Pedro","Luis","María","Christian","Esteban"),
edad=c(42,40,17,14,1),sexo=c("M","F","F","M","M"),stringsAsFactors=FALSE)
dataframe
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    F
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M

Ahora, ¿qué tipo de operaciones regularmente realiza un analista de información con su data o qué problemas podría surgir para el análisis de información?

  1. Extraer elementos de la base de datos
  2. Seleccionar elementos que cumplan ciertas condiciones
  3. Adicionar observaciones
  4. Adicionar variables

Extraer elementos

AL igual que en en el caso de una matriz, se utilizan los paréntesis cuadrados.

print(dataframe)
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    F
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M
dataframe[,1] #Seleccionar todas las filas de la columna 1
## [1] "Pedro"     "Luis"      "María"     "Christian" "Esteban"
dataframe$persona
## [1] "Pedro"     "Luis"      "María"     "Christian" "Esteban"
dataframe[dataframe$sexo=="F",]
##   persona edad sexo
## 2    Luis   40    F
## 3   María   17    F
dataframe[dataframe$edad>15,]
##   persona edad sexo
## 1   Pedro   42    M
## 2    Luis   40    F
## 3   María   17    F
dataframe[2,] #Seleccionar el elemento de la fila 2.
##   persona edad sexo
## 2    Luis   40    F
print(dataframe)
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    F
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M
dataframe[2,3]
## [1] "F"
dataframe[dataframe$persona=="Luis","sexo"]
## [1] "F"
dataframe[dataframe$persona=="Luis",3] <- "M"
dataframe
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    M
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M

Adicionalmente, se puede utilizar el símbolo de dólar ($) al igual que en las listas:

dataframe$persona
## [1] "Pedro"     "Luis"      "María"     "Christian" "Esteban"
dataframe$persona[2]
## [1] "Luis"

Seleccionar basado en condiciones

A veces se necesita examinar un subgrupo de nuestros datos que cumplan una determinada condición. Por ejemplo, operaciones de consumo o la proporción de individuos hombres que tienen una tarjeta,…,etc.

dataframe
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    M
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M
dataframe$sexo == "M"
## [1]  TRUE  TRUE FALSE  TRUE  TRUE

¿Qué sucedió? Se creó un vector de índices con valores verdaderos y falsos. Se puede ocupar este índice para seleccionar todas las filas en las cuales el sexo de los individuos sea masculino.

data_hombres <- dataframe[dataframe$sexo == "M",]
data_hombres
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    M
## 4 Christian   14    M
## 5   Esteban    1    M
dataframe[dataframe$sexo == "M",c("persona","edad")]
##     persona edad
## 1     Pedro   42
## 2      Luis   40
## 4 Christian   14
## 5   Esteban    1

Añadir columnas

Añadir columnas a un data frame (combinar observaciones) no es diferente a combinar arreglos o matrices. Se utiliza la función cbind.

dataframe <- data.frame(persona=c("Pedro","Luis","María","Christian","Esteban"),
edad=c(42,40,17,14,1),sexo=c("M","M","F","M","M"),stringsAsFactors=FALSE)
dataframe
##     persona edad sexo
## 1     Pedro   42    M
## 2      Luis   40    M
## 3     María   17    F
## 4 Christian   14    M
## 5   Esteban    1    M
estatura <- c("Alto","Alto","Bajo","Medio","Alto")
dataframe <- cbind(dataframe,estatura)
dataframe
##     persona edad sexo estatura
## 1     Pedro   42    M     Alto
## 2      Luis   40    M     Alto
## 3     María   17    F     Bajo
## 4 Christian   14    M    Medio
## 5   Esteban    1    M     Alto
dataframe$altura <- c("Alto","Alto","Bajo","Medio","Alto")
dataframe
##     persona edad sexo estatura altura
## 1     Pedro   42    M     Alto   Alto
## 2      Luis   40    M     Alto   Alto
## 3     María   17    F     Bajo   Bajo
## 4 Christian   14    M    Medio  Medio
## 5   Esteban    1    M     Alto   Alto
dataframe$estatura <- as.character(dataframe$estatura)
dataframe
##     persona edad sexo estatura altura
## 1     Pedro   42    M     Alto   Alto
## 2      Luis   40    M     Alto   Alto
## 3     María   17    F     Bajo   Bajo
## 4 Christian   14    M    Medio  Medio
## 5   Esteban    1    M     Alto   Alto
Anterior
Siguiente