1 Semana I

1.1 Tipos de datos y objetos en R

Estos tipos de datos, o modos, definen cómo se almacenan los valores en la computadora. Puede obtener el modo de un objeto usando la función typeof (). Tenga en cuenta que R también tiene una función mode () incorporada que servirá para el mismo propósito con la única excepción de que no distinguirá enteros de dobles.

R reconoce una variedad de tipos de datos, estos tipos de datos, definen cómo se almacenan los valores en la computadora. Los tipos de datos son estructurados en diferentes objetos o estructuras de datos, los tipos de datos que R reconoce son los siguientes:

Tipo de Dato Descripción
numeric Números con decimales
integer Números enteros
character Cadenas de texto
Complex Números complejos
logical valores lógicos, TRUE o FALSE

1.1.1 Crear variables

Para crear una variable de cualquiera de los tipos que se mencionó previamente se usa el comando concatenar, su sintaxis es la siguiente

x<-c(1)

La instrucción anterior crea una variable de tipo numerico, la función class() me permite verificar el tipo de dato

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

A continuación vamos a estudiar los principales objetos en R

1.1.2 Vectores

Son considerados como el objeto más básico en R, todos los elementos que componen un vector deben ser del mismo tipo, para crear un vector usarmos la función concatenar c() separando cada elemento por una coma, por ejemplo:

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

Hemos creado un vector de tamaño 3 con los elementos 1, 2 y 3, podemos verificar su tipo mediante class()

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

y notamos que es un vector de tipo numérico, también observemos que ya antes habiamos definido la variable x y perfectamente pudimos hacer una reasignación a esta variable, es decir, x pierde la información que tenia antes para guardar la nueva información.

Los vectores de tipo character son creados de la forma:

nombres<-c("Carlos","Maria","Daniel","Jorge","Luisa")
nombres
## [1] "Carlos" "Maria"  "Daniel" "Jorge"  "Luisa"
class(nombres)
## [1] "character"

Veamos que sucede si en un mismo vector colocamos diferentes tipos de datos

mezcla<-c(45,"Carlos",TRUE)
mezcla
## [1] "45"     "Carlos" "TRUE"
class(mezcla)
## [1] "character"

1.1.2.1 Secuencias

En R podemos crear secuencias de números indicando en que valor empezar, en que valor terminar y el salto. La primera forma de crear secuencia es indicar el valor inicial : valor final:

secuencia<-c(1:10)
secuencia
##  [1]  1  2  3  4  5  6  7  8  9 10

Hemos indicado crear una secuencia partiendo del número 1 y terminando en el 10, por defecto R asume que el salto debe hacerlo de uno en uno. Podemos personalizar mas las secuencias mediante la función seq, los parámetros de la función son from indica de que valor parte la secuencia, to indica hasa que valor termina la secuencia y by indica el salto de la secuencia

secuencia<-seq(from=1,to=10,by=2)
secuencia
## [1] 1 3 5 7 9

Los nombres de los parámetros pueden omitirse y obtenemos el mismo resultado

secuencia<-seq(1,10,2)
secuencia
## [1] 1 3 5 7 9

Otra forma de crear secuencias es indicar de donde partir hasta donde llegar y la longitud de la secuencia mediante el parámetro length

secuencia1<-seq(from=1,to=10,length = 5)
secuencia1
## [1]  1.00  3.25  5.50  7.75 10.00
secuencia2<-seq(from=1,to=10,length = 20)
secuencia2
##  [1]  1.000000  1.473684  1.947368  2.421053  2.894737  3.368421  3.842105
##  [8]  4.315789  4.789474  5.263158  5.736842  6.210526  6.684211  7.157895
## [15]  7.631579  8.105263  8.578947  9.052632  9.526316 10.000000

1.1.2.2 Acceder a valores de un vector

Nos va a interesar poder acceder, manipular, borrar o agregar entradas a un vector, para acceder a un valor especifico o varios valores en especifico, debemos indicarlo colocando el nombre del vector y entre corchetes el valor al que queremos acceder.

Por ejemplo, queremos acceder al 4 elemento del vector nombres, la forma de hacer esto es la siguiente:

nombres<-c("Carlos","Maria","Daniel","Jorge","Luisa")
nombres
## [1] "Carlos" "Maria"  "Daniel" "Jorge"  "Luisa"
nombres[4]
## [1] "Jorge"

