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
<-c(1) x
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:
<-c(1,2,3)
x 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:
<-c("Carlos","Maria","Daniel","Jorge","Luisa")
nombres nombres
## [1] "Carlos" "Maria" "Daniel" "Jorge" "Luisa"
class(nombres)
## [1] "character"
Veamos que sucede si en un mismo vector colocamos diferentes tipos de datos
<-c(45,"Carlos",TRUE)
mezcla 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:
<-c(1:10)
secuencia 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
<-seq(from=1,to=10,by=2)
secuencia secuencia
## [1] 1 3 5 7 9
Los nombres de los parámetros pueden omitirse y obtenemos el mismo resultado
<-seq(1,10,2)
secuencia 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
<-seq(from=1,to=10,length = 5)
secuencia1 secuencia1
## [1] 1.00 3.25 5.50 7.75 10.00
<-seq(from=1,to=10,length = 20)
secuencia2 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:
<-c("Carlos","Maria","Daniel","Jorge","Luisa")
nombres nombres
## [1] "Carlos" "Maria" "Daniel" "Jorge" "Luisa"
4] nombres[
## [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:
2:4] nombres[
## [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í.
c(1,3,5)] nombres[
## [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.
-c(1,3)] nombres[
## [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[-c(1,3)]
nombres 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:
<-c(nombres,"Alejandra","Manuel")
nombres 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.
<-c(1,6,9,3)
x<-c(5,2,4,7)
y+y x
## [1] 6 8 13 10
-y x
## [1] -4 4 5 -4
*y x
## [1] 5 12 36 21
/y x
## [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
<-c(2,7,5)
x+10 x
## [1] 12 17 15
/5 x
## [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 vectorprod
hace el producto de los elementos del vectrolength
devuelve el número de elementos que tiene el vectormean
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
<-matrix(c(1,2,3,4,5,6)) matriz
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
<-matrix(c(1,2,3,4,5,6),nrow = 2,ncol = 3)
matriz 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
<-matrix(c(1,2,3,4,5,6),nrow = 2,ncol = 3,byrow = T)
matriz 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í:
<-matrix(c(1,2,3,4,5,6),nrow = 2,ncol = 3,byrow = T)
matriz matriz
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
2,3] matriz[
## [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
2] # segunda columna matriz[,
## [1] 2 5
2,] # segunda fila matriz[
## [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:
<-matrix(c(1:4),ncol = 2,nrow = 2)
A<-matrix(c(5:8),ncol = 2,nrow = 2)
B A
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
B
## [,1] [,2]
## [1,] 5 7
## [2,] 6 8
+B A
## [,1] [,2]
## [1,] 6 10
## [2,] 8 12
-B A
## [,1] [,2]
## [1,] -4 -4
## [2,] -4 -4
*B A
## [,1] [,2]
## [1,] 5 21
## [2,] 12 32
/B A
## [,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
+10 A
## [,1] [,2]
## [1,] 11 13
## [2,] 12 14
^2 A
## [,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 matricesDet
Determinante de una matriztr
Traza de una matrizinv
Inversa de una matriz
Y muchas más, veamos los ejemplos:
%*%B A
## [,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.
<-c(45)
x<-c("Carlos","Maria","Daniel","Jorge","Luisa")
nombres<-matrix(c(1:4),ncol = 2,nrow = 2)
A<-list(x,nombres,A)
lista 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:
2]] lista[[
## [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:
<-c("Carlos","Maria","Daniel","Jorge","Luisa")
nombres<-c(12,34,21,24,44)
edades<-c("M","F","M","M","F") genero
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.
<-data.frame(nombres,edades,genero)
datos 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.
<-factor(c(1,2,3,1,1),levels = c(1,2,3),labels = c("Soltero","Casado","Divorciado") ) estCivil
Ahora podemos crear nuestro data frame agregando este nuevo factor
<-data.frame(nombres,edades,genero,estCivil)
datos 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í:
<-c("3","6","45")
numeros numeros
## [1] "3" "6" "45"
class(numeros)
## [1] "character"
<-as.numeric(numeros)
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"
<-as.factor(genero)
generostr(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
<-data.frame(nombres,edades,genero,estCivil)
datos 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
<- read.csv(file = 'nombre_de_archivo.csv') # datos será un 'data frame'
datos <- read_csv(file = 'nombre_de_archivo.csv') # datos será un 'tibble' datos
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
<- read.csv(file = 'titanic.csv')
titanic_df <- read_csv(file = 'titanic.csv') titanic_tib
## 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í:
$age titanic_df
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.
ageattach(titanic_df)
agedetach(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:
<- read.csv(file = 'titanic.csv',na.strings = "") titanic_df
Si lo que queremos es eliminar los NA
de toda la data lo podemos hacer con la función na.omit()
<-na.omit(titanic_df) titanicnoNA
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.
<-titanic_df[titanic_df$age>50,]
m50_1
<-subset(titanic_df,titanic_df$age>50) m50_2
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.
<-titanic_df[titanic_df$age>50 & titanic_df$pclass==1,]
primera1_50
<-subset(titanic_df,titanic_df$age>50 & titanic_df$pclass==1) primera2_50
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 columnasfilter
: devuelve un conjunto de filas según una o varias condiciones lógicasarrange
: reordena filas de un data framerename
: renombra variables en una data framemutate
: añade nuevas variables/columnas o transforma variables existentessummarise/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)
<-arrange(titanic_tib, age) titanicEDAD
<-rename(titanic_tib, clase = pclass, sobreviviente = survived, nombre = name, sexo = sex, edad=age) titanic_tib
<-iris
Iris<-mutate(Iris,ratio=Sepal.Length/Petal.Length) Iris
<-titanic_tib %>%
dataNfilter(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:
- Cada observación en los conjuntos de datos debe tener un identificador
- 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)
<-c("vaca","perro","rana","lagarto","mosca","paloma")
animal1<-c("mamifero","mamifero","anfibio","reptil","insecto","ave")
clase1
<- data.frame(animal1,clase1)
animales1 animales1
## animal1 clase1
## 1 vaca mamifero
## 2 perro mamifero
## 3 rana anfibio
## 4 lagarto reptil
## 5 mosca insecto
## 6 paloma ave
<-c("atun", "cocodrilo", "gato","rana")
animal2<-c("pez", "reptil", "mamifero","anfibio")
clase2
<- data.frame(animal2,clase2 )
animales2 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
<-rename(animales1, animal = animal1, clase=clase1)
animales1 animales1
## animal clase
## 1 vaca mamifero
## 2 perro mamifero
## 3 rana anfibio
## 4 lagarto reptil
## 5 mosca insecto
## 6 paloma ave
<-rename(animales2, animal = animal2, clase=clase2)
animales2 animales2
## animal clase
## 1 atun pez
## 2 cocodrilo reptil
## 3 gato mamifero
## 4 rana anfibio
<- rbind(animales1,animales2)
animales3 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()
<-merge(animales1,animales2)
animales4# muestra solo las filas comunes animales4
## animal clase
## 1 rana anfibio
<-merge(animales1,animales2,all=T)
animales5 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
<-c("perro","tortuga","paloma","cocodrilo","vaca","lagarto","sardina")
animal<-c("pelo","caparazon","plumas","escamas","pelo","escamas","escamas")
superficie
<-data.frame(animal,superficie)
superficieAnimales
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
- Almacene el siguiente valor en una variable con nombre
y
\[ \frac{1+2\cdot 3^4}{\frac{5}{6}-7} \]
# Solución
<- (1 + 2*3^4 ) / (5/6 - 7 )
y y
## [1] -26.43243
- 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
<- 80
peso <- 1.78
altura
<-peso/altura^2
IMC IMC
## [1] 25.24934
- 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
<- c(80, 70, 75, 94, 67)
pesos <- c(1.68, 1.75, 1.85, 1.90, 1.68)
alturas <-pesos/alturas^2
IMC IMC
## [1] 28.34467 22.85714 21.91381 26.03878 23.73866
- (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
<- 90
Farenheit <- 5/9*(Farenheit - 32)
Celcius Celcius
## [1] 32.22222
- Considere el conjunto de datos 2, 5, 4, 10, 8
- Guarde esta data en un vector con nombre x
- Encuentre el cuadrado de cada número
- Restele 6 a cada número
- Restele 9 a cada numero y luego eleve al cuadrado la respuesta (en una sola linea de código)
#Solución
<- c(2, 5, 4, 10, 8)
x ^2 - 6 x
## [1] -2 19 10 94 58
-9)^2 (x
## [1] 49 16 25 1 1
- Almacene los siguientes conjuntos de datos en un vector, utilizando
:
oseq
- 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10
# Solución
<- 1/(2:10)
sa sa
## [1] 0.5000000 0.3333333 0.2500000 0.2000000 0.1666667 0.1428571 0.1250000
## [8] 0.1111111 0.1000000
- 1, 8, 27, 64, 125, 216
#Solución
<- (1:6)^3
sb sb
## [1] 1 8 27 64 125 216
- 0, 25, 50, 75, …, 1000 (de 0 a 1000 de 25 en 25)
# Solución
<- seq(0,1000,by=25)
sc 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
- “a”, “a”, “a”, “a”, “a”
# Solución
<- rep("a",4)
sd sd
## [1] "a" "a" "a" "a"
- “a”, “a”, “b”, “b”, “b”, “c”
# Solución
<- rep(c("a","b","c"),c(2,3,1))
se se
## [1] "a" "a" "b" "b" "b" "c"
- Calcule la varianza muestral y la desviación estándar muestral, sin usar las funciones
var
ysd
de R para el conjunto de datostrees$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
<-trees$Height # lee la data trees$Height de R
arboles 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
<- length(arboles) # calcula la longitud del vector arboles
n n
## [1] 31
<- sum(arboles)/n
xbar xbar
## [1] 76
<- (1/(n-1))*sum( (arboles-xbar)^2 )
s2 s2
## [1] 40.6
<- sqrt(s2)
s s
## [1] 6.371813
- (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
<- rivers
rios <- length(rios)
n <- sum(rios)/n
xbar
# media muestral
xbar
## [1] 591.1844
<- abs(rios - xbar) #diferencia de los valores respecto a la media en valor absoluto
dif <- sum(dif)/n
dprom
# distancia promedio
dprom
## [1] 313.5508
- 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)
- Lea los datos de
titanic.csv
y códifique cada variable en el tipo adecuado.
- Lea los datos de
#Solución
<- read.csv("titanic.csv")
titanic 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" ...
<- as.factor(titanic$pclass)
pclass_factor 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 <- as.factor(titanic$pclass)
titanicstr(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" ...
$age <- as.numeric(titanic$age) titanic
## 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" ...
- 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
<- subset(titanic,titanic$age >= 25 & titanic$embarked=="S")
southhampton25 <-arrange(southhampton25, pclass) southhampton25
- 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
<-subset(titanic, titanic$pclass==1)
Primera_clase<-subset(titanic, titanic$pclass==2)
Segunda_clase<-subset(titanic, titanic$pclass==3) Tercera_clase
- 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 columnaticket
.
<-titanic %>%
dataFiltradafilter(embarked=="Q") %>%
mutate(m60=ifelse( age > 60, 1 ,0 ) )%>%
select(-ticket)
- Vamos a trabajar con la base de datos
Iris
. Por defecto, la base de datos Iris viene con la instalación de R.
- 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)
- Seleccionar las filas que pertenezcan a la especie
versicolor
.¿Cuantos individuos fueron seleccionados?.
#Solución
<- subset(iris, iris$Species=="versicolor") Ver
- Seleccionar solo la columna
Petal.Length
. ¿Cual es la media de la longitud de los petalos?.
#Solución
<- select(iris, Petal.Length)
long_petalos mean(long_petalos$Petal.Length)
## [1] 3.758
- 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 %>%
irisfilter(Species=="setosa")%>%
mutate(area=Petal.Length*Petal.Width*pi)
mean(iris$area)
## [1] 1.148566
- Calcular la frecuencia de individuos de la especie virginica que poseen un
Sepal.Width
mayor a 3.
#Solución
<- ifelse(iris$Sepal.Width > 3 ,1,0)
sepalom3 sum(sepalom3)
## [1] 42
- Calcular la frecuencia de individuos de la especie setosa que poseen un
Sepal.Length
mayor a 5 y unPetal.Width
menor a 0.3.
#Solución
.3 <- ifelse(iris$Sepal.Length > 5 & iris$Petal.Width < 0.3, 1,0)
sepalom5_petalom0sum(sepalom5_petalom0.3)
## [1] 12
- 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))
- (Entrega) Vamos a considerar los archivos
morosidad16.xlsx
ymorosidad17.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
ydeuda17
: 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.
<- read_excel("morosidad16.xlsx")
morosidad16 <- read_excel("morosidad17.xlsx") morosidad17
- 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
<- merge(morosidad16, morosidad17) morosidad
- 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" ...
- Eliminar las columnas repetidas
#Solución
# En este caso no quedan columnas repetidas
- Filtrar solamente las deudas del 2017 superiores a un millón y de dificil cobro.
#Solución
<- filter(morosidad, deuda17>1000000 & situacion=="DIFICIL COBRO") d17_DC
- Filtrar las deudas que crecieron entre 2016 y 2017
#Solución
<- filter(morosidad,deuda16 > deuda17 ) crecieron
- 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
<- filter(morosidad, deuda16 > 0 & deuda17 > 0) moros2
- 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
<- morosidad %>%
filtro filter(deuda16>0 & deuda17>0) %>%
mutate(diferencia=deuda16-deuda17) %>%
mutate(cambio =ifelse(diferencia>0,"Disminuyó",
ifelse(diferencia<0,"Aumentó","Mantuvo")))