Está en la página 1de 236

Minería de Datos con R

Dr. Jorge Párraga-Álava
Práctica 1 - Parte A

Actualizado al 2021-10-22
Agenda
1. Preliminares

2. Instalación R/RStudio

3. Instalación RTools

4. Empezar a trabajar con R

5. Variables y operadores

6. Estructuras y tipos de datos

7. Estructuras de control y funciones

2 / 69
Práctica 1 - Parte A
Preliminares

3 / 69
Algo de historia
R fue creado en 1993 como un entorno para el análisis estadístico y gráfico por
Roberth Gentleman y Ross Ihaka, de la Universidad de Auckland en Nueva
Zelanda.

A partir de 1997 su desarrollo (R-base) es llevado por un grupo de programadores


conocido como "The R-core team".

4 / 69
Algo de historia
En la actualidad, los usuarios pueden publicar paquetes que extienden la
funcionalidad básica de R en distintas áreas.

Existe un repositorio oficial de paquetes llamado: Comprehensive R Archive


Network (CRAN).

5 / 69
¿Por qué usar R?
R es software libre 😁 al distribuirse bajo licencia GNU GPL.
R es multiplataforma 💻, disponible para Windows, MAC y GNU/Linux.

La sintaxis es simple e intuitiva 🤩 y con buena variedad de funciones gráficas 📊.

R es extensible 📝 mediante funciones y paquetes 📦 que son publicados por los


usuarios.

La comunidad de R es muy prolífica 💬 y colaborativa 🤝: R-bloggers, etc.

Cada vez más usado 📈, no sólo en la academia , sino también en el mundo


empresarial por gigantes como Google, Facebook, Microsoft, IBM, etc.

Es el mejor programa para hacer análisis de datos 💪.


6 / 69
Práctica 1 - Parte A
Instalación de R

7 / 69
Instalación de R
Windows

Ingrese aquí y seleccione el vínculo Haga clic en el vínculo "base".


"Download R for Windows" (84MB de Seleccione la opcion "R 4.0.3 for
tamaño). Windows", descargue el instalador.

8 / 69
Instalación de R
Windows

Paso 1. Paso 2.

9 / 69
Instalación de R
Windows

Paso 3. Paso 4.

10 / 69
Instalación de R
Windows

Paso 5. Paso 6.

11 / 69
Instalación de R
Windows

Paso 7. Esperamos que se realice la


instalación

12 / 69
Instalación de R
Windows

Paso 9. Abra R y observará la siguiente


interfaz.

13 / 69
Instalación de R
Ubuntu
Para instalar la última versión de R en Ubuntu utilice los siguientes comandos:

sudo add-apt-repository "deb http://cran.rstudio.com/bin/linux/ubuntu $(lsb_release -cs)/"


sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9
sudo apt-get update
sudo apt-get install r-base r-base-dev

Luego de ello, podrá ejecutar R desde la terminal, escribiendo el comando R:

14 / 69
Práctica 1 - Parte A
Instalación de RStudio

15 / 69
Instalación de RStudio
Windows

La interfaz de usuario de R no es
muy amigable ni versátil.

Por ello, interactuaremos con R a


través de RStudio.

RStudio es una interfaz que facilita


muchas de las tareas de
programación y análisis de datos en
R.

El actual científico-jefe de RStudio es Hadley Wickham

Hadley Wickham quien es el creador


de un nuevo estilo de programar y
analizar datos en R conocido como
tidyverse. 16 / 69
Instalación de RStudio
Windows

Vaya a la página de descarga de Baje y seleccione la versión de


RStudio. RStudio Desktop según su sistema
operativo.

Ejecute el instalador recién


descargado.
17 / 69
Instalación de RStudio
Windows

Paso 1 Paso 2

18 / 69
Instalación de RStudio
Windows

Paso 3 Esperemos que se complete la


instalación.

19 / 69
Instalación de RStudio
Windows

Paso 4

20 / 69
Instalación de RStudio
Windows
Si abrimos RStudio vamos a ver algo parecido a lo que se muestra en la imagen:

21 / 69
Práctica 1 - Parte A
Instalación de Rtools

22 / 69
Instalación de Rtools
Windows
En algunos casos para usar paquetes en R (4.0.0 o superior) será necesario instalar
Rtools, el que trae programas para compilar como el GCC COMPILER.

1 Haga clic aquí y descargue Rtool. 2 Ejecute el asistente de instalación.

23 / 69
Instalación de Rtools
Windows

3 Clic en Next 4 Clic en Install.

24 / 69
Instalación de Rtools
Windows

5 Esperamos que finalice la instalación. 6 Clic en Finish

25 / 69
Instalación de Rtools
Windows
7 Abrimos RStudio y, en la consola ejecutar:

writeLines('PATH="${RTOOLS40_HOME}\\usr\\bin;${PATH}"', con = "~/.Renviron")

8 Finalmente, reiniciar RStudio, y en la consola escribir:

Sys.which("make")

Deberá obtener el siguiente mensaje:

## make 26 / 69
Instalación de herramientas previas
Ubuntu
En Linux, no es necesario instalar Rtools, pero si algunos paquetes de desarrollo en
GNOME XML library:

sudo apt install libcurl4-openssl-dev libssl-dev libxml2-dev

También, cuando no ha instalado R previamente, se podría requerir:

sudo apt install r-base


sudo apt install r-base-dev

27 / 69
Práctica 1 - Parte A
Empezar a trabajar con R

28 / 69
Empezar a trabajar con R
Creación de Proyectos
Los proyectos en RStudio son una forma de organizar nuestroas archivos.

Para crear un proyecto en RStudio, se debe hacer clic en el menú "File" -> "New
Project" -> "New Directory" -> "New Project".

Ingrese el nombre del directorio para guardar su proyecto, por ejemplo: "Curso-
MD", y clic en "Create Project"

29 / 69
Empezar a trabajar con R
Creación de Proyectos
Una vez creado el proyecto, genere la siguiente estructura de directorios,
dirigiéndose al panel Miscellaneus (ventana inferior derecha de RStudio), en la
pestaña "Files" y luego clic en "New Folder".

Todas las operaciones por código que se realicen deben ser guardadas dentro de
la carpeta Scripts. Estos archivos deben tener la extensión .R

30 / 69
Empezar a trabajar con R
Creación de Proyectos

31 / 69
Empezar a trabajar con R
Paquetes en R
Un paquete (package en inglés) es simplemente un conjunto de funciones, datos y
documentación disponible para usar en R.

Cuando abrimos RStudio, se cargan automáticamente paquetes: son los paquetes


de R-base. Puedes ver sus nombres tecleando en la consola loadedNamespaces().

R, en su repositorio oficial llamado CRAN, dispone de +10.000 paquetes.

32 / 69
Empezar a trabajar con R
Paquetes desde repositorio CRAN
Para instalar un paquete desde la consola use install.packages("nombre_paquete").

Para instalar en modo gráfico diríjase al panel de miscellaneous, en la pestaña


Packages, luego en Install, escriba el nombre del paquete y, luego clic en Install.

Para cargar un paquete previamente instalado use library("nombre_paquete").

33 / 69
Empezar a trabajar con R
Paquetes desde repositorio CRAN
Ejemplo:

Instalemos el paquete igraph que se utiliza para manipular/gestionar grafos:

install.packages("igraph")

Una vez instalado, cargue el paquete con la instrucción:

library("igraph")

Para no instalar paquetes previamente instalados use:

if(!require(igraph)) {install.packages("igraph")}

34 / 69
Empezar a trabajar con R
Ayuda
Hay varias formas de pedir la ayuda de R.

Para ayuda de paquetes use help(sum) o ?sum. Esto muestra la documentación de


ayuda de la función sum.

Para ayuda de funciones use library(help="stats"). Esto muestra la documentación


de ayuda del paquete stats.

Para ver las vignettes de un paquete, use vignette("dplyr"). Esto muestra las viñetas
del paquete dplyr.

35 / 69
Práctica 1 - Parte A
Estructuras y tipos de datos

36 / 69
Variables y tipos de datos
El símbolo <- es el operador para asignar valores a las variables. También se
puede utilizar =.

variable1 <- 5000


variable1
variable2 <- "FCI"
variable2

## [1] 5000

## [1] "FCI"

El símbolo # se utiliza para introducir un comentario. Todo lo que quede a la


derecha de # no se ejecutará.

# esto es un comentario
variable3 <- TRUE
variable3

## [1] TRUE

37 / 69
Variables y tipos de datos
Tipos de variables y su correspondencia en R.

38 / 69
Variables y tipos de datos
Las variables en R pueden almacenar los siguientes tipos de datos.

variable1 12.34 #numérico


<-
variable2 "UTM" #caracter
<-
variable3 FALSE #lógico
<-
variable4 4L #entero, agrega L al valor numérico
<-
variable5 <-
factor(c("hombre", "mujer", "mujer", "mujer", "hombre", "mujer"),
levels = c("hombre", "mujer"))
#factor sin orden
variable6 <- factor(c("alto", "bajo", "bajo", "medio", "alto"),
levels = c("bajo", "medio", "alto"),
ordered = TRUE)
#factor con orden

Para conocer el tipo de variable, se utiliza la función class.

class(variable4)

## [1] "integer"

39 / 69
Variables y tipos de datos
Para probar si el objeto es de un tipo de dato particular:

is.numeric(variable1)
is.integer(variable1)
is.character(variable1)
is.factor(variable1)
is.logical(variable3)

## [1] TRUE

## [1] FALSE

## [1] FALSE

## [1] FALSE

## [1] TRUE

40 / 69
Variables y tipos de datos
Para visualizar objetos en R, usamos cat() o print().

cat(variable2)
print(variable6)

## UTM

## [1] alto bajo bajo medio alto


## Levels: bajo < medio < alto

41 / 69
Operadores
Aritméticos
Show 10 entries Search:
Operador Operación Ejemplo Resultado

1 + Suma 5+3 8

2 - Resta 5-3 2

3 * Multiplicación 5*3 18

4 / División 5/3 166667

5 ^ Potencia 5^3 125

6 %% División entera 5 %% 3 2

Showing 1 to 6 of 6 entries Previous 1 Next

42 / 69
Operadores
Relacionales
Show 10 entries Search:
Operador Comparación Ejemplo Resultado

1 < Menor que 5<3 false

2 <= Menor o igual que 5 <= 3 false

3 > Mayor que 5>3 true

4 >= Mayor o igual que 5 >= 3 true

5 == Exactamente igual que 5 == 3 false

6 != No es igual que 5 != 3 true

Showing 1 to 6 of 6 entries Previous 1 Next

43 / 69
Operadores
Lógicos
Show 10 entries Search:
Operador Comparación Ejemplo Resultado

1 x|y x Ó y es verdadero TRUE | FALSE true

2 x&y x Y y son verdaderos TRUE & FALSE false

3 !x x no es verdadero (negación) !TRUE false

4 isTRUE(x) x es verdadero (afirmación) isTRUE(TRUE) true

Showing 1 to 4 of 4 entries Previous 1 Next

44 / 69
Estructuras de datos
Hay muchas estructuras de objetos R. Los de uso frecuente son:

Tomado de: https://medium.com/@tiwarigaurav2512/r-data-types-847fffb01d5b

En R todas las estructuras son tratadas como objetos.

45 / 69
Estructuras de datos
Vector
Para crear vectores se usa la función c(). Un vector solo puede contener objetos
de la misma clase (caracter, entero, etc.)

vector1 <- c(19.87, 28)


vector2 <- c("U", "T", "M")
vector3 <- c(TRUE, FALSE, FALSE)
vector4 <- c(14L, 3L, 2008L)

Para acceder a elementos del vector, usamos []. Si se intenta acceder a posiciones
no válidas, R devuelve NA (not available).

vector1[1] #accedemos al primer elemento.


vector1[5]

## [1] 19.87

## [1] NA

46 / 69
Estructuras de datos
Vector
La mayoría de las operaciones aritméticas son de carácter vectorial. Esto significa
que R realiza las operaciones solicitadas elemento por elemento.

A <- c(1,2,4,6)
B <- c(2,4,6,8)
Z <- A + B
Z

## [1] 3 6 10 14

47 / 69
Estructuras de datos
Vector
Cuando los vectores no tienen la misma longitud, R da una advertencia.

A <- c(1,2,4,6)
B <- c(2,4,6)
Z <- A + B

## Warning in A + B: longitud de objeto mayor no es múltiplo de la longitud de uno


## menor

## [1] 3 6 10 8

48 / 69
Estructuras de datos
Matriz
En R, una matriz puede considerarse como una unión de vectores.

La función cbind() une columnas (vectores) en una matriz. Mientras que rbind() une
filas (vectores).

Ahora crearemos una matriz con pesos y altura de personas, a partir de dos
vectores:

peso <- c(68, 70, 80, 76)


altura <- c(165, 169, 175, 170)
matriz <- cbind(peso, altura)
matriz

## peso altura
## [1,] 68 165
## [2,] 70 169
## [3,] 80 175
## [4,] 76 170

49 / 69
Estructuras de datos
Matriz
También es posible crear matriz con la función matrix().

matriz <- matrix(nrow=2, ncol=3) #crea matriz vacía


matriz

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


## [1,] NA NA NA
## [2,] NA NA NA

Las matrices se construyen en forma de columnas, por lo que las entradas


comienzan en la "esquina superior izquierda y van hacia abajo".

matriz <- matrix(data=1:12, nrow=4, ncol=3) #crea matriz con secuencia de enteros del 1 al 12
matriz

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


## [1,] 1 5 9
## [2,] 2 6 10
## [3,] 3 7 11
## [4,] 4 8 12
50 / 69
Estructuras de datos
Matriz
Para acceder a elementos de la matriz, usamos [ , ] e indicamos la fila y columna
a la que se quiere acceder.

matriz[1, 2] #accedemos a fila 1 columna 2

## [1] 5

Si se quiere acceder a todas las columnas, basta con dejar el espacio vacío:

matriz[1, ] #accedemos a fila 1 y todas las columnas

## [1] 1 5 9

También se puede especificar un rango de filas o columnas para acceder:

matriz[2, 1:3] #accedemos a fila 2 y las tres primeras columnas

## [1] 2 6 10
51 / 69
Estructuras de datos
Data frame
Son objetos similares a las matrices pero se diferencian en permitir el
almacenamiento de datos heterogéneos.

Para crear un data frame se utiliza la función data.frame().

datos <- data.frame(genero = c("M", "F", "F","M"),


peso = c(58.7, 69.8, 80.1, 76.2),
altura = c(174, 178, 169, 180),
soltero =c(TRUE, TRUE, FALSE, TRUE))
datos

## genero peso altura soltero


## 1 M 58.7 174 TRUE
## 2 F 69.8 178 TRUE
## 3 F 80.1 169 FALSE
## 4 M 76.2 180 TRUE

52 / 69
Estructuras de datos
Data frame
Para acceder a elementos del data frame se utiliza, al igual que en matrices, [ , ].
Sin embargo, también es posible acceder a grupos de elementos por nombre de
columnas.

datos[ , "soltero"] #Se muestran todas las filas pero únicamente la columna soltero

## [1] TRUE TRUE FALSE TRUE

Para conocer el número de filas y columnas se usan las funciones siguientes:

nrow(datos) #número de filas

## [1] 4

ncol(datos) #número de columnas

## [1] 4