Podemos acceder a varios valores, por ejemplo si estos son consecutivos lo hacemos con `:, si queremos acceder a los nombres 2, 3 y 4 lo hacemos de la forma:

nombres[2:4]
## [1] "Maria"  "Daniel" "Jorge"

Si estos valors no son consecutivos indicamos el vector de posiciones al que queremos acceder, por ejemplo a los nombres 1,3 y 5, lo hacemos así.

nombres[c(1,3,5)]
## [1] "Carlos" "Daniel" "Luisa"

Si lo que queremos es eliminar algún valor lo hacemos colocando el simbolo - antes de el valor o valores que queremos eliminar, a continuación eliminamos el nombre 1 y 2.

nombres[-c(1,3)]
## [1] "Maria" "Jorge" "Luisa"

Notemos que no hemos guardado la instrucción anterior en una variable, por tanto el vector nombres sigue siendo el mismo

nombres
## [1] "Carlos" "Maria"  "Daniel" "Jorge"  "Luisa"

Si lo que queremos es eliminar definitivamente los nombres 1 y 3 debemos asignar la instrucción de borrar en el vector nombres o en un nuevo vector si queremos conservar el original.

nombres<-nombres[-c(1,3)]
nombres
## [1] "Maria" "Jorge" "Luisa"

Si queremos agregar un numevo nombre o varios nombres nuevos, solo debemos concatenar al vector anterior el nuevo vector, queremos agregar los nombres Alejandra y Manuel, lo hacemos de la siguiente forma:

nombres<-c(nombres,"Alejandra","Manuel")
nombres
## [1] "Maria"     "Jorge"     "Luisa"     "Alejandra" "Manuel"

1.1.2.3 Operaciones con vectores

En R podemos hacer las operaciones aritmeticas básicas: adución sustracción, multiplicación y división. La mayoría de las funciones en R están vectorizadas, lo que significa que la función operará sobre todos los elementos de un vector sin necesidad de recorrer cada elemento y actuar sobre cada uno de ellos. Esto hace la escritura de código más concisa, fácil de leer y menos propenso a errores.

x<-c(1,6,9,3)
y<-c(5,2,4,7)
x+y
## [1]  6  8 13 10
x-y
## [1] -4  4  5 -4
x*y
## [1]  5 12 36 21
x/y
## [1] 0.2000000 3.0000000 2.2500000 0.4285714

Notemos que cara operación la realiza elemento a elemento, incluyendo la división, también podemos sumar, restar, multiplicar y dividir constantes a un vector, y lo que esto hace es que aplica la operación a cada elemento

x<-c(2,7,5)
x+10
## [1] 12 17 15
x/5
## [1] 0.4 1.4 1.0
2*x
## [1]  4 14 10
5/x
## [1] 2.5000000 0.7142857 1.0000000

Algunas otras funciones que son aplicables a vectores son:

  • sum suma los elementos de un vector
  • prod hace el producto de los elementos del vectro
  • length devuelve el número de elementos que tiene el vector
  • mean devuelve el promedio de los elementos del vector
sum(x)
## [1] 14
prod(x)
## [1] 70
length(x)
## [1] 3
mean(x)
## [1] 4.666667

1.1.3 Matrices

Las matrices son otra forma de almacenar valores, son estructuras bidimensionales, que poseen filas y columnas de valores, todos los valores dentro de una matriz, al igual que en un vector, deben ser del mismo tipo, todos numericos, todos caracteres, todos lógicos etc…

Para crear una matriz usamos la función matrix, idicamos los valores que debe contener la matriz, si no definimos filas y columnas por defecto las matrices son vectores columna

matriz<-matrix(c(1,2,3,4,5,6))

Si queremos indicar número de filas agregamos nrow y número de columnas con ncol, la siguiente instrucción crea una matriz de dos filas con 3 columnas

matriz<-matrix(c(1,2,3,4,5,6),nrow = 2,ncol = 3)
matriz
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6

Notemos que por defecto R toma las entradas de los datos como las columnas de la matriz, es decir, en este caso como tenemos 3 columnas y dos filas, cada columna tiene dos elementos y los toma de dos en dos del vector de datos para formar la matriz, si queremos cambiar esto, es decir que tome los valores por fila, debemos agregar el parámetro byrow=T

matriz<-matrix(c(1,2,3,4,5,6),nrow = 2,ncol = 3,byrow = T)
matriz
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6

1.1.3.1 Acceder a los valores de una matriz

Para acceder a los valores de matrices lo hacemos indicando la fila y columna correspondiente al valor, por ejemplo si queremos acceder al elemento de la fila 2 en la columna 3 de el último ejemplo lo hacemos así:

matriz<-matrix(c(1,2,3,4,5,6),nrow = 2,ncol = 3,byrow = T)
matriz
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
matriz[2,3]
## [1] 6

Siempre indicamos primero la fila y luego la columna, si queremos acceder a una fila completa lo hacemos indicando el número de fila, dejando vacio el espacio de la columna y si lo que queremos es una columna, lo hacemos indicando la columna, dejando en blanco la fila. A continuación vamos a acceder a la segunda columna y luego a la sefunda fila de la matriz

matriz
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
matriz[,2] # segunda columna
## [1] 2 5
matriz[2,] # segunda fila
## [1] 4 5 6

1.1.3.2 Operaciones con matrices

A igual que en los vectores, las operciones aritmeticas se realizan elemento a elemento de las matrices, por tanto, debemos asegurarnos que ambas tengan la misma cantidad de filas y columnas. En este caso debemos tener cuidado ya que el operador * no realizará la multiplicación de matrices usual, el resultado que se obtiene es la multiplicación elemento a elemento, y / dividira elemento a elemento, algo que algebrá de matrices no está definido. Veamos algunos ejemplos:

A<-matrix(c(1:4),ncol = 2,nrow = 2)
B<-matrix(c(5:8),ncol = 2,nrow = 2)
A
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
B
##      [,1] [,2]
## [1,]    5    7
## [2,]    6    8
A+B
##      [,1] [,2]
## [1,]    6   10
## [2,]    8   12
A-B
##      [,1] [,2]
## [1,]   -4   -4
## [2,]   -4   -4
A*B
##      [,1] [,2]
## [1,]    5   21
## [2,]   12   32
A/B
##           [,1]      [,2]
## [1,] 0.2000000 0.4285714
## [2,] 0.3333333 0.5000000
2*A
##      [,1] [,2]
## [1,]    2    6
## [2,]    4    8
3/B
##      [,1]      [,2]
## [1,]  0.6 0.4285714
## [2,]  0.5 0.3750000
A+10
##      [,1] [,2]
## [1,]   11   13
## [2,]   12   14
A^2
##      [,1] [,2]
## [1,]    1    9
## [2,]    4   16

1.1.3.3 Paquete matlib

Si queremos realizar operaciones con matrices, como la multiplicación, inversas, traspuestas, etc,… Debemos hacer uso del paquete matlib, primero debemos instalar el paquete y luego cargarlo para poder usarlo.

install.packages("matlib")
library(matlib)

Dentro del paquete matlib tenemos las siguientes funciones y operaciones:

  • %*% Operador de producto de matrices
  • Det Determinante de una matriz
  • tr Traza de una matriz
  • inv Inversa de una matriz

Y muchas más, veamos los ejemplos:

A%*%B
##      [,1] [,2]
## [1,]   23   31
## [2,]   34   46
Det(B)
## [1] -2
tr(A)
## [1] 5
inv(A)
##      [,1] [,2]
## [1,]   -2  1.5
## [2,]    1 -0.5
inv(A)%*%A
##      [,1] [,2]
## [1,]    1    0
## [2,]    0    1

1.1.4 Listas

A diferencia de las estructuras anteriores, vectores y matrices, una lista es una colección de elementos de diferente tipo, es decir, que un elemento puede ser un número, otro un caracter, otro un vector, otro una matriz, incluso puede tener otra lista, para crear una lista usamos la función list indicando sus elementos separados por coma, veamos un ejemplo.

x<-c(45)
nombres<-c("Carlos","Maria","Daniel","Jorge","Luisa")
A<-matrix(c(1:4),ncol = 2,nrow = 2)
lista<-list(x,nombres,A)
lista
## [[1]]
## [1] 45
## 
## [[2]]
## [1] "Carlos" "Maria"  "Daniel" "Jorge"  "Luisa" 
## 
## [[3]]
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4

Acabamos de crear una lista con 3 elementos, un número, un vector de nombres y una matriz, la función str nos indica la estructura de la lista especificando el tipo de dato que es cada entrada

str(lista)
## List of 3
##  $ : num 45
##  $ : chr [1:5] "Carlos" "Maria" "Daniel" "Jorge" ...
##  $ : int [1:2, 1:2] 1 2 3 4

Ahora si queremos acceder a un elemento especifico de una lista lo hacemos con [[]] indicando el número del elemento al que queremos acceder, por ejemplo, si queremos acceder el segundo elemento de la lista lo hacemos de la forma:

lista[[2]]
## [1] "Carlos" "Maria"  "Daniel" "Jorge"  "Luisa"

Las listas son estructuras muy útiles cuando trabajamos con funciones y queremos retornar mas de un valor a la vez.

1.1.5 Data frames

Un data frame es una estructura de datos bidimensional similar a una matriz, pero funciona de manera muy diferente. Si bien un data frame parece una tabla simple, de hecho es una lista de vectores de la misma longitud. Para los nuevos usuarios de R, las matrices y los data frames parecen similares. La principal diferencia es que un data frame permite tipos de datos mixtos (por ejemplo, numérico, lógico, caracter). Esto les permite almacenar diferentes tipos de variables, lo cual es muy útil en el análisis estadístico.

Para crear un data frame usamos la función data.frame por ejemplo:

nombres<-c("Carlos","Maria","Daniel","Jorge","Luisa")
edades<-c(12,34,21,24,44)
genero<-c("M","F","M","M","F")

Notemos que tenemos tres vectores de la misma dimensión, 5, uno indica nombres(caracter), el otro edades(números) y un último el género(caracteres), la estructura de datos más adecuada para almacenar toda esta información es unn data frame, ya que este me permitirá mantener los tipos de datos.

datos<-data.frame(nombres,edades,genero)
datos
##   nombres edades genero
## 1  Carlos     12      M
## 2   Maria     34      F
## 3  Daniel     21      M
## 4   Jorge     24      M
## 5   Luisa     44      F

Observemos el resultado, si se tratara de una encuesta, cada fila indicaría la información de cada individuo, mientras que cada columna una variable, con `str podemos verificar que, en efecto, el tipo de dato de cada columna se mantuvo intacto.