53 / 69
Estructuras de datos
Data frame
Para conocer los nombres de columnas y filas se usan las funciones siguientes:

rownames(datos) #etiquetas de filas

## [1] "1" "2" "3" "4"

colnames(datos) #etiquetas de columnas

## [1] "genero" "peso" "altura" "soltero"

54 / 69
Estructuras de datos
Data frame
Si se requiere cambiar el nombre de columnas, basta con asignar un nuevo vector
con tal información:

colnames(datos) <- c("sexo", "peso.en.kg", "estatura.en.cm", "civil")


datos

## sexo peso.en.kg estatura.en.cm civil


## 1 M 58.7 174 TRUE
## 2 F 69.8 178 TRUE
## 3 F 80.1 169 FALSE
## 4 M 76.2 180 TRUE

Para acceder a columnas del data frame se usa el símbolo $.

datos$civil

## [1] TRUE TRUE FALSE TRUE

55 / 69
Estructuras de datos
Data frame
Cuando la cantidad de registros en el data frame es extenso, es posible visualizar
únicamente las primeras o últimas filas del mismo, usando las funciones head() y
tail(), respectivamente.

head(datos, 2) #muestra las dos primeras filas.

## sexo peso.en.kg estatura.en.cm civil


## 1 M 58.7 174 TRUE
## 2 F 69.8 178 TRUE

tail(datos, 2) #muestra las dos últimas filas.

## sexo peso.en.kg estatura.en.cm civil


## 3 F 80.1 169 FALSE
## 4 M 76.2 180 TRUE

56 / 69
Estructuras de datos
Listas
Las listas se pueden crear explícitamente usando la función list(), que toma un
número arbitrario de argumentos.

lista <- list(c(2020, 2021), "Curso", TRUE, c(4L, 5L, 10L))


lista

## [[1]]
## [1] 2020 2021
##
## [[2]]
## [1] "Curso"
##
## [[3]]
## [1] TRUE
##
## [[4]]
## [1] 4 5 10

57 / 69
Estructuras de datos
Listas
Pare acceder a componentes de listas se usa doble corchete [ [ ] ].

lista[[2]] #accede al segundo componente

## [1] "Curso"

lista[[4]][3] #accede al tercer elemento del cuarto componente

## [1] 10

58 / 69
Estructuras de datos
Listas
También es posible asignar etiquetas a cada componente de la lista.

lista <- list(nombre="George", especie="Chelonoidis abingdonii",


antiguedad="110 anos", nacimientos=c(31, 36, 35, 20, 40))
lista

## $nombre
## [1] "George"
##
## $especie
## [1] "Chelonoidis abingdonii"
##
## $antiguedad
## [1] "110 anos"
##
## $nacimientos
## [1] 31 36 35 20 40

59 / 69
Estructuras de datos
Listas
Para conocer todas las etiquetas de los componentes de la lista se usa la función
attributes().

attributes(lista)

## $names
## [1] "nombre" "especie" "antiguedad" "nacimientos"

Para acceder a ellos, usamos el símbolo .

lista$especie

## [1] "Chelonoidis abingdonii"

60 / 69
Práctica 1 - Parte A
Estructuras de control y funciones

61 / 69
Estructuras de control y funciones

If Switch
# genera un número aleatorio entre 1 y 9 operacion <- "raiz"
prueba <- sample(1:9,1) numero <- 98
if(prueba >= 5){ switch(operacion,
print("El paciente presenta fiebre") raiz = sqrt(numero),
}else{ absoluto = abs(numero),
print("El paciente NO presenta fiebre") numero^2) #operación predeterminada
}
## [1] 9.899495
## [1] "El paciente presenta fiebre"

62 / 69
Estructuras de control y funciones

For While
for(i in 1:10) { i=1
print(i) while(i<=10){
} print(i)
i <- i+1
}
## [1] 1
## [1] 2
## [1] 3 ## [1] 1
## [1] 4 ## [1] 2
## [1] 5 ## [1] 3
## [1] 6 ## [1] 4
## [1] 7 ## [1] 5
## [1] 8 ## [1] 6
## [1] 9 ## [1] 7
## [1] 10 ## [1] 8
## [1] 9
## [1] 10

63 / 69
Estructuras de control y funciones
Funciones
Una función en R se define de la siguiente manera:

nombre <- function(arg1,arg2,...){


operaciones
}

Definamos una función que realiza diversas operaciones sobre los dos
argumentos que recibe:

operaciones <- function(x,y) {


list(
multi=x*y,
suma=sum(x,y),
resta=x-y
)
}

Note que las operaciones se configuran como componentes de lista para tenerlas
disponibles en cualquier momento de la ejecución del código.
64 / 69
Estructuras de control y funciones
Funciones
Ahora llamemos a la función recién creada:

resultados <- operaciones(15, 10)

Accedemos a cada valor devuelto por la función

resultados$multi

## [1] 150

resultados$suma

## [1] 25

resultados$resta

## [1] 5

65 / 69
Práctica 1 - Parte A
Actividad asíncrona

66 / 69
Actividad asíncrona
Use el código R necesario para reproducir las siguientes objetos R:

Matriz con nombres de filas y columnas

Data frame con nombres de columnas. Las dos primeras de tipo caracter y la última, tipo lógico.

67 / 69
Gracias!
👍
[Práctica 1 - Parte A]

Minería de Datos con R

Dr. Jorge Párraga-Álava

Sígueme en Twitter

@jorgeklz

68 / 69
Referencias
Parraga-Alava, J. 2020. Curso de Minería de Datos. Universidad Técnica de Manabí

Montaño, N. 2019. Aprendiendo R para DataScience. Sociedad Ecuatoriana de


Estadística

Coll, V., Pérez, P. 2017. Curso de Introducción a R. Universidad de Valencia

Flor, J. 2017. Introducción a la Minería de Datos con R. IT-Latino.Net

Bock, T. 2020. How to instal R Packages from GitHub. DisplayR

Santana, J., Farfan, E. 2014. El arte de programar en R. Instituto Mexicano de


Tecnología del Agua.

Villalobos, M., Parraga-Alava, J. 2016. Laboratorio de Bioinformática. Universidad


de Santiago de Chile

69 / 69
Minería de Datos con R
Dr. Jorge Párraga-Álava
Práctica 1 - Parte B

Actualizado al 2021-10-26
Agenda
1. Importación/Exportación de datos

2. Estadística descriptiva

3. Resumen de datos

4. Visualización

2 / 92
Creación de proyecto en RStudio
Para el desarrollo de esta sesión, no olvide realizar lo siguiente:

1. Crear un proyecto en RStudio.

2. Dentro del proyecto crear las carpetas recomendadas (Scripts, Datos).

3. Crear un nuevo R Script con Ctrl + Shift + N o haga a hacer clic en el menú "File" ->
"New File" -> "R Script"".

4. Guardar el R Script recién creado dentro de la carpeta Scripts.

3 / 92
Paquetes requeridos
Antes de iniciar esta sesión virtual deberá instalar los siguientes paquetes:

if(!require(openxlsx)) {install.packages("openxlsx")}
if(!require(tidyverse)) {install.packages("tidyverse")}
if(!require(readr)) {install.packages("readr")}
if(!require(DescTools)) {install.packages("DescTools")}
if(!require(ggplot2)) {install.packages("ggplot2")}
if(!require(dplyr)) {install.packages("dplyr")}
if(!require(magrittr)) {install.packages("magrittr")}
if(!require(tibble)) {install.packages("tibble")}

Ahora cargue los paquetes:

library("openxlsx")
library("tidyverse")
library("readr")
library("DescTools")
library("ggplot2")
library("dplyr")
library("magrittr")
library("tibble")

4 / 92
Práctica 1 - Parte B
Importación/Exportación de datos

5 / 92
Importación de datos
Desde Excel
R dispone de varias paquetes para importación de datos, en formatos como:

.csv
.txt
.xlsx
entre otros.

6 / 92
Importación de datos
Desde Excel
Para importar datos creados en Excel (.xlsx) utilizamos el paquete openxlsx.

# Leer el archivo de excel y asignarlo al objeto datos_licor


datos_licor <- read.xlsx(xlsxFile = "Datos/datos_licor.xlsx")
# ver tipo de datos de cada variable
class(datos_licor)

Para tener una visión global del conjunto de datos, usamos la función glimpse.

# Vista general de los datos


glimpse(datos_licor)

7 / 92
Importación de datos
Desde Excel
El código anterior produce:

## [1] "data.frame"

## Rows: 100
## Columns: 9
## $ PRODUCTO <chr> "Cerveza Pilsener light", "Cerveza Pilsener", "Cerveza …
## $ LOCAL <chr> "Samborondón", "Samborondón", "Ceibos", "Ceibos", "Samb…
## $ COD_CLTE <chr> "10027", "10018", "10014", "10007", "10016", "10020", "…
## $ CLIENTE <chr> "Marilyn Marlene Arratia Rivas", "Xavier Rafael Lagos O…
## $ FECHA_FACTURA <dbl> 42745, 42738, 42739, 42776, 42738, 42750, 42771, 42771,…
## $ VENTA_UND <dbl> 1, 2, 1, 4, 6, 4, 4, 4, 6, 6, 1, 1, 1, 1, 6, 6, 2, 6, 6…
## $ VENTA_USD <dbl> 0.9, 1.6, 0.9, 3.2, 5.4, 3.2, 3.6, 4.0, 6.0, 4.8, 1.0, …
## $ VENTA_COSTO <dbl> 0.78, 1.40, 0.78, 2.80, 4.68, 2.80, 3.12, 3.40, 5.10, 4…
## $ CALIF_SERVICIO <chr> "Mala", "Mala", "Regular", "Muy Buena", "Muy Buena", "B…

Note que el conjunto de datos tiene 100 filas y 9 columnas. Las columnas son de
tipo double (dbl) y character (chr).

8 / 92
Importación de datos
Desde Excel
Para importar una hoja específica, puede hacer referencia por nombre de hoja:

# Leer el archivo de excel y asignarlo al objeto datos_licor


datos_licor_local <- read.xlsx(xlsxFile = "Datos/datos_licor.xlsx",
sheet = "Data_Locales" )
# Vista general de los datos
glimpse(datos_licor_local)

9 / 92
Importación de datos
Desde Excel
El código anterior produce:

## Rows: 4
## Columns: 4
## $ LOCAL <chr> "Samborondón", "Samborondón", "Ceibos", "Ceibos"
## $ ANIO <dbl> 2017, 2017, 2017, 2017
## $ MES <dbl> 1, 2, 1, 2
## $ PROMOTORIA <chr> "Si", "No", "No", "Si"

10 / 92
Importación de datos
Desde CSV
Para importar datos almacenados en archivos con valores separados por coma
(.csv) utilizamos la función read_csv del paquete tidyverse.

# Leer el archivo csv y asignarlo al objeto datos_banco


datos_banco <- read_csv(file = "Datos/datos_banco.csv")
# Visualiza data
glimpse(datos_banco)

11 / 92
Importación de datos
Desde CSV
El código anterior produce:

## Rows: 24,299
## Columns: 8
## $ Sucursal <chr> "Paseo Shopping Portoviejo", "Paseo Shopping Porto…
## $ Nuevo_Sistema <chr> "No", "No", "No", "No", "No", "No", "No", "No", "N…
## $ Cajero <dbl> 4820, 4820, 4820, 4820, 4820, 4820, 4820, 4820, 48…
## $ ID_Transaccion <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
## $ Transaccion <chr> "Cobro/Pago (Cta externa)", "Cobro/Pago (Cta exter…
## $ Tiempo_Servicio_seg <dbl> 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42…
## $ Satisfaccion <chr> "Muy Bueno", "Malo", "Regular", "Regular", "Muy Bu…
## $ Monto <dbl> 2889.30, 1670.69, 3172.49, 1764.92, 1835.69, 2165.…

12 / 92
Importación de datos
Desde CSV
También se puede indicar el tipo de dato de cada columna al leer el archivo:

datos_banco <- read_csv(file = "Datos/datos_banco.csv",


col_types = cols(
Sucursal = col_character(),
Nuevo_Sistema = col_character(),
Cajero = col_integer(),
ID_Transaccion = col_double(),
Transaccion = col_character(),
Tiempo_Servicio_seg = col_double(),
Satisfaccion = col_character(),
Monto = col_double()
))
# Visualiza data
glimpse(datos_banco)

13 / 92
Importación de datos
Desde CSV
El código anterior produce:

## Rows: 24,299
## Columns: 8
## $ Sucursal <chr> "Paseo Shopping Portoviejo", "Paseo Shopping Porto…
## $ Nuevo_Sistema <chr> "No", "No", "No", "No", "No", "No", "No", "No", "N…
## $ Cajero <int> 4820, 4820, 4820, 4820, 4820, 4820, 4820, 4820, 48…
## $ ID_Transaccion <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
## $ Transaccion <chr> "Cobro/Pago (Cta externa)", "Cobro/Pago (Cta exter…
## $ Tiempo_Servicio_seg <dbl> 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42…
## $ Satisfaccion <chr> "Muy Bueno", "Malo", "Regular", "Regular", "Muy Bu…
## $ Monto <dbl> 2889.30, 1670.69, 3172.49, 1764.92, 1835.69, 2165.…

14 / 92
Importación/Exportación de datos
Entender los datos
Luego de importar se debe entender los datos:

¿Qué representa cada columna?

¿Qué tipo de dato debería tener cada columna?

¿Qué granularidad o atomicidad tienen los datos?

Si es que se tiene varios conjuntos de datos ¿Cómo se relacionan los datos?

¿A qué periodo de tiempo corresponden los datos?

15 / 92
Importación/Exportación de datos
Entender los datos
Podríamos ver las primeras 8 filas

head(datos_licor, n = 8)

## PRODUCTO LOCAL COD_CLTE CLIENTE


## 1 Cerveza Pilsener light Samborondón 10027 Marilyn Marlene Arratia Rivas
## 2 Cerveza Pilsener Samborondón 10018 Xavier Rafael Lagos Oliva
## 3 Cerveza Pilsener light Ceibos 10014 Irma del Carmen Gallardo Toledo
## 4 Cerveza Pilsener Ceibos 10007 Honorio David Muñoz Molina
## 5 Cerveza Pilsener light Samborondón 10016 José Aquiles Aguayo Chávez
## 6 Cerveza Pilsener Samborondón 10020 Santos Alejandro Altamirano Pinto
## 7 Cerveza Pilsener light Ceibos 10011 Francisco Segundo Ascencio Vera
## 8 Club verde Samborondón 10016 José Aquiles Aguayo Chávez
## FECHA_FACTURA VENTA_UND VENTA_USD VENTA_COSTO CALIF_SERVICIO
## 1 42745 1 0.9 0.78 Mala
## 2 42738 2 1.6 1.40 Mala
## 3 42739 1 0.9 0.78 Regular
## 4 42776 4 3.2 2.80 Muy Buena
## 5 42738 6 5.4 4.68 Muy Buena
## 6 42750 4 3.2 2.80 Buena
## 7 42771 4 3.6 3.12 Muy Buena
## 8 42771 4 4.0 3.40 Buena
16 / 92
Importación/Exportación de datos
Entender los datos
¿Qué representa cada columna?

Para hacernos una idea, listamos los nombres de variables.

names(datos_licor)

## [1] "PRODUCTO" "LOCAL" "COD_CLTE" "CLIENTE"


## [5] "FECHA_FACTURA" "VENTA_UND" "VENTA_USD" "VENTA_COSTO"
## [9] "CALIF_SERVICIO"

17 / 92
Importación/Exportación de datos
Entender los datos
¿Qué tipo de dato debería tener cada columna?.

glimpse(datos_licor)

## Rows: 100
## Columns: 9
## $ PRODUCTO <chr> "Cerveza Pilsener light", "Cerveza Pilsener", "Cerveza …
## $ LOCAL <chr> "Samborondón", "Samborondón", "Ceibos", "Ceibos", "Samb…
## $ COD_CLTE <chr> "10027", "10018", "10014", "10007", "10016", "10020", "…
## $ CLIENTE <chr> "Marilyn Marlene Arratia Rivas", "Xavier Rafael Lagos O…
## $ FECHA_FACTURA <dbl> 42745, 42738, 42739, 42776, 42738, 42750, 42771, 42771,…
## $ VENTA_UND <dbl> 1, 2, 1, 4, 6, 4, 4, 4, 6, 6, 1, 1, 1, 1, 6, 6, 2, 6, 6…
## $ VENTA_USD <dbl> 0.9, 1.6, 0.9, 3.2, 5.4, 3.2, 3.6, 4.0, 6.0, 4.8, 1.0, …
## $ VENTA_COSTO <dbl> 0.78, 1.40, 0.78, 2.80, 4.68, 2.80, 3.12, 3.40, 5.10, 4…
## $ CALIF_SERVICIO <chr> "Mala", "Mala", "Regular", "Muy Buena", "Muy Buena", "B…

18 / 92
Importación/Exportación de datos
Entender los datos
¿Qué tipo de dato debería tener cada columna?.

Para pasar de un tipo de dato a otro (siempre que sea posible), usamos R-base.

# De caracter a fecha
datos_licor$FECHA_FACTURA <- as.Date(datos_licor$FECHA_FACTURA, origin = "1899-12-30")
# De caracter a numérico
datos_licor$COD_CLTE <- as.numeric(datos_licor$COD_CLTE)

Para el caso de factores, usamos la función parse_factor() del paquete readr.

# De caracter a factor
datos_licor$CALIF_SERVICIO <- parse_factor(datos_licor$CALIF_SERVICIO,
levels = c("Muy Mala", "Mala",
"Regular",
"Buena", "Muy Buena"))
# Deben especificarse los niveles para evitar que se creen en orden alfabético.

19 / 92
Importación/Exportación de datos
Entender los datos
¿Qué tipo de dato debería tener cada columna?.

Finalmente, visualizamos los cambios hechos con el código anterior:

# Visualiza data
glimpse(datos_licor)

## Rows: 100
## Columns: 9
## $ PRODUCTO <chr> "Cerveza Pilsener light", "Cerveza Pilsener", "Cerveza …
## $ LOCAL <chr> "Samborondón", "Samborondón", "Ceibos", "Ceibos", "Samb…
## $ COD_CLTE <dbl> 10027, 10018, 10014, 10007, 10016, 10020, 10011, 10016,…
## $ CLIENTE <chr> "Marilyn Marlene Arratia Rivas", "Xavier Rafael Lagos O…
## $ FECHA_FACTURA <date> 2017-01-10, 2017-01-03, 2017-01-04, 2017-02-10, 2017-0…
## $ VENTA_UND <dbl> 1, 2, 1, 4, 6, 4, 4, 4, 6, 6, 1, 1, 1, 1, 6, 6, 2, 6, 6…
## $ VENTA_USD <dbl> 0.9, 1.6, 0.9, 3.2, 5.4, 3.2, 3.6, 4.0, 6.0, 4.8, 1.0, …
## $ VENTA_COSTO <dbl> 0.78, 1.40, 0.78, 2.80, 4.68, 2.80, 3.12, 3.40, 5.10, 4…
## $ CALIF_SERVICIO <fct> Mala, Mala, Regular, Muy Buena, Muy Buena, Buena, Muy B…

20 / 92
Importación/Exportación de datos
Entender los datos
Si es que se tiene varios conjuntos de datos ¿Cómo se relacionan los datos?.

# datos banco
head(datos_banco)
# datos licor
head(datos_licor)

21 / 92
Importación/Exportación de datos
Entender los datos
Si es que se tiene varios conjuntos de datos ¿Cómo se relacionan los datos?.

El código anterior produce:


## # A tibble: 4 × 8
## Sucursal Nuevo_Sistema Cajero ID_Transaccion Transaccion Tiempo_Servicio…
## <chr> <chr> <int> <dbl> <chr> <dbl>
## 1 Paseo Shop… No 4820 2 Cobro/Pago (… 41
## 2 Paseo Shop… No 4820 2 Cobro/Pago (… 41
## 3 Paseo Shop… No 4820 2 Cobro/Pago (… 41
## 4 Paseo Shop… No 4820 2 Cobro/Pago (… 41
## # … with 2 more variables: Satisfaccion <chr>, Monto <dbl>

## PRODUCTO LOCAL COD_CLTE CLIENTE


## 1 Cerveza Pilsener light Samborondón 10027 Marilyn Marlene Arratia Rivas
## 2 Cerveza Pilsener Samborondón 10018 Xavier Rafael Lagos Oliva
## 3 Cerveza Pilsener light Ceibos 10014 Irma del Carmen Gallardo Toledo
## 4 Cerveza Pilsener Ceibos 10007 Honorio David Muñoz Molina
## FECHA_FACTURA VENTA_UND VENTA_USD VENTA_COSTO CALIF_SERVICIO
## 1 2017-01-10 1 0.9 0.78 Mala
## 2 2017-01-03 2 1.6 1.40 Mala
## 3 2017-01-04 1 0.9 0.78 Regular
## 4 2017-02-10 4 3.2 2.80 Muy Buena
22 / 92
Importación/Exportación de datos
Entender los datos
¿A qué periodo de tiempo corresponden los datos?

# Fecha mínima
min(datos_licor$FECHA_FACTURA)
# Fecha mínima
max(datos_licor$FECHA_FACTURA)

El código anterior produce:

## [1] "2017-01-01"

## [1] "2017-02-11"

23 / 92
Práctica 1 - Parte B
Estadística descriptiva

24 / 92
Estadística descriptiva
Con tidyverse
R tiene sus comandos predeterminados para manipular datos y realizar
estadística, esto se conoce como R-base.

Sin embargo existen otros paquetes que simplifican esta tarea.

En este curso veremos cómo hacerlo con los paquetes magrittr, tibble y dplyr que
está dentro del conjunto de paquetes llamado tidyverse.

25 / 92
Estadística descriptiva
Con tidyverse
Operador Pipe %>%
El operador pipe %>% del paquete magrittr permite que el código sea más legible.

library(magrittr)
# con R-base
names(datos_licor)
# con pipe
datos_licor %>% names

26 / 92
Estadística descriptiva
Con tidyverse
Operador Pipe %>%
El código anterior produce:
## [1] "PRODUCTO" "LOCAL" "COD_CLTE" "CLIENTE"
## [5] "FECHA_FACTURA" "VENTA_UND" "VENTA_USD" "VENTA_COSTO"
## [9] "CALIF_SERVICIO"

## [1] "PRODUCTO" "LOCAL" "COD_CLTE" "CLIENTE"


## [5] "FECHA_FACTURA" "VENTA_UND" "VENTA_USD" "VENTA_COSTO"
## [9] "CALIF_SERVICIO"

27 / 92
Estadística descriptiva
Con tidyverse
Operador Pipe %>%
Otro ejemplo:

# con R-base
head(datos_licor, n= 2)
# con pipe
datos_licor %>% head(n=2)

28 / 92
Estadística descriptiva
Con tidyverse
Operador Pipe %>%
Otro ejemplo:
## PRODUCTO LOCAL COD_CLTE CLIENTE
## 1 Cerveza Pilsener light Samborondón 10027 Marilyn Marlene Arratia Rivas
## 2 Cerveza Pilsener Samborondón 10018 Xavier Rafael Lagos Oliva
## FECHA_FACTURA VENTA_UND VENTA_USD VENTA_COSTO CALIF_SERVICIO
## 1 2017-01-10 1 0.9 0.78 Mala
## 2 2017-01-03 2 1.6 1.40 Mala

## PRODUCTO LOCAL COD_CLTE CLIENTE


## 1 Cerveza Pilsener light Samborondón 10027 Marilyn Marlene Arratia Rivas
## 2 Cerveza Pilsener Samborondón 10018 Xavier Rafael Lagos Oliva
## FECHA_FACTURA VENTA_UND VENTA_USD VENTA_COSTO CALIF_SERVICIO
## 1 2017-01-10 1 0.9 0.78 Mala
## 2 2017-01-03 2 1.6 1.40 Mala

29 / 92
Estadística descriptiva
Con tidyverse
Estructura Tibble
Una data frame puede ser convertido en un objeto tibble usando la función as_tibble()
del paquete tibble, entre las mejoras que da es que no imprime todo el objeto en
pantalla, sino un resumen del mismo.

# Convertir el data frame datos_licor a un objeto tibble


datos_licor <- tibble::as_tibble(datos_licor)
# Muestra datos_licor
datos_licor

30 / 92
Estadística descriptiva
Con tidyverse
Estructura Tibble
El código anterior produce:
## # A tibble: 100 × 9
## PRODUCTO LOCAL COD_CLTE CLIENTE FECHA_FACTURA VENTA_UND VENTA_USD VENTA_COSTO
## <chr> <chr> <dbl> <chr> <date> <dbl> <dbl> <dbl>
## 1 Cerveza… Samb… 10027 "Maril… 2017-01-10 1 0.9 0.78
## 2 Cerveza… Samb… 10018 "Xavie… 2017-01-03 2 1.6 1.4
## 3 Cerveza… Ceib… 10014 "Irma … 2017-01-04 1 0.9 0.78
## 4 Cerveza… Ceib… 10007 "Honor… 2017-02-10 4 3.2 2.8
## 5 Cerveza… Samb… 10016 "José … 2017-01-03 6 5.4 4.68
## 6 Cerveza… Samb… 10020 "Santo… 2017-01-15 4 3.2 2.8
## 7 Cerveza… Ceib… 10011 "Franc… 2017-02-05 4 3.6 3.12
## 8 Club ve… Samb… 10016 "José … 2017-02-05 4 4 3.4
## 9 Club ve… Samb… 10022 "Edina… 2017-01-25 6 6 5.1
## 10 Cerveza… Samb… 10026 "Carlo… 2017-01-16 6 4.8 4.2
## # … with 90 more rows, and 1 more variable: CALIF_SERVICIO <fct>

31 / 92
Estadística descriptiva
Datos a usar
Se usará datos_banco, por ello se adecuarán las variables al tipo de datos que
corresponda. Usaremos la función mutate del paquete dplyr.

# Realiza cambios en tipos de datos de algunas variables


datos_banco <- datos_banco %>%
mutate(
Transaccion = str_trim(Transaccion), # quitar espacios
Nuevo_Sistema = parse_factor(Nuevo_Sistema), # como factor sin orden
# como factor con orden
Satisfaccion = parse_factor(Satisfaccion, levels = c("Muy Malo",
"Malo",
"Regular",
"Bueno",
"Muy Bueno")),
Sucursal = parse_factor(Sucursal) # como factor sin orden
)
# Visualiza los cambios
glimpse(datos_banco)

32 / 92
Estadística descriptiva
Datos a usar
Se usará datos_banco, por ello se adecuarán las variables al tipo de datos que
corresponda. Usaremos la función mutate del paquete dplyr.
## Rows: 24,299
## Columns: 8
## $ Sucursal <chr> "Paseo Shopping Portoviejo", "Paseo Shopping Porto…
## $ Nuevo_Sistema <chr> "No", "No", "No", "No", "No", "No", "No", "No", "N…
## $ Cajero <int> 4820, 4820, 4820, 4820, 4820, 4820, 4820, 4820, 48…
## $ ID_Transaccion <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
## $ Transaccion <chr> "Cobro/Pago (Cta externa)", "Cobro/Pago (Cta exter…
## $ Tiempo_Servicio_seg <dbl> 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42…
## $ Satisfaccion <fct> Muy Bueno, Malo, Regular, Regular, Muy Bueno, Buen…
## $ Monto <dbl> 2889.30, 1670.69, 3172.49, 1764.92, 1835.69, 2165.…

33 / 92
Estadística descriptiva
Medidas de tendencia central
Media. Promedio de los valores.

Mediana. Punto medio de los valores una vez que se han ordenado de menor a
mayor o de mayor a menor.

Moda. Valor de la observación que aparece con mayor frecuencia.

34 / 92
Estadística descriptiva
Medidas de tendencia central
Calcularemos las medidas de tendencia central para datos_banco.

# %$% versión simplificada de %>%, que sólo selecciona una variable.

# Media
datos_banco %$% mean(Tiempo_Servicio_seg, na.rm = TRUE)
# Mediana
datos_banco %$% median(Tiempo_Servicio_seg, na.rm = TRUE)
# Moda
datos_banco %$% Mode(Tiempo_Servicio_seg, na.rm = TRUE)

35 / 92
Estadística descriptiva
Medidas de tendencia central
El código anterior produce:

## [1] 58.3282

## [1] 51

## [1] 43
## attr(,"freq")
## [1] 862

36 / 92
Estadística descriptiva
Medidas de posición
Cuartiles. Dividen al conjunto de observaciones en 4 partes iguales.

Deciles. Dividen al conjunto de observaciones en 10 partes iguales.

Percentiles. Dividen al conjunto de observaciones en 100 partes iguales.

37 / 92
Estadística descriptiva
Medidas de posición
Calcularemos las medidas de posición para datos_banco.

# %$% versión simplificada de %>%, que sólo selecciona una variable.

# Cuartiles
quantile(datos_banco$Tiempo_Servicio_seg , probs = c(0.25, 0.50, 0.75))
# Deciles
quantile(datos_banco$Tiempo_Servicio_seg , probs = seq(from = 0.1, to = 1, by = 0.1))
# Percentil 5% y 95%
quantile(datos_banco$Tiempo_Servicio_seg , probs = c(0.05, 0.95))

38 / 92
Estadística descriptiva
Medidas de posición
El código anterior produce:

## 25% 50% 75%


## 43 51 63

## 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
## 39 42 45 48 51 55 60 67 83 297

## 5% 95%
## 37 105

39 / 92
Estadística descriptiva
Medidas de dispersión
Varianza. Media aritmética de las desviaciones de la media elevadas al cuadrado.

Desviación Estándar. Raíz cuadrada de la varianza.

Rango. Diferencia entre maximo y minimo valor.

Mínimo y Máximo.

40 / 92
Estadística descriptiva
Medidas de dispersión
Calcularemos las medidas de dispersión para datos_banco.

# %$% versión simplificada de %>%, que sólo selecciona una variable.

# Varianza
var(datos_banco$Tiempo_Servicio_seg, na.rm = TRUE)
# Desviación
sd(datos_banco$Tiempo_Servicio_seg, na.rm = TRUE)
# Min Max
range(datos_banco$Tiempo_Servicio_seg, na.rm = TRUE)
# Rango
diff(range(datos_banco$Tiempo_Servicio_seg, na.rm = TRUE))

41 / 92
Estadística descriptiva
Medidas de dispersión
El código anterior produce:

## [1] 711.0764

## [1] 26.66602

## [1] 33 297