str(datos)
## 'data.frame':    5 obs. of  3 variables:
##  $ nombres: chr  "Carlos" "Maria" "Daniel" "Jorge" ...
##  $ edades : num  12 34 21 24 44
##  $ genero : chr  "M" "F" "M" "M" ...

1.1.5.1 Factores

Notemos la variable genero esta variable originalmente está siendo tratada como caracter, de los cursos básicos de estadística sabemos que la variable genero es una variable del tipo cualitativa o categórica, este tipo de variables son aquellas que toman un conjunto fijo y conocido de valores posibles, en R este tipo de variables se llaman factores y es convenienete tratarlos como tales.

Por ejemplo, suponga que una variable es estado civil, esta varible tomará los valores de soltero, casado y divorciado, cada una de estas categorias llevara una codificación numérica, puede ser: 0: soltero, 1: casado, 2:divorciado, y a las palabras, soltero, casado y divorciado se le llaman etiquetas. Para crear un factor lo hacemos con factor indicando los valores y opcionalmente etiquetas y valores.

estCivil<-factor(c(1,2,3,1,1),levels = c(1,2,3),labels = c("Soltero","Casado","Divorciado") )

Ahora podemos crear nuestro data frame agregando este nuevo factor

datos<-data.frame(nombres,edades,genero,estCivil)
datos
##   nombres edades genero   estCivil
## 1  Carlos     12      M    Soltero
## 2   Maria     34      F     Casado
## 3  Daniel     21      M Divorciado
## 4   Jorge     24      M    Soltero
## 5   Luisa     44      F    Soltero
str(datos)
## 'data.frame':    5 obs. of  4 variables:
##  $ nombres : chr  "Carlos" "Maria" "Daniel" "Jorge" ...
##  $ edades  : num  12 34 21 24 44
##  $ genero  : chr  "M" "F" "M" "M" ...
##  $ estCivil: Factor w/ 3 levels "Soltero","Casado",..: 1 2 3 1 1

1.1.5.2 Conversión de datos

Algunas veces vamos a querer convertir datos de un tipo en otro, por ejemplo, convertir un vector de números en caracteres o viceversa, en caso de que sea posible. Por ejemplo si tenemos un vector de caracteres numericos y queremos convertirlos a numérico lo hacemos así:

numeros<-c("3","6","45")
numeros
## [1] "3"  "6"  "45"
class(numeros)
## [1] "character"
numeros<-as.numeric(numeros)
numeros
## [1]  3  6 45
class(numeros)
## [1] "numeric"

También podemos convertir a factores, por ejemplo, si queremos convertir la variable genero que es de tipo caracter a factor con dos niveles. De hecho podemos hacer esta conversión adentro de la misma variable, veamos:

str(genero)
##  chr [1:5] "M" "F" "M" "M" "F"
genero<-as.factor(genero)
str(genero)
##  Factor w/ 2 levels "F","M": 2 1 2 2 1

Recordemos que el hecho de haber convertido genero a factor no significa que en el data frame datos también se haya cambiado.

str(datos)
## 'data.frame':    5 obs. of  4 variables:
##  $ nombres : chr  "Carlos" "Maria" "Daniel" "Jorge" ...
##  $ edades  : num  12 34 21 24 44
##  $ genero  : chr  "M" "F" "M" "M" ...
##  $ estCivil: Factor w/ 3 levels "Soltero","Casado",..: 1 2 3 1 1
datos<-data.frame(nombres,edades,genero,estCivil)
datos
##   nombres edades genero   estCivil
## 1  Carlos     12      M    Soltero
## 2   Maria     34      F     Casado
## 3  Daniel     21      M Divorciado
## 4   Jorge     24      M    Soltero
## 5   Luisa     44      F    Soltero
str(datos)
## 'data.frame':    5 obs. of  4 variables:
##  $ nombres : chr  "Carlos" "Maria" "Daniel" "Jorge" ...
##  $ edades  : num  12 34 21 24 44
##  $ genero  : Factor w/ 2 levels "F","M": 2 1 2 2 1
##  $ estCivil: Factor w/ 3 levels "Soltero","Casado",..: 1 2 3 1 1

1.2 Manipulación de datos

Una vez tengamos recolectados nuestros datos en distintos formatos, vamos a querer leerlos en R, hacer una limpieza o un analisis exploratorio de los mismos.

Los datos bien estructurados tienen dos porpositos:

  • Hace que los datos sean adecuados para el procesamiento del software, ya sean funciones matemáticas, visualización, etc.

  • Revela información y nuevas perspectivas.

Cuando hablamos de manipulación de datos nos referimos a leerlos, acceder a alguna parte de ellos, realizar limpiezas, aplicar filtros, etc. Esto en R se puede hacer con los paquetes instalados por defecto, pero también lo podemos hacer con Tidyverse, este es un conjunto de paquetes en R diseñados para ciencia de datos. Esto lo que significa es que ayuda en todo el proceso de importar transformar visualizar modelar y comunicar toda la información que normalmente utilizamos en procesos de ciencia de datos.

La ventaja que tienen estos paquetes que comparten nombre y estructuras comunes. Hay cosas como por ejemplo que todos los nombres están en minúscula o que utilizan la barra baja para llamar a las funciones.

Antes de iniciar esta parte debemos instalar el paquete tydyver

install.packages("tidyverse")
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.5     ✓ purrr   0.3.4
## ✓ tibble  3.1.6     ✓ dplyr   1.0.7
## ✓ tidyr   1.1.4     ✓ stringr 1.4.0
## ✓ readr   2.1.1     ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()

Este paquete instalará además otras dependencias, otros paquetes que son necesarios, por lo que podría llevarnos un poco de tiempo la instalación.

1.2.1 Importar datos

Podemos leer archivos de datos de diferentes formatos, como ser los utilizados por excel, SPSS, STATA, separados por comas, etc…

Primero veamos como leer arvhivos en formato .csv, para esto tenemos dos opciones

datos <- read.csv(file = 'nombre_de_archivo.csv') # datos será un 'data frame'
datos <- read_csv(file = 'nombre_de_archivo.csv') # datos será un 'tibble'

La primera linea de código leera los datos y los almacenará como un data frame, mientras que la seguna opción los almacenará como un tibble, estructura de los datos en el tydiverse.

Ejemplo: Leamos el archivo titanic.csv en ambos formatos

titanic_df <- read.csv(file = 'titanic.csv') 
titanic_tib <- read_csv(file = 'titanic.csv')
## Rows: 1309 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (6): name, sex, age, ticket, fare, embarked
## dbl (4): pclass, survived, sibsp, parch
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Este archivo contiene información sobre la tripulación del titanic, hagamos una descripción del conjunto de datos. Las funciones head y tail nos muestran los primeros y ultimos datos del data frame.

str(titanic_df)
head(titanic_df)
tail(titanic_df)
str(titanic_tib)

Para acceder a las variables de un data frame podemos hacerlo asi nombre_data_frame$nombre_variable colocando el nombre del data frame, el simbolo $ y el nombre de la variable, si queremos acceder a la variable age lo hacemos así:

titanic_df$age

Otra forma es utilizando la función attach() y detach() esto establece el data frame y no hay necesidad de especificar el nombre para acceder a las variables.

age
attach(titanic_df)
age
detach(titanic_df)
age

Algunos conjutos de datos contienen datos faltantes cuando leimos la data del titanic con read.csv notemos que no se reconocieron los valores NA, esto se puede corregir asi:

titanic_df <- read.csv(file = 'titanic.csv',na.strings = "") 

Si lo que queremos es eliminar los NA de toda la data lo podemos hacer con la función na.omit()

titanicnoNA<-na.omit(titanic_df)

1.2.2 Manipular datos con dplyr

Algunas veces vamos a querer filtrar un conjunto de datos, es decir obtener un subconjunto de los datos que tengan alguna caracteristica. Consideremos la data del titanic, estamos interesados en obtener solamente las observaciones de personas mayores de 50 años.

m50_1<-titanic_df[titanic_df$age>50,]

m50_2<-subset(titanic_df,titanic_df$age>50)

Podemos tener propocisiones compuestas para filtrar los datos, por ejemplo queremos personas mayores de 50 años y además que viajaban en primera clase.

primera1_50<-titanic_df[titanic_df$age>50 & titanic_df$pclass==1,]

primera2_50<-subset(titanic_df,titanic_df$age>50 & titanic_df$pclass==1)

Ahora como hacemos esto en el tydiverse, el paquete encargado de hacer esto es dplyr este paquete no proporciona ninguna nueva funcionalidad a R, en el sentido que todo aquello que podemos hacer con dplyr lo podríamos hacer con la sintaxis básica de R.