## [1] 264

42 / 92
Práctica 1 - Parte B
Resumen de datos

43 / 92
Resumen de datos
Todas las medidas descriptivas calculadas previamente podrían resumirse en una sóla
estructura usando la función summarise().

Medidas de tendencia central para variable tiempo de servicio:

datos_banco %>%
summarise(
MEDIA= mean(Tiempo_Servicio_seg, na.rm=TRUE),
MEDIANA = median(Tiempo_Servicio_seg, na.rm = TRUE),
MODA = Mode(Tiempo_Servicio_seg, na.rm = TRUE),
TOTAL_OBS = n()
)

44 / 92
Resumen de datos
Todas las medidas descriptivas calculadas previamente podrían resumirse en una sola
estructura usando la función summarise().

Medidas de tendencia central para variable tiempo de servicio:


## # A tibble: 1 × 4
## MEDIA MEDIANA MODA TOTAL_OBS
## <dbl> <dbl> <dbl> <int>
## 1 58.3 51 43 24299

45 / 92
Resumen de datos
También se puede indicar a cuáles variables aplicar el resumen. Para ello usamos la
función summarise_at().

Medidas de tendencia central para variable tiempo de servicio y monto:

datos_banco %>%
summarise_at(vars(Tiempo_Servicio_seg, Monto),
funs (
MEDIA= mean(., na.rm=TRUE),
MEDIANA = median(., na.rm = TRUE),
MODA = Mode(., na.rm = TRUE)
)
)

46 / 92
Resumen de datos
También se puede indicar a cuáles variables aplicar el resumen. Para ello usamos la
función summarise_at().

Medidas de tendencia central para variable tiempo de servicio y monto:


## # A tibble: 1 × 6
## Tiempo_Servicio_… Monto_MEDIA Tiempo_Servicio_… Monto_MEDIANA Tiempo_Servicio…
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 58.3 1996. 51 2087. 43
## # … with 1 more variable: Monto_MODA <dbl>

47 / 92
Resumen de datos
Datos agrupados
Podemos generar resúmenes para datos agrupados. En este caso, medidas de
tendencia central por tipo de transacción.

datos_banco %>%
group_by(Transaccion) %>%
summarise_at( vars(Tiempo_Servicio_seg),
funs (
MEDIA= mean(., na.rm=TRUE),
MEDIANA = median(., na.rm = TRUE),
MODA = Mode(., na.rm = TRUE),
TOTAL_OBS = n()
)
)

48 / 92
Resumen de datos
Datos agrupados
Podemos generar resúmenes para datos agrupados. En este caso, medidas de
tendencia central por tipo de transacción.
## # A tibble: 3 × 5
## Transaccion MEDIA MEDIANA MODA TOTAL_OBS
## <chr> <dbl> <dbl> <dbl> <int>
## 1 Cobrar cheque (Cta del Bco) 50.8 46 42 5407
## 2 Cobro/Pago (Cta externa) 48.8 44 36 3005
## 3 Deposito 62.7 54 46 15887

49 / 92
Resumen de datos
Datos agrupados
Los resúmenes se pueden realizar para datos agrupados por más de una variable.

# Medidas de tendencia central para el tiempo de servicio para cada transacción


# y nivel de satisfacción
datos_banco %>%
group_by(Transaccion, Satisfaccion) %>%
summarise_at(vars(Tiempo_Servicio_seg),
funs (
MEDIA= mean(., na.rm=TRUE),
MEDIANA = median(., na.rm = TRUE),
MODA = Mode(., na.rm = TRUE),
TOTAL_OBS = n()
)
)

50 / 92
Resumen de datos
Datos agrupados
Los resúmenes se pueden realizar para datos agrupados por más de una variable.

## # A tibble: 15 × 6
## # Groups: Transaccion [3]
## Transaccion Satisfaccion MEDIA MEDIANA MODA TOTAL_OBS
## <chr> <fct> <dbl> <dbl> <dbl> <int>
## 1 Cobrar cheque (Cta del Bco) Muy Malo 61.6 53 42 505
## 2 Cobrar cheque (Cta del Bco) Malo 56.8 51 45 840
## 3 Cobrar cheque (Cta del Bco) Regular 49.9 46.5 41 1046
## 4 Cobrar cheque (Cta del Bco) Bueno 48.4 45 38 1423
## 5 Cobrar cheque (Cta del Bco) Muy Bueno 46.8 43 41 1593
## 6 Cobro/Pago (Cta externa) Muy Malo 65.2 56 51 238
## 7 Cobro/Pago (Cta externa) Malo 58.6 53 45 403
## 8 Cobro/Pago (Cta externa) Regular 48.2 43 36 556
## 9 Cobro/Pago (Cta externa) Bueno 46.0 41 36 851
## 10 Cobro/Pago (Cta externa) Muy Bueno 43.4 40 35 957
## 11 Deposito Muy Malo 82.4 65 46 2266
## 12 Deposito Malo 67.7 59 48 3231
## 13 Deposito Regular 60.8 55 41 3037
## 14 Deposito Bueno 58.5 52 39 3641
## 15 Deposito Muy Bueno 52.1 48 43 3712

51 / 92
Resumen de datos
Datos agrupados
Finalmente, se pueden crear resúmenes para datos filtrados:

# Para la Sucursal Multiplaza, obtener medidas de tendencia central para


# el tiempo de servicio agrupado por transacción y nivel de satisfacción.
datos_banco %>%
filter(Sucursal== "Multiplaza") %>%
group_by(Transaccion, Satisfaccion) %>%
summarise_at( vars(Tiempo_Servicio_seg),
funs (
MEDIA= mean(., na.rm=TRUE),
MEDIANA = median(., na.rm = TRUE),
MODA = Mode(., na.rm = TRUE),
TOTAL_OBS = n()
)
)

52 / 92
Resumen de datos
Datos agrupados
Finalmente, se pueden crear resúmenes para datos filtrados:

## # A tibble: 27 × 6
## # Groups: Transaccion, Satisfaccion [15]
## Transaccion Satisfaccion MEDIA MEDIANA MODA TOTAL_OBS
## <chr> <fct> <dbl> <dbl> <dbl> <int>
## 1 Cobrar cheque (Cta del Bco) Muy Malo 67.1 60 46 144
## 2 Cobrar cheque (Cta del Bco) Malo 60.7 56 50 277
## 3 Cobrar cheque (Cta del Bco) Regular 57.6 54 50 226
## 4 Cobrar cheque (Cta del Bco) Bueno 57.5 54 50 249
## 5 Cobrar cheque (Cta del Bco) Bueno 57.5 54 51 249
## 6 Cobrar cheque (Cta del Bco) Muy Bueno 56.1 54 49 232
## 7 Cobro/Pago (Cta externa) Muy Malo 69.5 61.5 51 70
## 8 Cobro/Pago (Cta externa) Muy Malo 69.5 61.5 61 70
## 9 Cobro/Pago (Cta externa) Malo 64.2 56.5 50 104
## 10 Cobro/Pago (Cta externa) Malo 64.2 56.5 52 104
## # … with 17 more rows

53 / 92
Práctica 1 - Parte B
Visualización

54 / 92
Gráficos con ggplot2
En esta sesión nos vamos a centrar en la generación de gráficos, para esto se va a usar
el paquete ggplot2. Este paquete presenta la información en modo de capas.

55 / 92
Gráficos con ggplot2
Las tres capas básicas son:

Datos (data)
Estéticas (aesthetics)
Geometría (geometries)

56 / 92
Gráficos con ggplot2
Para empezar un gráfico con ggplot2 se declara primero el objeto (data) a utilizar y las
estéticas (aes) que son requeridas por el gráfico.

# data: datos_banco,
# aes: Tiempo_Servicio_seg
ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg))

57 / 92
Gráficos con ggplot2
Para empezar un gráfico con ggplot2 se declara primero el objeto (data) a utilizar y las
estéticas (aes) que son requeridas por el gráfico.

58 / 92
Gráficos con ggplot2
Si al plot agregamos la capa geom, en modo de barras con la opción geom_histogram(),
obtenemos un histograma.

# data: datos_banco,
# aes: Tiempo_Servicio_seg,
# geom: barras
ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram()

59 / 92
Gráficos con ggplot2
Si al plot agregamos la capa geom, en modo de barras con la opción geom_histogram(),
obtenemos un histograma.

60 / 92
Gráficos con ggplot2
Se pueden agregar otras opciones, como `labs() para personalizar el gráfico.

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram() +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Densidad", x= "Tiempo")

61 / 92
Gráficos con ggplot2
Se pueden agregar otras opciones, como `labs() para personalizar el gráfico.

62 / 92
Gráficos con ggplot2
Podemos cambiar la amplitud del intervalo:

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram( binwidth = 50) +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Densidad", x= "Tiempo")

63 / 92
Gráficos con ggplot2
Podemos cambiar la amplitud del intervalo:

64 / 92
Gráficos con ggplot2
O si queremos especificar el número de intervalos:

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram( bins = 6) +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Densidad", x= "Tiempo")

65 / 92
Gráficos con ggplot2
O si queremos especificar el número de intervalos:

66 / 92
Gráficos con ggplot2
Ahora, podríamos responder la pregunta ¿El tiempo de servicio varía según la
sucursal?.

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg, fill= Sucursal)) +
geom_histogram(bins = 6, aes(y= ..count.., fill= Sucursal), position = "dodge")+
labs(title= 'Tiempo de Servicio (seg) para cada sucursal', y= "Cantidad", x= "Tiempo")

67 / 92
Gráficos con ggplot2
Ahora, podríamos responder la pregunta ¿El tiempo de servicio varía según la
sucursal?.

68 / 92
Gráficos con ggplot2
Ahora vamos a comparar los histogramas del tiempo de servicio según la transacción.

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram(bins = 6, aes(y= ..count.., fill= Transaccion), position = "dodge") +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Cantidad", x= "Tiempo")

69 / 92
Gráficos con ggplot2
Ahora vamos a comparar los histogramas del tiempo de servicio según la transacción.

70 / 92
Gráficos con ggplot2
También podemos agregar la capa facet_grid para formar una especie de matriz con
gráficos para cada valor de variable.

ggplot(data = datos_banco, aes(x = Tiempo_Servicio_seg)) +


geom_histogram(aes(y= ..count.., fill= Transaccion), position = "dodge") +
facet_grid(~Transaccion) +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Cantidad", x= "Tiempo")

71 / 92
Gráficos con ggplot2
También podemos agregar la capa facet_grid para formar una especie de matriz con
gráficos para cada valor de variable.

72 / 92
Gráficos con ggplot2
Si quisieramos el facet_grid de forma vertical:

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram(aes(y= ..count.., fill= Transaccion), position = "dodge") +
facet_grid(Transaccion~.) +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Cantidad", x= "Tiempo")

73 / 92
Gráficos con ggplot2
Si quisieramos el facet_grid de forma vertical:

74 / 92
Gráficos con ggplot2
Finalmente, usamos facet_wrap junto con fill y color para obtener:

ggplot(data = datos_banco,
aes(x = Tiempo_Servicio_seg)) +
geom_histogram(aes(y= ..count.., fill= Transaccion), position = "dodge") +
facet_wrap("Sucursal") +
labs(title= 'Histograma para Tiempo de Servicio (seg)', y= "Cantidad", x= "Tiempo")

75 / 92
Gráficos con ggplot2
Finalmente, usamos facet_wrap junto con fill y color para obtener:

76 / 92
Gráficos con ggplot2
Gráfico de barras
Para generar gráficos de barras usamos la geometría geom_bar():

ggplot(data = datos_banco,
aes(x = Sucursal)) +
geom_bar()

77 / 92
Gráficos con ggplot2
Gráfico de barras
Para generar gráficos de barras usamos la geometría geom_bar():

78 / 92
Gráficos con ggplot2
Gráfico de barras
También lo podemos personalizar

ggplot(data = datos_banco,
aes(x = Sucursal)) +
geom_bar() +
labs(title= 'Distribución de los datos por Sucursal', y= "Cantidad", x= "Sucursal")

79 / 92
Gráficos con ggplot2
Gráfico de barras
También lo podemos personalizar

80 / 92
Gráficos con ggplot2
Gráfico de barras
Finalmente, separamos las barras y agregamos color:

ggplot(data = datos_banco,
aes(x = Sucursal, fill=Sucursal)) +
geom_bar(position="dodge") +
labs(title= 'Distribución de los datos por Sucursal', y= "Cantidad", x= "Sucursal")

81 / 92
Gráficos con ggplot2
Gráfico de barras
Finalmente, separamos las barras y agregamos color:

82 / 92
Gráficos con ggplot2
Diagrama de dispersión
Para graficar la relación entre dos variables cuantitativas usamos diagramas de
dispersión. Si queremos ver si el tiempo cambia de acuerdo al monto, usamos:

ggplot(data = datos_banco,
aes(x= Monto, y = Tiempo_Servicio_seg)) +
geom_point( alpha=0.5) +
labs(title= 'Gráfico de dispersión', y= 'Tiempo')

83 / 92
Gráficos con ggplot2
Diagrama de dispersión
Para graficar la relación entre dos variables cuantitativas usamos diagramas de
dispersión. Si queremos ver si el tiempo cambia de acuerdo al monto, usamos:

84 / 92
Gráficos con ggplot2
Diagrama de dispersión
Podemos agregar una línea de tendencia.

ggplot(data = datos_banco,
aes(x= Monto, y = Tiempo_Servicio_seg)) +
geom_point( alpha=0.5) +
geom_smooth(method=lm) +
labs(title= 'Gráfico de dispersión', y= 'Tiempo')

85 / 92
Gráficos con ggplot2
Diagrama de dispersión
Podemos agregar una línea de tendencia.

86 / 92
Gráficos con ggplot2
Diagrama de dispersión
También podemos dar colores a los puntos según la variable Transacción.

ggplot(data = datos_banco,
aes(x= Monto, y = Tiempo_Servicio_seg)) +
geom_point(aes(color= Transaccion), alpha=0.5) +
labs(title= 'Gráfico de dispersión', y= 'Tiempo')

87 / 92
Gráficos con ggplot2
Diagrama de dispersión
También podemos dar colores a los puntos según la variable Transacción.

88 / 92
Gráficos con ggplot2
Diagrama de dispersión
Finalmente podemos mapear la forma de los puntos.

ggplot(data = datos_banco,
aes(x= Monto, y = Tiempo_Servicio_seg)) +
geom_point(aes(color= Transaccion, shape= Nuevo_Sistema), alpha=0.5) +
labs(title= 'Gráfico de dispersión', y= 'Tiempo')

89 / 92
Gráficos con ggplot2
Diagrama de dispersión
Finalmente podemos mapear la forma de los puntos.

90 / 92
Gracias!
👍
[Práctica 1 - Parte B]

Minería de Datos con R

Dr. Jorge Párraga-Álava

Sígueme en Twitter

@jorgeklz

91 / 92
Referencias
Montaño, N. 2019. Aprendiendo R para DataScience. Sociedad Ecuatoriana de
Estadística

Parraga-Alava, J. 2020. Curso de Minería de Datos. Universidad Técnica de Manabí

Coll, V., Pérez, P. 2017. Curso de Introducción a R. Universidad de Valencia

Santana, J., Farfan, E. 2014. El arte de programar en R. Instituto Mexicano de


Tecnología del Agua.

Godoy, E. 2020. Generación de gráficas con ggplot2. R-Ladies Cuernavaca

92 / 92
Minería de Datos con R
Dr. Jorge Párraga-Álava
Práctica 1 - Parte C

Actualizado al 2021-11-09
Agenda
1. Expresiones regulares

2. Limpieza y transformación de datos

2 / 57
Creación de proyecto en RStudio
Para el desarrollo de esta sesión, no olvide realizar lo siguiente:

1. Crear un proyecto en RStudio.

2. Dentro del proyecto crear las carpetas recomendadas (Scripts, Datos).

3. Crear un nuevo R Script con Ctrl + Shift + N o haga a hacer clic en el menú "File" ->
"New File" -> "R Script"".

4. Guardar el R Script recién creado dentro de la carpeta Scripts.

3 / 57
Paquetes requeridos
Antes de iniciar esta sesión virtual deberá instalar los siguientes paquetes:

if(!require(tidyverse)) {install.packages("tidyverse")}

if(!require(magrittr)) {install.packages("magrittr")}

if(!require(readr)) {install.packages("readr")}

if(!require(dplyr)) {install.packages("dplyr")}

if(!require(stringr)) {install.packages("stringr")}

if(!require(tidyr)) {install.packages("tidyr")}

4 / 57
Paquetes requeridos
Ahora cargue los paquetes:

library("tidyverse")

library("magrittr")

library("readr")

library("dplyr")

library("stringr")

library("tidyr")

5 / 57
Práctica 1 - Parte C
Expresiones regulares

6 / 57
Expresiones regulares
Son patrones utilizados para encontrar una determinada combinación de
caracteres dentro de una cadena de caracteres.

Son como un lenguaje especial para hablar con nuestro computador.

Usaremos principalmente el paquete stringr.

7 / 57
Expresiones regulares
Buscadores de coincidencias
\d cualquier dígito

\w cualquier caracter de palabra

\s espacio en blanco

\b límite de palabra

. cualquier caracter, excepto un salto línea

8 / 57
Expresiones regulares
Buscadores de coincidencias
\D cualquier NO dígito

\W cualquier NO caracter de palabra

\S NO espacio en blanco

9 / 57
Expresiones regulares
Buscadores de coincidencias
Ejemplo
Encontrar un número

\d

10 / 57
Expresiones regulares
Cuantificadores
Para indicar cuántas veces se quiere encontrar cada patrón.

? 0 o 1 vez

+ 1 o más

* 0 o más

11 / 57
Expresiones regulares
Cuantificadores
Para indicar cuántas veces se quiere encontrar cada patrón.

{n} exactamente n

{n,} n o más

{n,m} entre n y m

{,m} hasta m

12 / 57
Expresiones regulares
Cuantificadores
Ejemplo
Encontrar una secuencia de cuatro números.

\d{4}

13 / 57
Expresiones regulares
Anclas
Para fijar el inicio y/o término de una cadena.

^ La expresión regular está al inicio de la cadena

$ La expresión regular está al fin de la cadena

14 / 57
Expresiones regulares
Anclas
Ejemplo
Encontrar una secuencia de cuatro números que estén al final de una cadena de texto.

\d{4}$

15 / 57
Expresiones regulares
Alternos
Para indicar alternativas al encontrar patrones.

[ ] uno de

16 / 57
Expresiones regulares
Alternos
Ejemplo
Palabras terminadas en vocal.

[aeiou]$
Encontrar cualquier dígito.

[[:digit:]]

17 / 57
Expresiones regulares en R
Escape de caracteres especiales
En R, a todas las expresiones regulares que usan \ se les debe agregar otra \ para que
sean interpretadas correctamente.

Expresión regular Expresión regular en R


\d \\d

\s \\s

\w \\w

18 / 57
Expresiones regulares en R
Para interpretar caracteres especiales.

Caracter especial Para que R lo reconozca como tal


^ \\^

$ \\$

+ \\+

? \\?

* \\*

19 / 57
Práctica 1 - Parte C
Limpieza y transformación de datos

20 / 57
Limpieza y transformación de datos
Para esta sesión de trabajo se usarán varios conjuntos de datos, el primero llamado
paises que contiene información de distinto países. Para cada país existen 12
observaciones, una por año.

paises <- read_csv("https://raw.githubusercontent.com/jorgeklz/curso-utm/main/paises.csv")

21 / 57
Limpieza y transformación de datos
Hacemos un previsualización de los datos:

glimpse(paises)

## Rows: 1,704
## Columns: 6
## $ pais <chr> "Afganistán", "Afganistán", "Afganistán", "Afganistá…
## $ continente <chr> "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "Asi…
## $ anio <dbl> 1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992…
## $ esperanza_de_vida <dbl> 28.801, 30.332, 31.997, 34.020, 36.088, 38.438, 39.8…
## $ poblacion <dbl> 8425333, 9240934, 10267083, 11537966, 13079460, 1488…
## $ pib_per_capita <dbl> 779.4453, 820.8530, 853.1007, 836.1971, 739.9811, 78…

22 / 57
Limpieza y transformación de datos
Usamos la función filter.

paises %>%
filter()

## # A tibble: 1,704 × 6
## pais continente anio esperanza_de_vida poblacion pib_per_capita
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Afganistán Asia 1952 28.8 8425333 779.
## 2 Afganistán Asia 1957 30.3 9240934 821.
## 3 Afganistán Asia 1962 32.0 10267083 853.
## 4 Afganistán Asia 1967 34.0 11537966 836.
## 5 Afganistán Asia 1972 36.1 13079460 740.
## 6 Afganistán Asia 1977 38.4 14880372 786.
## 7 Afganistán Asia 1982 39.9 12881816 978.
## 8 Afganistán Asia 1987 40.8 13867957 852.
## 9 Afganistán Asia 1992 41.7 16317921 649.
## 10 Afganistán Asia 1997 41.8 22227415 635.
## # … with 1,694 more rows

23 / 57
Limpieza y transformación de datos
Filtramos por país:

paises %>%
filter(pais=="Ecuador")

## # A tibble: 12 × 6
## pais continente anio esperanza_de_vida poblacion pib_per_capita
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Ecuador Américas 1952 48.4 3548753 3522.
## 2 Ecuador Américas 1957 51.4 4058385 3781.
## 3 Ecuador Américas 1962 54.6 4681707 4086.
## 4 Ecuador Américas 1967 56.7 5432424 4579.
## 5 Ecuador Américas 1972 58.8 6298651 5281.
## 6 Ecuador Américas 1977 61.3 7278866 6680.
## 7 Ecuador Américas 1982 64.3 8365850 7214.
## 8 Ecuador Américas 1987 67.2 9545158 6482.
## 9 Ecuador Américas 1992 69.6 10748394 7104.
## 10 Ecuador Américas 1997 72.3 11911819 7429.
## 11 Ecuador Américas 2002 74.2 12921234 5773.
## 12 Ecuador Américas 2007 75.0 13755680 6873.

24 / 57
Limpieza y transformación de datos
Esta forma de filtrar es exacta:

paises %>%
filter(pais=="Corea")

## # A tibble: 0 × 6
## # … with 6 variables: pais <chr>, continente <chr>, anio <dbl>,
## # esperanza_de_vida <dbl>, poblacion <dbl>, pib_per_capita <dbl>

Notamos que no se obtienen resultados, toda vez que para el caso de "Corea", el
nombre ingresado es "Corea, Rep."

25 / 57
Limpieza y transformación de datos
Para estos casos, se usa la función str_detect() del paquete stringr que detecta la
presencia de una patrón en una cadena.

paises %>%
filter(str_detect(pais, "Corea")) #Alguna vez aparezca Corea

## # A tibble: 24 × 6
## pais continente anio esperanza_de_vida poblacion pib_per_capita
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Corea, Rep. Dem. Asia 1952 50.1 8865488 1088.
## 2 Corea, Rep. Dem. Asia 1957 54.1 9411381 1571.
## 3 Corea, Rep. Dem. Asia 1962 56.7 10917494 1622.
## 4 Corea, Rep. Dem. Asia 1967 59.9 12617009 2144.
## 5 Corea, Rep. Dem. Asia 1972 64.0 14781241 3702.
## 6 Corea, Rep. Dem. Asia 1977 67.2 16325320 4106.
## 7 Corea, Rep. Dem. Asia 1982 69.1 17647518 4107.
## 8 Corea, Rep. Dem. Asia 1987 70.6 19067554 4106.
## 9 Corea, Rep. Dem. Asia 1992 70.0 20711375 3726.
## 10 Corea, Rep. Dem. Asia 1997 67.7 21585105 1691.
## # … with 14 more rows

26 / 57
Limpieza y transformación de datos
Para contar las ocurrencias de "Corea", usamos la función count().

paises %>%
filter(str_detect(pais, "Corea")) %>%
count(pais)

## # A tibble: 2 × 2
## pais n
## <chr> <int>
## 1 Corea, Rep. 12
## 2 Corea, Rep. Dem. 12

27 / 57
Limpieza y transformación de datos
Similarmente ocurre con Perú, cuando no se sabe si fue inscrito con tilde o sin tilde:

paises %>%
filter(str_detect(pais, "Per"))

## # A tibble: 12 × 6
## pais continente anio esperanza_de_vida poblacion pib_per_capita
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Perú Américas 1952 43.9 8025700 3759.
## 2 Perú Américas 1957 46.3 9146100 4245.
## 3 Perú Américas 1962 49.1 10516500 4957.
## 4 Perú Américas 1967 51.4 12132200 5788.
## 5 Perú Américas 1972 55.4 13954700 5938.
## 6 Perú Américas 1977 58.4 15990099 6281.
## 7 Perú Américas 1982 61.4 18125129 6435.
## 8 Perú Américas 1987 64.1 20195924 6361.
## 9 Perú Américas 1992 66.5 22430449 4446.
## 10 Perú Américas 1997 68.4 24748122 5838.
## 11 Perú Américas 2002 69.9 26769436 5909.
## 12 Perú Américas 2007 71.4 28674757 7409.

28 / 57
Limpieza y transformación de datos
También lo podríamos hacer usando expresiones regulares:

paises %>%
filter(str_detect(pais, "Per[u|ú]"))

## # A tibble: 12 × 6
## pais continente anio esperanza_de_vida poblacion pib_per_capita
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Perú Américas 1952 43.9 8025700 3759.
## 2 Perú Américas 1957 46.3 9146100 4245.
## 3 Perú Américas 1962 49.1 10516500 4957.
## 4 Perú Américas 1967 51.4 12132200 5788.
## 5 Perú Américas 1972 55.4 13954700 5938.
## 6 Perú Américas 1977 58.4 15990099 6281.
## 7 Perú Américas 1982 61.4 18125129 6435.
## 8 Perú Américas 1987 64.1 20195924 6361.
## 9 Perú Américas 1992 66.5 22430449 4446.
## 10 Perú Américas 1997 68.4 24748122 5838.
## 11 Perú Américas 2002 69.9 26769436 5909.
## 12 Perú Américas 2007 71.4 28674757 7409.

29 / 57
Limpieza y transformación de datos
Ejemplo
Usamos el conjunto de datos teléfono.

telefonos <- read_csv("https://raw.githubusercontent.com/jorgeklz/curso-utm/main/telefonos.csv")

30 / 57
Limpieza y transformación de datos
Ejemplo
Mostramos las primeras seis observaciones:

head(telefonos)

## # A tibble: 6 × 4
## nombre ciudad numero_telefonico nacimiento
## <chr> <chr> <chr> <dbl>
## 1 Pérez, María Valparaíso +56 981497134 2001
## 2 Juan González Olmué 928374591 1987
## 3 Hernández, Lautaro quilpué 56 964379583 1988
## 4 Lobos, Antonia La Serena 987654321 2001
## 5 Martínez, José La Serena +56-983726153 1996
## 6 Manuel Garrido valparaiso 914230795 1998

31 / 57
Limpieza y transformación de datos
Ejemplo
Contamos cuantas ciudades hay.

# contar y cuantos hay de cada uno


telefonos %>%
count(ciudad)

## # A tibble: 9 × 2
## ciudad n
## <chr> <int>
## 1 La Serena 2
## 2 Olmué 2
## 3 quilpue 1
## 4 quilpué 3
## 5 Serena 2
## 6 valparaiso 1
## 7 Valparaiso 1
## 8 valparaíso 2
## 9 Valparaíso 5

32 / 57
Limpieza y transformación de datos
Ejemplo
Ahora mostramos los datos para obtener todas las versiones de la palabra Quilpué.

telefonos %>%
filter(str_detect(ciudad, "quilpu[e|é]"))

## # A tibble: 4 × 4
## nombre ciudad numero_telefonico nacimiento
## <chr> <chr> <chr> <dbl>
## 1 Hernández, Lautaro quilpué 56 964379583 1988
## 2 Sanhueza, Pedro quilpué 56 981408973 1982
## 3 Aníbal García quilpue 982733747 1987
## 4 Gómez, Lirayén quilpué 914257483 2003

33 / 57
Limpieza y transformación de datos
Ejemplo
Si no usamos corchetes:

telefonos %>%
filter(str_detect(ciudad, "quilpue|é")) # busca la é sola

## # A tibble: 6 × 4
## nombre ciudad numero_telefonico nacimiento
## <chr> <chr> <chr> <dbl>
## 1 Juan González Olmué 928374591 1987
## 2 Hernández, Lautaro quilpué 56 964379583 1988
## 3 Jiménez, Luis Olmué 925403948 1999
## 4 Sanhueza, Pedro quilpué 56 981408973 1982
## 5 Aníbal García quilpue 982733747 1987
## 6 Gómez, Lirayén quilpué 914257483 2003

34 / 57
Limpieza y transformación de datos
Ejemplo
Similarmente buscamos todas las versiones de Valparaíso:

telefonos %>%
filter(str_detect(ciudad, "[v|V]alpara[i|í]so"))

## # A tibble: 9 × 4
## nombre ciudad numero_telefonico nacimiento
## <chr> <chr> <chr> <dbl>
## 1 Pérez, María Valparaíso +56 981497134 2001
## 2 Manuel Garrido valparaiso 914230795 1998
## 3 Soto, Loreto valparaíso 925479238 2007
## 4 Pérez, Pedro valparaíso 985740293 2002
## 5 González, Camila Valparaiso 56 973629584 2004
## 6 Cayuqueo, Marina Valparaíso 973629853 1999
## 7 Jaime Espinoza Valparaíso 56981359284 1987
## 8 Hernández, Francisca Valparaíso 56993418209 1971
## 9 González, Olivia Valparaíso no tengo 1949

35 / 57
Limpieza y transformación de datos
Ejemplo
Ahora, transformamos los datos de modo que queden los nombres de ciudades
correctamente escritos:

telefonos %>%
mutate(ciudad_limpia = case_when(
str_detect(ciudad, "[v|V]alpara[i|í]so") ~ "Valparaíso"
))