Una importante contribución del paquete dplyr es que proporciona una “gramática” (particularmente verbos) para la manipulación y operaciones con data frames. Con esta gramática podemos comunicar mediante nuestro código que es lo que estamos haciendo en los data frames a otras personas (asumiendo que conozcan la gramática). Esto es muy útil, ya que proporciona una abstracción que anteriormente no existía. Por último, cabe destacar que las funciones del paquete dplyr son muy rápidas, puesto que están implementadas con el lenguaje C++.

Algunas de los principales “verbos” del paquete dplyr son:

  • select: devuelve un conjunto de columnas
  • filter: devuelve un conjunto de filas según una o varias condiciones lógicas
  • arrange: reordena filas de un data frame
  • rename: renombra variables en una data frame
  • mutate: añade nuevas variables/columnas o transforma variables existentes
  • summarise/summarize: genera resúmenes estadísticos de diferentes variables en el data frame.
  • _%>% : el operador “pipe” es usado para conectar múltiples acciones en una única “pipeline” (tubería)

veamos algunas de estas funciones

select(titanic_tib,age)
select(titanic_tib,sex,name)
select(titanic_tib,-age)
filter(titanic_tib,age>50)
filter(titanic_tib,age>50 & titanic_df$pclass==1)
titanicEDAD<-arrange(titanic_tib, age)
titanic_tib<-rename(titanic_tib, clase = pclass, sobreviviente = survived, nombre = name, sexo = sex, edad=age)
Iris<-iris
Iris<-mutate(Iris,ratio=Sepal.Length/Petal.Length)
dataN<-titanic_tib %>%
  filter(edad<20) %>%
  select(clase,sobreviviente,edad)

1.2.3 Combinar datos

Algunas veces podemos tener dos o más conjuntos de datos con estructura parecida y vamos a querer combinar estos datos en un solo data frame, para hacer esto tenemos que tener en cuenta que:

  1. Cada observación en los conjuntos de datos debe tener un identificador
  2. Las variables deben llamarse igual en los conjuntos de datos.

La función rbind() sirve para unir los data frames por filas, veamos un ejemplo

library(dplyr)
animal1<-c("vaca","perro","rana","lagarto","mosca","paloma")
clase1<-c("mamifero","mamifero","anfibio","reptil","insecto","ave")

animales1 <- data.frame(animal1,clase1)
animales1
##   animal1   clase1
## 1    vaca mamifero
## 2   perro mamifero
## 3    rana  anfibio
## 4 lagarto   reptil
## 5   mosca  insecto
## 6  paloma      ave
animal2<-c("atun", "cocodrilo", "gato","rana")
clase2<-c("pez", "reptil", "mamifero","anfibio")

animales2 <- data.frame(animal2,clase2 )
animales2
##     animal2   clase2
## 1      atun      pez
## 2 cocodrilo   reptil
## 3      gato mamifero
## 4      rana  anfibio
#animales3 <- rbind(animales1,animales2) # error ambas columnas deben tener el mismo nombre

animales1<-rename(animales1, animal = animal1, clase=clase1)
animales1
##    animal    clase
## 1    vaca mamifero
## 2   perro mamifero
## 3    rana  anfibio
## 4 lagarto   reptil
## 5   mosca  insecto
## 6  paloma      ave
animales2<-rename(animales2, animal = animal2, clase=clase2)
animales2
##      animal    clase
## 1      atun      pez
## 2 cocodrilo   reptil
## 3      gato mamifero
## 4      rana  anfibio
animales3 <- rbind(animales1,animales2)
animales3
##       animal    clase
## 1       vaca mamifero
## 2      perro mamifero
## 3       rana  anfibio
## 4    lagarto   reptil
## 5      mosca  insecto
## 6     paloma      ave
## 7       atun      pez
## 8  cocodrilo   reptil
## 9       gato mamifero
## 10      rana  anfibio

Otra función muy útil para unir archivos es la función merge()

animales4<-merge(animales1,animales2)
animales4 # muestra solo las filas comunes
##   animal   clase
## 1   rana anfibio
animales5<-merge(animales1,animales2,all=T)
animales5
##      animal    clase
## 1      atun      pez
## 2 cocodrilo   reptil
## 3      gato mamifero
## 4   lagarto   reptil
## 5     mosca  insecto
## 6    paloma      ave
## 7     perro mamifero
## 8      rana  anfibio
## 9      vaca mamifero

Que sucede si mis conjuntos de datos tienen estructuras diferentes y queremos combinarlas, veamos el ejemplo

animal<-c("perro","tortuga","paloma","cocodrilo","vaca","lagarto","sardina")
superficie<-c("pelo","caparazon","plumas","escamas","pelo","escamas","escamas")

superficieAnimales<-data.frame(animal,superficie)