36 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 5
## nombre ciudad numero_telefonico nacimiento ciudad_limpia
## <chr> <chr> <chr> <dbl> <chr>
## 1 Pérez, María Valparaíso +56 981497134 2001 Valparaíso
## 2 Juan González Olmué 928374591 1987 <NA>
## 3 Hernández, Lautaro quilpué 56 964379583 1988 <NA>
## 4 Lobos, Antonia La Serena 987654321 2001 <NA>
## 5 Martínez, José La Serena +56-983726153 1996 <NA>
## 6 Manuel Garrido valparaiso 914230795 1998 Valparaíso
## 7 Soto, Loreto valparaíso 925479238 2007 Valparaíso
## 8 Pérez, Pedro valparaíso 985740293 2002 Valparaíso
## 9 González, Camila Valparaiso 56 973629584 2004 Valparaíso
## 10 Jiménez, Luis Olmué 925403948 1999 <NA>
## 11 Sanhueza, Pedro quilpué 56 981408973 1982 <NA>
## 12 Aníbal García quilpue 982733747 1987 <NA>
## 13 Gómez, Lirayén quilpué 914257483 2003 <NA>
## 14 Cayuqueo, Marina Valparaíso 973629853 1999 Valparaíso
## 15 Jaime Espinoza Valparaíso 56981359284 1987 Valparaíso
## 16 Hernández, Francisca Valparaíso 56993418209 1971 Valparaíso
## 17 López, Carla Serena 56912338475 1949 <NA>
## 18 Soto, Martina Serena 925653948 1948 <NA>
## 19 González, Olivia Valparaíso no tengo 1949 Valparaíso

37 / 57
Limpieza y transformación de datos
Ejemplo
Para evitar los NAs cuando no coincide el patrón usamos:

telefonos %>%
mutate(ciudad_limpia = case_when(
str_detect(ciudad, "[v|V]alpara[i|í]so") ~ "Valparaíso",
negate =TRUE ~ as.character(ciudad)
))

38 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 5
## nombre ciudad numero_telefonico nacimiento ciudad_limpia
## <chr> <chr> <chr> <dbl> <chr>
## 1 Pérez, María Valparaíso +56 981497134 2001 Valparaíso
## 2 Juan González Olmué 928374591 1987 Olmué
## 3 Hernández, Lautaro quilpué 56 964379583 1988 quilpué
## 4 Lobos, Antonia La Serena 987654321 2001 La Serena
## 5 Martínez, José La Serena +56-983726153 1996 La Serena
## 6 Manuel Garrido valparaiso 914230795 1998 Valparaíso
## 7 Soto, Loreto valparaíso 925479238 2007 Valparaíso
## 8 Pérez, Pedro valparaíso 985740293 2002 Valparaíso
## 9 González, Camila Valparaiso 56 973629584 2004 Valparaíso
## 10 Jiménez, Luis Olmué 925403948 1999 Olmué
## 11 Sanhueza, Pedro quilpué 56 981408973 1982 quilpué
## 12 Aníbal García quilpue 982733747 1987 quilpue
## 13 Gómez, Lirayén quilpué 914257483 2003 quilpué
## 14 Cayuqueo, Marina Valparaíso 973629853 1999 Valparaíso
## 15 Jaime Espinoza Valparaíso 56981359284 1987 Valparaíso
## 16 Hernández, Francisca Valparaíso 56993418209 1971 Valparaíso
## 17 López, Carla Serena 56912338475 1949 Serena
## 18 Soto, Martina Serena 925653948 1948 Serena
## 19 González, Olivia Valparaíso no tengo 1949 Valparaíso

39 / 57
Limpieza y transformación de datos
Ejemplo
Ahora transformamos las tres ciudades:

# Ahora las tres ciudades


telefonos <- telefonos %>%
mutate(ciudad_limpia = case_when(
str_detect(ciudad, "[v|V]alpara[i|í]so") ~ "Valparaíso",
str_detect(ciudad, "quilpu[e|é]") ~ "Olmué",
str_detect(ciudad, "^Serena$") ~ "La Serena",
negate =TRUE ~ as.character(ciudad)
))

40 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 5
## nombre ciudad numero_telefonico nacimiento ciudad_limpia
## <chr> <chr> <chr> <dbl> <chr>
## 1 Pérez, María Valparaíso +56 981497134 2001 Valparaíso
## 2 Juan González Olmué 928374591 1987 Olmué
## 3 Hernández, Lautaro quilpué 56 964379583 1988 Olmué
## 4 Lobos, Antonia La Serena 987654321 2001 La Serena
## 5 Martínez, José La Serena +56-983726153 1996 La Serena
## 6 Manuel Garrido valparaiso 914230795 1998 Valparaíso
## 7 Soto, Loreto valparaíso 925479238 2007 Valparaíso
## 8 Pérez, Pedro valparaíso 985740293 2002 Valparaíso
## 9 González, Camila Valparaiso 56 973629584 2004 Valparaíso
## 10 Jiménez, Luis Olmué 925403948 1999 Olmué
## 11 Sanhueza, Pedro quilpué 56 981408973 1982 Olmué
## 12 Aníbal García quilpue 982733747 1987 Olmué
## 13 Gómez, Lirayén quilpué 914257483 2003 Olmué
## 14 Cayuqueo, Marina Valparaíso 973629853 1999 Valparaíso
## 15 Jaime Espinoza Valparaíso 56981359284 1987 Valparaíso
## 16 Hernández, Francisca Valparaíso 56993418209 1971 Valparaíso
## 17 López, Carla Serena 56912338475 1949 La Serena
## 18 Soto, Martina Serena 925653948 1948 La Serena
## 19 González, Olivia Valparaíso no tengo 1949 Valparaíso

41 / 57
Limpieza y transformación de datos
Ejemplo
Verificamos los cambios:

telefonos %>%
count(ciudad_limpia)

## # A tibble: 3 × 2
## ciudad_limpia n
## <chr> <int>
## 1 La Serena 4
## 2 Olmué 6
## 3 Valparaíso 9

42 / 57
Limpieza y transformación de datos
Ejemplo
También podemos aplicar transformaciones para la variable del número telefónico:

telefonos %>%
count(numero_telefonico) %>%
head()

## # A tibble: 6 × 2
## numero_telefonico n
## <chr> <int>
## 1 +56 981497134 1
## 2 +56-983726153 1
## 3 56 964379583 1
## 4 56 973629584 1
## 5 56 981408973 1
## 6 56912338475 1

43 / 57
Limpieza y transformación de datos
Ejemplo
Eliminamos cualquier +, -, o espacio en blanco:

telefonos <- telefonos %>%


mutate(
numero_limpio = str_replace_all(numero_telefonico, "\\+|-|[:space:]", "")
)
telefonos

44 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 6
## nombre ciudad numero_telefoni… nacimiento ciudad_limpia numero_limpio
## <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Pérez, María Valpara… +56 981497134 2001 Valparaíso 56981497134
## 2 Juan Gonzál… Olmué 928374591 1987 Olmué 928374591
## 3 Hernández, … quilpué 56 964379583 1988 Olmué 56964379583
## 4 Lobos, Anto… La Sere… 987654321 2001 La Serena 987654321
## 5 Martínez, J… La Sere… +56-983726153 1996 La Serena 56983726153
## 6 Manuel Garr… valpara… 914230795 1998 Valparaíso 914230795
## 7 Soto, Loreto valpara… 925479238 2007 Valparaíso 925479238
## 8 Pérez, Pedro valpara… 985740293 2002 Valparaíso 985740293
## 9 González, C… Valpara… 56 973629584 2004 Valparaíso 56973629584
## 10 Jiménez, Lu… Olmué 925403948 1999 Olmué 925403948
## 11 Sanhueza, P… quilpué 56 981408973 1982 Olmué 56981408973
## 12 Aníbal Garc… quilpue 982733747 1987 Olmué 982733747
## 13 Gómez, Lira… quilpué 914257483 2003 Olmué 914257483
## 14 Cayuqueo, M… Valpara… 973629853 1999 Valparaíso 973629853
## 15 Jaime Espin… Valpara… 56981359284 1987 Valparaíso 56981359284
## 16 Hernández, … Valpara… 56993418209 1971 Valparaíso 56993418209
## 17 López, Carla Serena 56912338475 1949 La Serena 56912338475
## 18 Soto, Marti… Serena 925653948 1948 La Serena 925653948
## 19 González, O… Valpara… no tengo 1949 Valparaíso notengo

45 / 57
Limpieza y transformación de datos
Ejemplo
A cualquier combinación menor de 9 dígitos le agregamos el código de país (56) y en el
caso notengo, agregamos 00000000000.

telefonos <- telefonos %>%


mutate(
numero_limpio = str_replace_all(numero_limpio, "^\\d{9}$", paste0("56", numero_limpio)),
numero_limpio = str_replace_all(numero_limpio, "notengo", "00000000000")
)
telefonos

46 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 6
## nombre ciudad numero_telefoni… nacimiento ciudad_limpia numero_limpio
## <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Pérez, María Valpara… +56 981497134 2001 Valparaíso 56981497134
## 2 Juan Gonzál… Olmué 928374591 1987 Olmué 56928374591
## 3 Hernández, … quilpué 56 964379583 1988 Olmué 56964379583
## 4 Lobos, Anto… La Sere… 987654321 2001 La Serena 56987654321
## 5 Martínez, J… La Sere… +56-983726153 1996 La Serena 56983726153
## 6 Manuel Garr… valpara… 914230795 1998 Valparaíso 56914230795
## 7 Soto, Loreto valpara… 925479238 2007 Valparaíso 56925479238
## 8 Pérez, Pedro valpara… 985740293 2002 Valparaíso 56985740293
## 9 González, C… Valpara… 56 973629584 2004 Valparaíso 56973629584
## 10 Jiménez, Lu… Olmué 925403948 1999 Olmué 56925403948
## 11 Sanhueza, P… quilpué 56 981408973 1982 Olmué 56981408973
## 12 Aníbal Garc… quilpue 982733747 1987 Olmué 56982733747
## 13 Gómez, Lira… quilpué 914257483 2003 Olmué 56914257483
## 14 Cayuqueo, M… Valpara… 973629853 1999 Valparaíso 56973629853
## 15 Jaime Espin… Valpara… 56981359284 1987 Valparaíso 56981359284
## 16 Hernández, … Valpara… 56993418209 1971 Valparaíso 56993418209
## 17 López, Carla Serena 56912338475 1949 La Serena 56912338475
## 18 Soto, Marti… Serena 925653948 1948 La Serena 56925653948
## 19 González, O… Valpara… no tengo 1949 Valparaíso 00000000000

47 / 57
Limpieza y transformación de datos
Ejemplo
También podemos aplicar transformaciones para variables numéricas:

telefonos %>%
count(nacimiento)

## # A tibble: 14 × 2
## nacimiento n
## <dbl> <int>
## 1 1948 1
## 2 1949 2
## 3 1971 1
## 4 1982 1
## 5 1987 3
## 6 1988 1
## 7 1996 1
## 8 1998 1
## 9 1999 2
## 10 2001 2
## 11 2002 1
## 12 2003 1
## 13 2004 1
## 14 2007 1
48 / 57
Limpieza y transformación de datos
Ejemplo
Asignamos categoría según año de nacimiento, usando la función between().

telefonos <- telefonos %>%


mutate(categoria = case_when(
between(nacimiento, 2002, 2020) ~ "Jóven",
between(nacimiento, 1956, 2001) ~ "Adulto",
between(nacimiento, 1955, 1920) ~ "Adulto mayor",
negate =TRUE ~ "Centenario"
))
telefonos

49 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 7
## nombre ciudad numero_telefoni… nacimiento ciudad_limpia numero_limpio
## <chr> <chr> <chr> <dbl> <chr> <chr>
## 1 Pérez, María Valpara… +56 981497134 2001 Valparaíso 56981497134
## 2 Juan Gonzál… Olmué 928374591 1987 Olmué 56928374591
## 3 Hernández, … quilpué 56 964379583 1988 Olmué 56964379583
## 4 Lobos, Anto… La Sere… 987654321 2001 La Serena 56987654321
## 5 Martínez, J… La Sere… +56-983726153 1996 La Serena 56983726153
## 6 Manuel Garr… valpara… 914230795 1998 Valparaíso 56914230795
## 7 Soto, Loreto valpara… 925479238 2007 Valparaíso 56925479238
## 8 Pérez, Pedro valpara… 985740293 2002 Valparaíso 56985740293
## 9 González, C… Valpara… 56 973629584 2004 Valparaíso 56973629584
## 10 Jiménez, Lu… Olmué 925403948 1999 Olmué 56925403948
## 11 Sanhueza, P… quilpué 56 981408973 1982 Olmué 56981408973
## 12 Aníbal Garc… quilpue 982733747 1987 Olmué 56982733747
## 13 Gómez, Lira… quilpué 914257483 2003 Olmué 56914257483
## 14 Cayuqueo, M… Valpara… 973629853 1999 Valparaíso 56973629853
## 15 Jaime Espin… Valpara… 56981359284 1987 Valparaíso 56981359284
## 16 Hernández, … Valpara… 56993418209 1971 Valparaíso 56993418209
## 17 López, Carla Serena 56912338475 1949 La Serena 56912338475
## 18 Soto, Marti… Serena 925653948 1948 La Serena 56925653948
## 19 González, O… Valpara… no tengo 1949 Valparaíso 00000000000
## # … with 1 more variable: categoria <chr>

50 / 57
Limpieza y transformación de datos
Ejemplo
Finalmente, seleccionamos los datos limpios y transformados.

telefonos %>% select(


nombre,
ciudad_limpia,
numero_limpio,
categoria
)

51 / 57
Limpieza y transformación de datos
Ejemplo
## # A tibble: 19 × 4
## nombre ciudad_limpia numero_limpio categoria
## <chr> <chr> <chr> <chr>
## 1 Pérez, María Valparaíso 56981497134 Adulto
## 2 Juan González Olmué 56928374591 Adulto
## 3 Hernández, Lautaro Olmué 56964379583 Adulto
## 4 Lobos, Antonia La Serena 56987654321 Adulto
## 5 Martínez, José La Serena 56983726153 Adulto
## 6 Manuel Garrido Valparaíso 56914230795 Adulto
## 7 Soto, Loreto Valparaíso 56925479238 Jóven
## 8 Pérez, Pedro Valparaíso 56985740293 Jóven
## 9 González, Camila Valparaíso 56973629584 Jóven
## 10 Jiménez, Luis Olmué 56925403948 Adulto
## 11 Sanhueza, Pedro Olmué 56981408973 Adulto
## 12 Aníbal García Olmué 56982733747 Adulto
## 13 Gómez, Lirayén Olmué 56914257483 Jóven
## 14 Cayuqueo, Marina Valparaíso 56973629853 Adulto
## 15 Jaime Espinoza Valparaíso 56981359284 Adulto
## 16 Hernández, Francisca Valparaíso 56993418209 Adulto
## 17 López, Carla La Serena 56912338475 Adulto mayor
## 18 Soto, Martina La Serena 56925653948 Adulto mayor
## 19 González, Olivia Valparaíso 00000000000 Adulto mayor

52 / 57
Práctica 1 - Parte C
Actividad asíncrona

53 / 57
Actividad asíncrona
Transforme la variable nombre de modo que, se muestre primero el nombre y
luego, el apellido (sin comas) de los clientes del conjunto de datos telefonos.
## # A tibble: 19 × 4
## nombres_limpio ciudad_limpia numero_limpio categoria
## <chr> <chr> <chr> <chr>
## 1 María Pérez Valparaíso 56981497134 Adulto
## 2 Juan González Olmué 56928374591 Adulto
## 3 Lautaro Hernández Olmué 56964379583 Adulto
## 4 Antonia Lobos La Serena 56987654321 Adulto
## 5 José Martínez La Serena 56983726153 Adulto
## 6 Manuel Garrido Valparaíso 56914230795 Adulto
## 7 Loreto Soto Valparaíso 56925479238 Jóven
## 8 Pedro Pérez Valparaíso 56985740293 Jóven
## 9 Camila González Valparaíso 56973629584 Jóven
## 10 Luis Jiménez Olmué 56925403948 Adulto
## 11 Pedro Sanhueza Olmué 56981408973 Adulto
## 12 Aníbal García Olmué 56982733747 Adulto
## 13 Lirayén Gómez Olmué 56914257483 Jóven
## 14 Marina Cayuqueo Valparaíso 56973629853 Adulto
## 15 Jaime Espinoza Valparaíso 56981359284 Adulto
## 16 Francisca Hernández Valparaíso 56993418209 Adulto
## 17 Carla López La Serena 56912338475 Adulto mayor
## 18 Martina Soto La Serena 56925653948 Adulto mayor
## 19 Olivia González Valparaíso 00000000000 Adulto mayor

54 / 57
Actividad asíncrona
Solución:

telefonos %>%
mutate (
nom = str_split(nombre, pattern = fixed(","), simplify = TRUE)[,2],
ape = str_split(nombre, pattern = fixed(","), simplify = TRUE)[,1],
nombres_limpio = str_trim(paste(nom, ape))
) %>%
select(
nombres_limpio, ciudad_limpia, numero_limpio, categoria
)

55 / 57
Gracias!
👍
[Práctica 1 - Parte C]

Minería de Datos con R

Dr. Jorge Párraga-Álava

Sígueme en Twitter

@jorgeklz

56 / 57
Referencias
Quiroga, R., Orellana, S. 2020. Expresiones regulares para la Limpieza y
transformación de datos. LatinR

Parraga-Alava, J. 2020. Asignatura Minería de Datos. Universidad Técnica de


Manabí

Grolemund, G., Wickham, H. 2017. R para Ciencia de Datos. R4DS en Español.

57 / 57
Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

Práctica de Minería de Datos


Actualizado: 21 noviembre, 2021

1. Objetivos

Utilizar árboles de decisión como técnica para clasificación de datos.

2. Paquetes requeridos

Para el desarrollo del taller se requieren los siguientes paquetes:

library("MASS"); library("tidyverse");library("dplyr");
library("C50"); library("caret"); library("e1071")

3. Conjunto de datos

El conjunto de datos sobre cangrejos (crabs) presenta siete atributos físicos de los cangrejos, incluida
la clase sex. Está disponible dentro del paquete MASS.

Tarea de clasificación

La tarea consiste entonces en predecir (clasificar) el sexo del cangrejo según sus características físicas.

Dr. Jorge Párraga-Álava Pág. 1


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

4. Desarrollo

4.1 Datos

Para cargar el conjunto de datos usamos el siguiente código.

# cargar la base datos crabs y asignarla a variable


ds_cangrejos <- crabs
# mostrar resumen de atributos y clase
glimpse(ds_cangrejos)

## Rows: 200
## Columns: 8
## $ sp <fct> B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B~
## $ sex <fct> M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M~
## $ index <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1~
## $ FL <dbl> 8.1, 8.8, 9.2, 9.6, 9.8, 10.8, 11.1, 11.6, 11.8, 11.8, 12.2, 12.~
## $ RW <dbl> 6.7, 7.7, 7.8, 7.9, 8.0, 9.0, 9.9, 9.1, 9.6, 10.5, 10.8, 11.0, 1~
## $ CL <dbl> 16.1, 18.1, 19.0, 20.1, 20.3, 23.0, 23.8, 24.5, 24.2, 25.2, 27.3~
## $ CW <dbl> 19.0, 20.8, 22.4, 23.1, 23.0, 26.5, 27.1, 28.4, 27.8, 29.3, 31.6~
## $ BD <dbl> 7.0, 7.4, 7.7, 8.2, 8.2, 9.8, 9.8, 10.4, 9.7, 10.3, 10.9, 11.4, ~

Observamos que son 200 instancias y 8 atributos. Note que el atributo index, no corresponde a car-
acterísticas físicas de los cangrejos, por ello no es considerado. Pare eliminarlo, usamos el siguiente
código:

# eliminar atributo index


ds_cangrejos <- ds_cangrejos %>%
select(-index)

Ahora, cambiamos el nombre de los atributos a español para que sean mas fáciles de interpretar.

ds_cangrejos <- ds_cangrejos %>%


rename(especie=sp, sexo=sex,
ancho_frontal=FL, ancho_posterior=RW,
largo_carapacho=CL, ancho_carapacho=CW,
profundidad_cuerpo=BD)

Luego, binarizamos los atributos categóricos especie y sexo.

Dr. Jorge Párraga-Álava Pág. 2


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

# especie --> B: blue=1, O: orange=0


# sexo --> M: male=1, F: female=0
ds_cangrejos <- ds_cangrejos %>%
mutate(especie = ifelse(especie == "B", 1, 0),
sexo = ifelse(sexo == "M", 1, 0))

Ahora separamos el conjunto de datos en entrenamiento y prueba. Para ello dividimos en 70% y 30%,
respectivamente.

# fijar semilla. Con esto garantizamos que los experimentos sean reproducibles
set.seed(1987)
# generar 70% de números aleatorios
id_instancias <- sample(1:nrow(ds_cangrejos), nrow(ds_cangrejos)*.70)

# crear el conjunto de entrenamiento


ds_entrenamiento <- ds_cangrejos[id_instancias,]
ds_entrenamiento <- ds_entrenamiento %>%
mutate(sexo = factor(sexo, levels = c(1, 0)))

# crear el conjunto de prueba


ds_prueba <- ds_cangrejos[-id_instancias,]
ds_prueba <- ds_prueba %>%
mutate(sexo = factor(sexo, levels = c(1, 0)))

Y para conocer el número de instancias en cada clase, realizamos lo siguiente:

# resumen de instancias por clase


print(ds_entrenamiento %>% count(sexo))

## sexo n
## 1 1 73
## 2 0 67

print(ds_prueba %>% count(sexo))

## sexo n
## 1 1 27
## 2 0 33

Dr. Jorge Párraga-Álava Pág. 3


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

4.2 Clasificación

Usaremos como clasificador el algoritmo de inferencia de árbol de decisión llamado 𝐶5.0. Este infiere
el árbol usando como medida de selección de atributos la razón de ganancia. Además, el paquete
contiene algunas funciones para realizar el proceso de poda y eliminar ramas que no contribuyan a
reducir el error de la clasificación.

Como sabemos, el proceso de clasificación de datos comprende el aprendizaje y clasificación.

• Para el aprendizaje, usaremos el conjunto de entrenamiento para que el algoritmo aprenda a


identificar características de los cangrejos y a partir de ellas inferir el sexo.

• Para la clasificación usaremos el conjunto de pruebas para validar que el algoritmo prediga ade-
cuadamente la clase (sexo) de acuerdo con las características entregadas.

4.2.1 Aprendizaje

Para el proceso de aprendizaje o entrenamiento de nuestro clasificador, realizamos lo siguiente:

# creamos el clasificador indicando que y es sexo, y todos los demás atributos


# indicado como todos menos sexo (-sexo) son las variables predictoras.
clasificador_entrenado <- C5.0(y=ds_entrenamiento$sexo,
x= ds_entrenamiento %>% select(-sexo))
print(clasificador_entrenado)

##
## Call:
## C5.0.default(x = ds_entrenamiento %>% select(-sexo), y = ds_entrenamiento$sexo)
##
## Classification Tree
## Number of samples: 140
## Number of predictors: 6
##
## Tree size: 10
##
## Non-standard options: attempt to group attributes

El algoritmo nos muestra que el conjunto de entrenamiento consta de 140 instancias y 6 variables
predictoras. Si queremos más detalle usamos lo siguiente:

# muestra resumen del entrenamiento del clasificador


summary(clasificador_entrenado)

Dr. Jorge Párraga-Álava Pág. 4


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

##
## Call:
## C5.0.default(x = ds_entrenamiento %>% select(-sexo), y = ds_entrenamiento$sexo)
##
##
## C5.0 [Release 2.07 GPL Edition] Sun Nov 21 11:13:44 2021
## -------------------------------
##
## Class specified by attribute `outcome'
##
## Read 140 cases (7 attributes) from undefined.data
##
## Decision tree:
##
## ancho_posterior > 15.8: 0 (17/1)
## ancho_posterior <= 15.8:
## :...largo_carapacho > 35.6: 1 (34/1)
## largo_carapacho <= 35.6:
## :...ancho_posterior > 12.9: 0 (24)
## ancho_posterior <= 12.9:
## :...largo_carapacho > 30.1: 1 (15)
## largo_carapacho <= 30.1:
## :...ancho_posterior > 11: 0 (15/2)
## ancho_posterior <= 11:
## :...ancho_frontal > 11.7: 1 (15)
## ancho_frontal <= 11.7:
## :...ancho_posterior > 9.1: 0 (10/1)
## ancho_posterior <= 9.1:
## :...especie <= 0: 1 (2)
## especie > 0:
## :...profundidad_cuerpo <= 7.8: 0 (5/1)
## profundidad_cuerpo > 7.8: 1 (3)
##
##
## Evaluation on training data (140 cases):
##
## Decision Tree
## ----------------
## Size Errors
##
## 10 6( 4.3%) <<

Dr. Jorge Párraga-Álava Pág. 5


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

##
##
## (a) (b) <-classified as
## ---- ----
## 68 5 (a): class 1
## 1 66 (b): class 0
##
##
## Attribute usage:
##
## 100.00% ancho_posterior
## 87.86% largo_carapacho
## 25.00% ancho_frontal
## 7.14% especie
## 5.71% profundidad_cuerpo
##
##
## Time: 0.0 secs

Ahora podemos observar las reglas de clasificación producidas a partil del árbol. Allí notamos que el
nodo raíz, y atributo, que mejor discrimina entre clases, es ancho_posterior (100%) cuando su valor
es de más de 15.8 mm. Mientras que largo_carapacho es el segundo atributo con poder de discrimi-
nación de clase. Note que también se genera una matriz de confusión. En esta podemos observar que
el algoritmo clasifica como clase 0 (hembra) a 66 instancia de las 67 que en realidad eran de esta clase.
Mientras que clasificó como clase 1 (macho) a 68 instancias cuando en realidad eran 73. Recuerde que
esta matriz es únicamente ilustrativa del proceso de aprendizaje. Para evaluar el rendimiento real
del algoritmo se debe crear una con base en el conjunto de prueba.

Para visualizar el árbol usamos el siguiente código:

# visualiza el árbol de decisión


plot(clasificador_entrenado, type="s")

Dr. Jorge Párraga-Álava Pág. 6


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

1
ancho_posterior

≤ 15.8 > 15.8


2 19
0
largo_carapacho
(n = 17, err = 5.9%)

≤ 35.6 > 35.6


3 18
1
ancho_posterior
(n = 34, err = 2.9%)

≤ 12.9 > 12.9


4 17
0
largo_carapacho
(n = 24, err = 0.0%)

≤ 30.1 > 30.1


5 16
1
ancho_posterior
(n = 15, err = 0.0%)

≤ 11 > 11
6 15
0
ancho_frontal
(n = 15, err = 13.3%)

≤ 11.7 > 11.7


7 14
1
ancho_posterior
(n = 15, err = 0.0%)

≤ 9.1 > 9.1


8 13
0
especie
(n = 10, err = 10.0%)

≤0 >0
9 10
1
profundidad_cuerpo
(n = 2, err = 0.0%)

≤ 7.8 > 7.8


11 12
0 1
(n = 5, err = 20.0%) (n = 3, err = 0.0%)

Analicemos las reglas:

• La regla 1: ancho_posterior > 15.8 tiene 17 instancias que son de clase 0 (hembra) y 1 de clase
1 (macho), esto se inferiere al multiplicar 17 instancias x 5.9% error de clasificación.

• Similarmente vemos que para la regla 2: ancho_posterior <= 15.8 y largo_carapacho >35.6
existen 34 instancias de clase 1 (macho) y 1 de clase 0 (hembra) (34 x 2.9%).

Poda
Uno de los principales problemas de los árboles de decisión es su tendencia al **overfitting** (sobre-
aprendizaje). Para reducir este problema, se suele utilizar la técnica de **poda** del árbol. Esta elimina
las ramas del árbol que no contribuyen a generalizar el aprendizaje.

4.2.2 Evaluación

Una vez entrenado el algoritmo, se realiza el proceso de clasificación o validación del clasificador.
Para ello se usa la función predict. Esta función, a partir del modelo entrenado, predice a que clase
pertenece cada instancia del conjunto de prueba.

Dr. Jorge Párraga-Álava Pág. 7


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

# genera predicciones a partir del conjunto de pruebas


clasificador_predicciones <- predict(clasificador_entrenado, ds_prueba)

Ahora generamos la matriz de confusión, a través de la función especializada confusionMatrix del


paquete caret.

# genera matriz de confusión.


# indicamos que la clase positiva es la que tiene valor 1 (macho)
confusionMatrix(data = clasificador_predicciones,
reference = ds_prueba$sexo,
positive = "1")

## Confusion Matrix and Statistics


##
## Reference
## Prediction 1 0
## 1 21 5
## 0 6 28
##
## Accuracy : 0.8167
## 95% CI : (0.6956, 0.9048)
## No Information Rate : 0.55
## P-Value [Acc > NIR] : 1.344e-05
##
## Kappa : 0.6284
##
## Mcnemar's Test P-Value : 1
##
## Sensitivity : 0.7778
## Specificity : 0.8485
## Pos Pred Value : 0.8077
## Neg Pred Value : 0.8235
## Prevalence : 0.4500
## Detection Rate : 0.3500
## Detection Prevalence : 0.4333
## Balanced Accuracy : 0.8131
##
## 'Positive' Class : 1
##

En la matriz de confusión observamos que el algoritmo clasificó como macho a 21 de los 26 cangrejos
en el conjunto de datos, y como hembra a 28 de 34. Notamos que la función, además de calcular la ma-

Dr. Jorge Párraga-Álava Pág. 8


Minería de datos Práctica 2 - Clasificación ( Árboles de decisión )

triz de confusión, nos devuelve algunas métricas de calidad. Observamos que la exactitud (Accuracy),
sensibilidad (Sensitivity) y especificidad (Specificity) de nuestro algoritmo es de 81.67%, 77.78%,
y 84.85%, respectivamente. Esto indica que el algoritmo, globalmente hablando, es capaz de identi-
ficar correctamente si un cangrejo es macho o hembra un 82% de las veces. El valor de la sensibilidad
nos indica que el 78% de los cangrejos que eran machos fueron clasificados como machos por el al-
goritmo. Mientras que la especificidad nos indica que el 85% de lo cangrejos que eran hembra fueron
clasificados como hembras por el algoritmo.

En conclusión, el algoritmo clasificador implementado tiene un rendimiento aceptable. Claramente


este rendimiento puede ser mejorado para alcanzar tasas, al menos, superiores al 95% de exactitud.
Esta mejora se puede lograr cambiando la medida de selección de atributos, limitando el tamaño del
árbol o con un proceso de podado.

5. Actividad asíncrona

1. ¿Cuál es el principal inconveniente con la medida de calidad exactitud (Accuracy)?.

2. ¿Qué es el proceso de podado (pruning) de árboles de decisión?