superficieAnimales
##      animal superficie
## 1     perro       pelo
## 2   tortuga  caparazon
## 3    paloma     plumas
## 4 cocodrilo    escamas
## 5      vaca       pelo
## 6   lagarto    escamas
## 7   sardina    escamas
animales3
##       animal    clase
## 1       vaca mamifero
## 2      perro mamifero
## 3       rana  anfibio
## 4    lagarto   reptil
## 5      mosca  insecto
## 6     paloma      ave
## 7       atun      pez
## 8  cocodrilo   reptil
## 9       gato mamifero
## 10      rana  anfibio
merge(animales3,superficieAnimales) # Muestra sólo los animales comunes a ambos dataframes
##      animal    clase superficie
## 1 cocodrilo   reptil    escamas
## 2   lagarto   reptil    escamas
## 3    paloma      ave     plumas
## 4     perro mamifero       pelo
## 5      vaca mamifero       pelo
merge(animales3,superficieAnimales, all.x=TRUE) # Muestra todos los animales del primer dataframe.
##       animal    clase superficie
## 1       atun      pez       <NA>
## 2  cocodrilo   reptil    escamas
## 3       gato mamifero       <NA>
## 4    lagarto   reptil    escamas
## 5      mosca  insecto       <NA>
## 6     paloma      ave     plumas
## 7      perro mamifero       pelo
## 8       rana  anfibio       <NA>
## 9       rana  anfibio       <NA>
## 10      vaca mamifero       pelo
merge(animales3,superficieAnimales, all.y=TRUE) # Muestra todos los animales del segundo dataframe.
##      animal    clase superficie
## 1 cocodrilo   reptil    escamas
## 2   lagarto   reptil    escamas
## 3    paloma      ave     plumas
## 4     perro mamifero       pelo
## 5   sardina     <NA>    escamas
## 6   tortuga     <NA>  caparazon
## 7      vaca mamifero       pelo
merge(animales3,superficieAnimales, all=TRUE) # Muestra todos los animales de ambos dataframes.
##       animal    clase superficie
## 1       atun      pez       <NA>
## 2  cocodrilo   reptil    escamas
## 3       gato mamifero       <NA>
## 4    lagarto   reptil    escamas
## 5      mosca  insecto       <NA>
## 6     paloma      ave     plumas
## 7      perro mamifero       pelo
## 8       rana  anfibio       <NA>
## 9       rana  anfibio       <NA>
## 10   sardina     <NA>    escamas
## 11   tortuga     <NA>  caparazon
## 12      vaca mamifero       pelo

1.3 Ejercicios

  1. Almacene el siguiente valor en una variable con nombre y \[ \frac{1+2\cdot 3^4}{\frac{5}{6}-7} \]
# Solución
y <- (1 + 2*3^4 ) / (5/6 - 7 )
y
## [1] -26.43243
  1. Calcular el índice de masa corporal (IMC) de una persona cuya altura es 1.78 m y su peso es 80 kg. \((IMC = peso / altura^2)\).
# Solución
peso <- 80
altura <- 1.78

IMC<-peso/altura^2
IMC
## [1] 25.24934
  1. Ahora suponga que tenemos los pesos de 5 personas (80, 70, 75, 94, 67) y sus alturas(1.68, 1.75, 1.85, 1.90, 1.68), calcule el indice de masa corporal para las 5 personas.
#Solución
pesos <- c(80, 70, 75, 94, 67)
alturas <- c(1.68, 1.75, 1.85, 1.90, 1.68)
IMC<-pesos/alturas^2
IMC
## [1] 28.34467 22.85714 21.91381 26.03878 23.73866
  1. (Entrega) Escriba un código en R que dada la variable grados, que presenta la temperatura en grados Farenheit, calcule en otra variable el valor en Celcius, pruebe su código con 90 grados Farenheit
# Solución
Farenheit <- 90
Celcius <- 5/9*(Farenheit - 32)
Celcius
## [1] 32.22222
  1. Considere el conjunto de datos 2, 5, 4, 10, 8
    1. Guarde esta data en un vector con nombre x
    2. Encuentre el cuadrado de cada número
    3. Restele 6 a cada número
    4. Restele 9 a cada numero y luego eleve al cuadrado la respuesta (en una sola linea de código)
#Solución
x <- c(2, 5, 4, 10, 8)
x^2 - 6
## [1] -2 19 10 94 58
(x-9)^2
## [1] 49 16 25  1  1
  1. Almacene los siguientes conjuntos de datos en un vector, utilizando : o seq
    1. 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10
# Solución
sa <- 1/(2:10) 
sa
## [1] 0.5000000 0.3333333 0.2500000 0.2000000 0.1666667 0.1428571 0.1250000
## [8] 0.1111111 0.1000000
  1. 1, 8, 27, 64, 125, 216
#Solución
sb <- (1:6)^3 
sb
## [1]   1   8  27  64 125 216
  1. 0, 25, 50, 75, …, 1000 (de 0 a 1000 de 25 en 25)
# Solución
sc <- seq(0,1000,by=25)
sc
##  [1]    0   25   50   75  100  125  150  175  200  225  250  275  300  325  350
## [16]  375  400  425  450  475  500  525  550  575  600  625  650  675  700  725
## [31]  750  775  800  825  850  875  900  925  950  975 1000
  1. “a”, “a”, “a”, “a”, “a”
# Solución
sd <- rep("a",4)
sd
## [1] "a" "a" "a" "a"
  1. “a”, “a”, “b”, “b”, “b”, “c”
# Solución
se <- rep(c("a","b","c"),c(2,3,1)) 
se
## [1] "a" "a" "b" "b" "b" "c"
  1. Calcule la varianza muestral y la desviación estándar muestral, sin usar las funciones var y sd de R para el conjunto de datos trees$Height, la altura de un grupo de árboles de cerezo negro. \[ s^2=\frac{1}{n-1}\sum_{i=1}^n (x_i-\bar{x})^2 \]
# Solución

arboles<-trees$Height # lee la data trees$Height de R
arboles
##  [1] 70 65 63 72 81 83 66 75 80 75 79 76 76 69 75 74 85 86 71 64 78 80 74 72 77
## [26] 81 82 80 80 80 87
n <- length(arboles) # calcula la longitud del vector arboles
n
## [1] 31
xbar <- sum(arboles)/n
xbar
## [1] 76
s2<- (1/(n-1))*sum( (arboles-xbar)^2 )
s2
## [1] 40.6
s <- sqrt(s2)
s
## [1] 6.371813
  1. (Entrega) La distancia promedio desde el centro se calcula mediante \((\vert x_1 -\bar{x}\vert + \vert x_2 -\bar{x}\vert + \cdots +\vert x_n -\bar{x}\vert )/n\), donde \(\bar{x}\) es la media del vector de datos. Calcule esto para el conjunto de datos rivers de usando la función suma para sumar los valores y abs para encontrar el valor absoluto.
#Solución
rios <- rivers
n <- length(rios)
xbar <- sum(rios)/n

# media muestral
xbar
## [1] 591.1844
dif <- abs(rios - xbar) #diferencia de los valores respecto a la media en valor absoluto
dprom <- sum(dif)/n