Dr. Jorge Párraga-Álava Pág. 9


Minería de datos Práctica 3 - Regresión ( Lineal )

Práctica de Minería de Datos


Actualizado: 29 noviembre, 2021

1. Objetivos

Utilizar modelos de regresión lineal para la predicción de datos.

2. Paquetes requeridos

Para el desarrollo del taller se requieren los siguientes paquetes:

library("openxlsx");library("tidyverse")
library("dplyr"); library("modelr")

3. Conjunto de datos

El conjunto de datos contiene información semanal de dólares invertidos en publicidad en cada medio
de comunicación, y, la cantidad de clientes que visitan a la cadena de tiendas textiles del Ecuador.
El área financiera se ha quejado del alto gasto generado en horas extras para los empleados de las
tiendas, por lo que quieren planificarse de tal manera que, cuándo se realicen campañas publicitarias
se puedan modificar los horarios de los empleados en función de la cantidad de personas esperadas.

La próxima semana se va a gastar 2000 USD en publicidad, estime cuántos clientes visitarán las
tiendas.

4. Desarrollo

4.1 Datos

Para cargar el conjunto de datos usamos una librería especializada para trabajar con archivos .xlsx:

Dr. Jorge Párraga-Álava Pág. 1


Minería de datos Práctica 3 - Regresión ( Lineal )

# cargar la base datos de publicidad y asignarla a variable


ds_publicidad <- read.xlsx(xlsxFile = "../Datos/ds_publicidad.xlsx", detectDates = TRUE)
# mostrar resumen de atributos y clase
glimpse(ds_publicidad)

## Rows: 169
## Columns: 8
## $ SEMANAS <chr> "2016-01-05", "2016-01-12", "2016-01-19", "2016-01-26~
## $ VISITAS <dbl> 163782, 208690, 182352, 170626, 188772, 190512, 14804~
## $ PUBLICIDAD_TOTAL <dbl> 1400, 1550, 1160, 1240, 1290, 1530, 960, 1440, 550, 1~
## $ TV <dbl> 500, 610, 450, 540, 720, 470, 390, 620, 270, 880, 280~
## $ RADIO <dbl> 280, 470, 490, 290, 360, 360, 430, 530, 180, 760, 300~
## $ PERIODICO <dbl> 620, 470, 220, 410, 210, 700, 140, 290, 100, 280, 110~
## $ REDES <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10~
## $ USA_FAMOSO <chr> "NO", "NO", "NO", "NO", "NO", "NO", "NO", "NO", "NO",~

Observamos que son 169 instancias y 8 atributos. Como se solicita estimar cuanta gente visitará las
tiendas con un gasto de 2000 USD, veamos primero ¿cuánta gente visitó historicamente la tienda,
cuando se gastó menos de 2000 USD en publicidad?. Para eso usaremos un diagrama de dispersión.

options(scipen=999)
ds_publicidad %>%
filter(PUBLICIDAD_TOTAL < 2000) %>%
ggplot(aes(x=PUBLICIDAD_TOTAL, y=VISITAS)) +
geom_point() +
labs(title= 'Visitas recibidas según gasto en publicidad',
x='Publicidad total (en dólares)', y= 'Visitas')

Dr. Jorge Párraga-Álava Pág. 2


Minería de datos Práctica 3 - Regresión ( Lineal )

Visitas recibidas según gasto en publicidad


500000

400000
Visitas

300000

200000

100000

500 1000 1500 2000


Publicidad total (en dólares)

A partir del diagrama de dispersión observamos que el patrón de puntos trazados se inclina desde
la parte inferior izquierda a la superior derecha, esto nos indica que aparentemente existe una cor-
relación positiva entre las variables PUBLICIDAD_TOTAL y VISITAS. Esto significa que a medida que
aumenta el gasto de publicidad se incrementa el número de visitas a las tiendas.

Entrenamiento y prueba

El siguiente paso consiste en separar el conjunto de datos en entrenamiento y prueba. Para ello dividi-
mos en 70% y 30%, respectivamente.

set.seed(1987)
# generar 70% de números aleatorios
id_instancias <- sample(1:nrow(ds_publicidad), nrow(ds_publicidad)*.70)
# crear el conjunto de entrenamiento
ds_entrenamiento <- ds_publicidad[id_instancias,]
# crear el conjunto de prueba
ds_prueba <- ds_publicidad[-id_instancias,]

Dr. Jorge Párraga-Álava Pág. 3


Minería de datos Práctica 3 - Regresión ( Lineal )

4.2 Regresión lineal simple

4.2.1 Modelo

Para responder la pregunta: si se gastan 2000 USD en publicidad, ¿cuántos clientes visitarán las
tiendas?, usamos la regresión lineal simple de acuerdo al siguiente modelo:

𝑦 ̂ = 𝛽 0 + 𝛽1 𝑥

Donde 𝑦 ̂ representa el número estimado de clientes que visitarán las tiendas, 𝛽0 es el intercepto, 𝛽1
la pendiente, y 𝑥 corresponde a la variable PUBLICIDAD_TOTAL.

Para realizar la regresión, R dispone de la función lm que realiza la estimación de los parámetros del
modelo y ofrece información adicional del mismo. Para ello usamos el siguiente código:

# Realiza una regresión lineal simple: y ~ x


rl_simple <- lm(VISITAS ~ PUBLICIDAD_TOTAL, data = ds_entrenamiento)

Para ver los resultados de la regresión usamos lo siguiente:

summary(rl_simple)

##
## Call:
## lm(formula = VISITAS ~ PUBLICIDAD_TOTAL, data = ds_entrenamiento)
##
## Residuals:
## Min 1Q Median 3Q Max
## -138926 -34131 -8642 18314 259975
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -63893.14 18574.41 -3.44 0.00081 ***
## PUBLICIDAD_TOTAL 202.58 12.25 16.53 < 0.0000000000000002 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 73760 on 116 degrees of freedom
## Multiple R-squared: 0.7021, Adjusted R-squared: 0.6995
## F-statistic: 273.3 on 1 and 116 DF, p-value: < 0.00000000000000022

El modelo de regresión estimó como 𝛽0 el valor de -63893.14 y como 𝛽1 202.58. Estos valores impli-
can que, por cada dólar que se incremente en publicidad, llegarán 202 personas más a las tiendas,

Dr. Jorge Párraga-Álava Pág. 4


Minería de datos Práctica 3 - Regresión ( Lineal )

esto partiendo de una base de -63893.14 (no real). Adicionalmente se obtiene un coeficiente de de-
terminación 𝑅2 ajustado de 0.6995 lo cual indica que el modelo explica el 69.95% de la varianza de la
variable VISITAS. En general esto indica que es un modelo con un “buen” ajuste, claramente la idea es
que este valor sea cercano al 100%. Finalmente se obtiene un p-value muy cercano a 0 (valor menor
que 0.05), lo que indica que hay suficiente evidencia estadística que nos permite concluir que hay un
buen ajuste en el modelo predictivo generado.

Entonces para responder la pregunta: ¿cuántos clientes visitarán las tiendas, si se gastan 2000
USD en publicidad?, se realiza lo siguiente:

# Asignamos 2000 a la variable independiente


PUBLICIDAD_TOTAL=2000
# Convertimos a dataframe y realizamos la predicción con base en nuestro modelo
print(as.data.frame(PUBLICIDAD_TOTAL) %>%
# La función add_predictions utiliza rl_simple para estimar las VISITAS
add_predictions(rl_simple, var = 'PREDICCION') )

## PUBLICIDAD_TOTAL PREDICCION
## 1 2000 341268.6

Entonces nuestro modelo indica que si se gastan 2000 USD en publicidad se estima que llegarán
341268 clientes a las tiendas.

4.2.2 Predicción y visualización

Se generan predicciones a partir de nuestro modelo y se muestra gráficamente, como sigue:

# Agrega predicciones.
# Toma del conjunto de pruebas la variable PUBLICIDAD_TOTAL
ds_prediccion <- ds_prueba %>% select(PUBLICIDAD_TOTAL) %>%
add_predictions(rl_simple, var = 'PREDICCION')
# agregamos a ds_prueba la variable PREDICCION
ds_prueba$PREDICCION <- ds_prediccion$PREDICCION

Para visualizar cuanto se alejan los datos reales de la predicción, graficamos los errores.

# Visualiza predicciones.
ds_prueba %>% ggplot(aes(x= PUBLICIDAD_TOTAL, y= VISITAS)) +
# generamos lineas de errores
geom_segment(aes(xend = PUBLICIDAD_TOTAL, yend = PREDICCION), color= "gray") +
geom_point() +
# creamos la línea de regresión
geom_line(aes(y= PREDICCION), colour = "red", size = 1) + ggtitle("Errores predicción")

Dr. Jorge Párraga-Álava Pág. 5


Minería de datos Práctica 3 - Regresión ( Lineal )

Errores predicción

600000

400000
VISITAS

200000

500 1000 1500 2000 2500


PUBLICIDAD_TOTAL

4.2.3 Evaluación

Una vez ajustado el modelo de regresión, se realiza el proceso de validación. Para la regresión lineal
se usará el error de predicción (𝑒). Este consiste en obtener las diferencias entre los valores reales (𝑦)
y valores predichos (𝑦).̂ Entonces la métrica de calidad será la raiz del error cuadrático medio (RMSE),
que se calcula como sigue:
∑(𝑦 − 𝑦)̂ 2
𝑅𝑀 𝑆𝐸 = √
𝑁
Donde 𝑁 es el número de instancias en el conjunto de datos de prueba.

Entonces calculamos los errores para cada instancia en el conjunto de datos usando el código siguiente:

# seleccionamos las columnas VISITAS (y), PREDICCION (y^)


RMSE <- sqrt(sum((ds_prueba$VISITAS - ds_prueba$PREDICCION)^2)/(nrow(ds_prueba)))
print(RMSE)

## [1] 67993.23

Observamos que el error de nuestro modelo es de 67993.23, esto quiere decir que hay una variación
entre lo que predice el modelo y lo que realmente ocurrió. Tal variación es en aproximadamente 68000
visitas a las tiendas de la cadena.

Dr. Jorge Párraga-Álava Pág. 6


Minería de datos Práctica 3 - Regresión ( Lineal )

En conclusión, el modelo de predicción implementado tiene un rendimiento medianamente aceptable.


Claramente este rendimiento puede ser mejorado para alcanzar errores cercanos a 0. Esta mejora
se puede lograr aumentando la cantidad de instancias en el dataset o realizando diversas formas de
separación del conjunto de datos.

4.3 Regresión lineal múltiple

El directorio la cadena de tiendas desea saber si la presencia de famosos en la publicidad influye en el


número de visitas a las tiendas. Para ello se le pide a usted que desarrolle un modelo de regresión lineal
múltiple (PUBLICIDAD_TOTAL + USA_FAMOSO) para estimar el número de visitas cuando se gastan
1500 USD en publicidad con presencia de famoso, y sin presencia de famoso.

El modelo matemático de la regresión sería:

𝑦 ̂ = 𝛽0 + 𝛽1 .𝑥1 + 𝛽2 .𝑥2

Siendo 𝑥1 , y 𝑥2 las variables PUBLICIDAD_TOTAL y USA_FAMOSO, respectivamente.

4.3.1 Adecuar los datos

Convertimos a binario la variable USA_FAMOSO.

# Convierte a binario
ds_publicidad <- ds_publicidad %>%
mutate(USA_FAMOSO_NUM = ifelse(USA_FAMOSO=="SI", 1, 0))

Separamos datos en entrenamiento y prueba.

set.seed(1987)
# generar 70% de números aleatorios
id <- sample(1:nrow(ds_publicidad), nrow(ds_publicidad)*.70)
# crear el conjunto de entrenamiento
ds_entrenamiento <- ds_publicidad[id,]
# crear el conjunto de prueba
ds_prueba <- ds_publicidad[-id,]

4.3.2 Modelo

Realiza la regresión lineal múltiple.

Dr. Jorge Párraga-Álava Pág. 7


Minería de datos Práctica 3 - Regresión ( Lineal )

# Aplica regresión múltiple


rl_multiple <- ds_entrenamiento %>%
lm(VISITAS ~ PUBLICIDAD_TOTAL + USA_FAMOSO_NUM, data=.) #<<
# Ver resumen de resultados
summary(rl_multiple) #<<

##
## Call:
## lm(formula = VISITAS ~ PUBLICIDAD_TOTAL + USA_FAMOSO_NUM, data = .)
##
## Residuals:
## Min 1Q Median 3Q Max
## -162861 -39801 -1369 27695 219455
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -88938.19 16619.27 -5.352 0.00000045083 ***
## PUBLICIDAD_TOTAL 199.10 10.65 18.689 < 0.0000000000000002 ***
## USA_FAMOSO_NUM 75200.79 12059.43 6.236 0.00000000768 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 64040 on 115 degrees of freedom
## Multiple R-squared: 0.7773, Adjusted R-squared: 0.7735
## F-statistic: 200.7 on 2 and 115 DF, p-value: < 0.00000000000000022

El modelo de regresión estimó como 𝛽0 el valor de -88938.19 y como 𝛽1 199.10, 𝛽2 75200.79. Adi-
cionalmente se obtiene un coeficiente de determinación 𝑅2 ajustado de 0.7735 lo cual indica que el
modelo explica el 77.35% de la varianza de la variable VISITAS. En general esto indica que es un modelo
con un “buen’ ’ ajuste, claramente la idea es que este valor sea cercano al 100%.

4.3.3 Predicción

Entonces para responder la pregunta: ¿cuánto será número de visitas cuando se gastan 1500 USD
en publicidad con presencia de famoso, y sin presencia de famoso?, se realiza lo siguiente:

𝑦 = −88938.19 + 199.10 × 𝑃 𝑈 𝐵𝐿𝐼𝐶𝐼𝐷𝐴𝐷_𝑇 𝑂𝑇 𝐴𝐿 + 75200.79 × 𝑈 𝑆𝐴_𝐹 𝐴𝑀 𝑂𝑆𝑂

PUBLICIDAD_TOTAL <- c(1500, 1500)


USA_FAMOSO_NUM <- c(1, 0)
respuesta <- as_data_frame(cbind(PUBLICIDAD_TOTAL, USA_FAMOSO_NUM)) %>%

Dr. Jorge Párraga-Álava Pág. 8


Minería de datos Práctica 3 - Regresión ( Lineal )

add_predictions(rl_multiple, var = 'PREDICCION_VISITAS (miles)')


print(respuesta)

## # A tibble: 2 x 3
## PUBLICIDAD_TOTAL USA_FAMOSO_NUM `PREDICCION_VISITAS (miles)`
## <dbl> <dbl> <dbl>
## 1 1500 1 284916.
## 2 1500 0 209715.

Entonces nuestro modelo indica que si se gastan 1500 USD en publicidad y se usa famoso en ella,
se estima que llegarán 284916 clientes a las tiendas. Mientras que si NO se usa famosa, la cantidad
estimada de clientes es de 209715.

5. Actividad asíncrona

Para el modelo de regresión lineal múltiple, usando el conjunto de prueba realice lo siguiente:

1. Grafique los errores.

2. Determine el valor del RMSE.

6. Referencias

Párraga-Álava, J. 2020. Taller de Minería de Datos.

Montaño, N. 2019. Regresion y Series de tiempo aplicadas.

Dr. Jorge Párraga-Álava Pág. 9

También podría gustarte