# distancia promedio
dprom
## [1] 313.5508
  1. El RMS Titanic fue en su momento el mayor barco de pasajeros del mundo, hundiéndose en su viaje inaugural de Southampton a Nueva York en el año 1912. En el evento fallecieron 1514 de las 2223 personas que iban a bordo, entre tripulación y pasajeros. El archivo de datos titanic.csv contiene alguna información sobre los pasajeros, las variables son:
  • \(\textbf{survival}\): supervivencia (0 No, 1 Sí).

  • \(\textbf{pclass}\): clase del pasajero (1,2 o 3).

  • \(\textbf{sex}\): sexo del pasajero

  • \(\textbf{age}\): edad del pasajero.

  • \(\textbf{sibsp}\): cantidad de hermanos y cónyuges (totalizado) embarcados (número entero).

  • \(\textbf{parch}\): cantidad de padres e hijos (totalizado) embarcados (número entero).

  • \(\textbf{ticket}\): código del boleto (texto).

  • \(\textbf{fare}\): tarifa del pasaje (número real).

  • \(\textbf{embarked}\): puerto de embarque (S= Southampton, Q=Queenstown, C = Cherbourg)

    1. Lea los datos de titanic.csv y códifique cada variable en el tipo adecuado.
#Solución
titanic <- read.csv("titanic.csv")
str(titanic)
## 'data.frame':    1309 obs. of  10 variables:
##  $ pclass  : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ survived: int  1 1 0 0 0 1 1 0 1 0 ...
##  $ name    : chr  "Allen, Miss. Elisabeth Walton" "Allison, Master. Hudson Trevor" "Allison, Miss. Helen Loraine" "Allison, Mr. Hudson Joshua Creighton" ...
##  $ sex     : chr  "female" "male" "female" "male" ...
##  $ age     : chr  "29" "0,9167" "2" "30" ...
##  $ sibsp   : int  0 1 1 1 1 0 1 0 2 0 ...
##  $ parch   : int  0 2 2 2 2 0 0 0 0 0 ...
##  $ ticket  : chr  "24160" "113781" "113781" "113781" ...
##  $ fare    : chr  "211,3375" "151,5500" "151,5500" "151,5500" ...
##  $ embarked: chr  "S" "S" "S" "S" ...
pclass_factor <- as.factor(titanic$pclass)
str(titanic)
## 'data.frame':    1309 obs. of  10 variables:
##  $ pclass  : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ survived: int  1 1 0 0 0 1 1 0 1 0 ...
##  $ name    : chr  "Allen, Miss. Elisabeth Walton" "Allison, Master. Hudson Trevor" "Allison, Miss. Helen Loraine" "Allison, Mr. Hudson Joshua Creighton" ...
##  $ sex     : chr  "female" "male" "female" "male" ...
##  $ age     : chr  "29" "0,9167" "2" "30" ...
##  $ sibsp   : int  0 1 1 1 1 0 1 0 2 0 ...
##  $ parch   : int  0 2 2 2 2 0 0 0 0 0 ...
##  $ ticket  : chr  "24160" "113781" "113781" "113781" ...
##  $ fare    : chr  "211,3375" "151,5500" "151,5500" "151,5500" ...
##  $ embarked: chr  "S" "S" "S" "S" ...
titanic$pclass <-  as.factor(titanic$pclass)
str(titanic)
## 'data.frame':    1309 obs. of  10 variables:
##  $ pclass  : Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
##  $ survived: int  1 1 0 0 0 1 1 0 1 0 ...
##  $ name    : chr  "Allen, Miss. Elisabeth Walton" "Allison, Master. Hudson Trevor" "Allison, Miss. Helen Loraine" "Allison, Mr. Hudson Joshua Creighton" ...
##  $ sex     : chr  "female" "male" "female" "male" ...
##  $ age     : chr  "29" "0,9167" "2" "30" ...
##  $ sibsp   : int  0 1 1 1 1 0 1 0 2 0 ...
##  $ parch   : int  0 2 2 2 2 0 0 0 0 0 ...
##  $ ticket  : chr  "24160" "113781" "113781" "113781" ...
##  $ fare    : chr  "211,3375" "151,5500" "151,5500" "151,5500" ...
##  $ embarked: chr  "S" "S" "S" "S" ...
titanic$age <- as.numeric(titanic$age)
## Warning: NAs introduced by coercion
str(titanic)
## 'data.frame':    1309 obs. of  10 variables:
##  $ pclass  : Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
##  $ survived: int  1 1 0 0 0 1 1 0 1 0 ...
##  $ name    : chr  "Allen, Miss. Elisabeth Walton" "Allison, Master. Hudson Trevor" "Allison, Miss. Helen Loraine" "Allison, Mr. Hudson Joshua Creighton" ...
##  $ sex     : chr  "female" "male" "female" "male" ...
##  $ age     : num  29 NA 2 30 25 48 63 39 53 71 ...
##  $ sibsp   : int  0 1 1 1 1 0 1 0 2 0 ...
##  $ parch   : int  0 2 2 2 2 0 0 0 0 0 ...
##  $ ticket  : chr  "24160" "113781" "113781" "113781" ...
##  $ fare    : chr  "211,3375" "151,5500" "151,5500" "151,5500" ...
##  $ embarked: chr  "S" "S" "S" "S" ...
  1. Extraiga un subconjunto de datos dónde se encuentre la información de las personas que embarcaron en Southampton y cuya edad era de al menos 25 años, el sub conjuto debe estar ordenado por la clase del pasajero, guarde este sub conjunto en un data frame con nombre Southampton25.
#Solución
southhampton25 <- subset(titanic,titanic$age >= 25 & titanic$embarked=="S")
southhampton25<-arrange(southhampton25, pclass)
  1. Divida el archivo en 3 subconjuntos que contengan personas de primera, segunda y tercera clase respectivamente, guardelos en los data frame con nombres Primera_clase, Segunda_clase y Tercera_clase.
# Solución
Primera_clase<-subset(titanic, titanic$pclass==1)
Segunda_clase<-subset(titanic, titanic$pclass==2)
Tercera_clase<-subset(titanic, titanic$pclass==3)
  1. Utilizar el operador pipe para generar el siguiente data frame: Debe contener solo los pasajeros que embarcaron en Queenstown, se debe calcular una nueva variable que indique si la persona es de la tercera edad (mayor de 60 años) o no y no debe contener la columna ticket.
dataFiltrada<-titanic %>%
  filter(embarked=="Q") %>%
  mutate(m60=ifelse( age > 60, 1 ,0 ) )%>%
  select(-ticket)
  1. Vamos a trabajar con la base de datos Iris. Por defecto, la base de datos Iris viene con la instalación de R.
  1. Describir a la base de datos. ¿Cuantas filas tiene?. ¿Y columnas?. ¿Cuantas variables tiene?
#Solución
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
# 150 filas (observaciones)
# 5 columnas (Variables)
  1. Seleccionar las filas que pertenezcan a la especie versicolor.¿Cuantos individuos fueron seleccionados?.
#Solución
Ver <- subset(iris, iris$Species=="versicolor")
  1. Seleccionar solo la columna Petal.Length. ¿Cual es la media de la longitud de los petalos?.
#Solución
long_petalos <- select(iris, Petal.Length)
mean(long_petalos$Petal.Length)
## [1] 3.758
  1. Si suponemos que el area del pétalo se puede estimar como (largo* ancho * \(\pi\)), ¿Cuanto es el área promedio del pétalo de la especie setosa?.
#Solución
iris<-iris %>%
  filter(Species=="setosa")%>%
  mutate(area=Petal.Length*Petal.Width*pi)

mean(iris$area)
## [1] 1.148566
  1. Calcular la frecuencia de individuos de la especie virginica que poseen un Sepal.Width mayor a 3.
#Solución
sepalom3 <- ifelse(iris$Sepal.Width > 3 ,1,0)
sum(sepalom3)
## [1] 42
  1. Calcular la frecuencia de individuos de la especie setosa que poseen un Sepal.Length mayor a 5 y un Petal.Width menor a 0.3.
#Solución
sepalom5_petalom0.3 <- ifelse(iris$Sepal.Length > 5 & iris$Petal.Width < 0.3, 1,0)
sum(sepalom5_petalom0.3)
## [1] 12
  1. Ahora agregale una columna al df que sea la suma de los cuatro atributos para cada individuo.
#Solución
iris <- iris %>%
   mutate(suma=(Sepal.Length + Sepal.Width+Petal.Length + Petal.Width))
  1. (Entrega) Vamos a considerar los archivos morosidad16.xlsx y morosidad17.xlsx que contienen información sobre morosidad, las variables que podemos encontrar son: -id: cédula del deudor ya sea cédula física o jurídica.
  • nombre: Nombre de la persona física o jurídica.
  • deuda16 y deuda17 : monto de la deuda en 2016 y 2017.
  • situación: situación en la que se encuentra la deuda.
  • lugar.pago: sucursal donde se tiene que cancelar la deuda.
  • Estado: Estado de la deuda.
morosidad16 <- read_excel("morosidad16.xlsx")
morosidad17 <- read_excel("morosidad17.xlsx")
  1. Unir las dos bases de morosidad en una sola, dejando todas las observaciones de ambas bases. Guardar en un data frame con nombre morosidad
#Solución
morosidad <- merge(morosidad16, morosidad17)
  1. Haga una descripción de las variables de su base de datos resultante.
#Solución
str(morosidad)
## 'data.frame':    50650 obs. of  7 variables:
##  $ id        : num  1e+08 1e+08 1e+08 1e+08 1e+08 ...
##  $ nombre    : chr  "QUIROS ROJAS MARIA" "QUIROS SALAZAR ADELA" "RAMIREZ RAMIREZ ERNESTO" "MARTINEZ ARRIAGA SARA" ...
##  $ situacion : chr  "DIFICIL COBRO" "DIFICIL COBRO" "DIFICIL COBRO" "COBRO JUDICIAL" ...
##  $ lugar.pago: chr  "SUCURSAL GUADALUPE" "SUCURSAL OFICINAS CENTRALES" "SUCURSAL ALAJUELA" "SUCURSAL OFICINAS CENTRALES" ...
##  $ deuda16   : num  35681 46806 71184 99476 33447 ...
##  $ deuda17   : num  69067 88022 139013 189646 61902 ...
##  $ Estado    : chr  "Inactivo" "Inactivo" "Inactivo" "Inactivo" ...
  1. Eliminar las columnas repetidas
#Solución
# En este caso no quedan columnas repetidas
  1. Filtrar solamente las deudas del 2017 superiores a un millón y de dificil cobro.
#Solución
d17_DC <- filter(morosidad, deuda17>1000000 & situacion=="DIFICIL COBRO")
  1. Filtrar las deudas que crecieron entre 2016 y 2017
#Solución
crecieron <- filter(morosidad,deuda16 > deuda17 )
  1. Filtrar los datos de forma que únicamente queden los casos de las empresas o personas que han estado morosas por los dos años.
#Solución
moros2 <- filter(morosidad, deuda16 > 0 & deuda17 > 0)
  1. utilizar el operador pipe para generar el siguiente data frame: No debe contener variables repetidas, solo debe contener personas o empresas morososas por los dos años, debe contener una columna con la diferencia de la deuda entre el 2016 y 2017 y otra variable que indique si la deuda disminuyó o aumentó.
#Solución
filtro <- morosidad %>%
  filter(deuda16>0 & deuda17>0) %>%
  mutate(diferencia=deuda16-deuda17) %>%
  mutate(cambio =ifelse(diferencia>0,"Disminuyó",
                        ifelse(diferencia<0,"Aumentó","Mantuvo")))