Inteligencia Analítica de Datos con R


logo

Diplomado en Inteligencia Analítica de Datos (Semana 1.2)

Msc. Roberto Trespalacios

Importancia de la calidad de la información

La falta de calidad de la informacion (datos), es uno de los principales problemas a los que se enfrentan los responsables de sistemas de información y las empresa en general. Te contamos por qué es importante priorizar la calidad de los datos.

Calidad y Tratamiento de Datos

  • A menudo se dice que el 80% del análisis de datos se gasta en el proceso de limpieza y preparación de los datos. (Dasu y Johnson, 2003)
  • Los datos bien estructurados tienen dos propósitos:
    • Hace que los datos sean adecuados para el procesamiento del software, ya sean funciones matemáticas, visualización, etc. Revela información y nuevas perspectivas.
    • El artículo de Hadley Wickham sobre Tidy Data proporciona una acertada explicación detrás del concepto de datos ordenados o “tidy data”

Introducción a tidyverse: dplyr

  • El paquete dplyr de R es parte del marco de trabajo tidyverse de R.
  • Este contiene un conjunto de herramientas (funciones) sumamente intuitivas y poderosas para una rápida y fácil manipulación y procesamiento de los datos.
  • Las posibilidades de dplyr son muy extensas, pero abordaremos las más importantes.

Uso de la libreria `dplyr`

Carguemos las librerías (Observación: Primero de se deben instalar las librerías o paquetes con: install.package())

library(readr)  # Se cargan los paquetes o librerías de tidyverse.
library(dplyr)

Recordemos, que en la clase semana 1.1, trbajamos con los datos iris. Veamos nuevamente.

mi_iris <- read_csv(file = "C:/Users/Roberto Trespalacio/Documents/mi_iris.csv") # leemos los datos locales
head(mi_iris) # visualizamos el encabezado de los datos

La estructura mostrada se conoce como tibble. Los Tibbles son una versión moderna de los Data Frame.

Valores no disponibles

Los valores no disponibles o faltantes juegan un papel importante en las estadísticas y el análisis de datos.

A menudo, los valores faltantes no deben ignorarse, sino que deben estudiarse cuidadosamente para determinar si hay un patrón subyacente o causa de su desaparición. En R, tenemos la siguientes nomenclaturas para valores no disponibles:

  • NA se usa para representar cualquier valor que “no está disponible (Not Available)” o “falte” (en el sentido estadístico).
  • Inf significa “valor infinito”. Esto se debe a una división de un número diferente de cero por cero; por ejemplo, 1/0.
  • NaN significa “no es un número (Not a Number)”. Esto puede ser debido a:
    • 0/0
    • Inf - Inf
    • Inf/Inf
    • 0*Inf

Probando valores no disponibles

A manera de ejemplo, construyamos un vector y verifiquemos cuales entradas del vector no NA o NaN con la función is.na()

mis_datos <- c(1,2,3,NA,5,6,NA,NaN,9)
mi_na <- is.na(mis_datos)
mi_na

Si queremos realizar una operación con estos datos, por ejemplo el promedio, con la función mean(), tendremos inconvenientes. Veamos:

mean(mis_datos) 

Podemos sortear esa situación agregando un parámetro a la función mean(). Así:

mean(x, na.rm=TRUE) # retorna 2
  • La función complete.cases(nombre_variable) devuelve un vector lógico que indica qué casos están completos.
  • La función na.omit() devuelve el objeto con eliminación en lista de valores faltantes.
# Crear nueva variable sin valores no disponibles:
nuevos_datos <- na.omit(mis_datos)
nuevos_datos

Explorar los datos y unir las bases

Antes de comenzar a analizar los datos tenemos que depurarlos o realizar. Para estos primeros ejercicios vamos a usar las bases de datos de morosidad (morosidad16.csv y morosidad17.csv) con la CCSS (Caja Costarricense de Seguro Social).

Ambas bases de datos tienen las siguientes variables:

  • id: cédula del deudor ya sea cédula física o jurídica.
  • nombre: Nombre de la persona física o jurídica.
  • deuda16 y deuda17: monto de la deuda en colones.
  • situación: situación en la que se encuentra la deuda.
  • lugar.pago: sucursal donde se tiene que cancelar la deuda.
  • Estado: Estado de la deuda.

Unir y mezclar bases de datos

  • Para unir o mezclar bases de datos necesitamos una o más variables en común entre las dos bases de datos.
  • Existen varias funciones para unir bases de datos.
  • Una de ellas es merge, que sirve para unir columnas de dos bases de datos diferentes.
  • Para unir bases es clave hacerse la pregunta: ¿Queremos conservar todas las variables o solo las que hacen “match” o coincidencia?. De acuerdo a la respuesta, así va a depender la fórmula(función) que usemos.

Unir y mezclar bases de datos - la función merge()

Merge es una función genérica cuyo método principal es para data frames: el método predeterminado convierte sus argumentos en data frames y llama al data.frame.

Sintaxixs de la función merge()

  • merge(base1, base2, by.x=“nombre variable base 1”, by.y=“nombre variable base 2”)
    • En el caso en el que la variable se llame igual en las dos bases: merge(base1, base2, by=“nombre variable”)
  • merge(base1, base2, by=“nombre variable”, all=TRUE)
    • Si queremos que se unan todos los casos, usamos la opción all=TRUE.
  • merge(base1, base2, by=c(“variable1”, “variable2”))
    • Si queremos unir por más de una variable y si las variables se llaman igual en ambas bases.
    • Si las variables se llaman diferente en ambas bases: merge(base1, base2, by.x=c(“variable1”, “variable2”), by.y=c(“variable1”, “variable2”))

Trabajando con los datos morosidad16 y morosidad17

Para este ejercicio queremos unir las dos bases de morosidad en una sola, dejando todas las observaciones de ambas bases. Primero carguemos los datos.

morosidad16 <- read_csv("Documents/utb_diplomado/sem_1.2/datos/morosidad16.csv")
morosidad17 <- read_csv("Documents/utb_diplomado/sem_1.2/datos/morosidad17.csv")

Luego, usamos merge() para unir por la variable id.

morosidad <- merge(morosidad16, morosidad17, by= "id", all=TRUE)

Otra forma: Usando la librería dplyr

También podemos unir bases con funciones de la libreria dplyr(). Las funciones se ilustran en la imagen:

La que utilicemos va a depender de qué es lo queramos unir. Ejemplo, si queremos unir todas las observaciones entonces vamos a utilizar la función full_join.

library(dplyr)
morosidad <- full_join(morosidad16, morosidad17, by= "id")
  • Si las variables se llama diferente: La sintaxis sería:
    by = c(“variable1” = “variable2”).
  • Si queremos unir por más de una variable: La sintaxis sería:
    by = c(“variable1”, “variable2”).

RECOMENDACIÓN: Para simplificar la sintaxis, se debe procurar nombres iguales en las diferentes bases. Puede ser antes de importar la base, o en R con el comando rename(). Así:
rename(base, nombre_nuevo = nombre anterior)

Ejemplo: left_join e inner_join

Veamos como resulta el left_joint de las bases morosidad16, morosidad17

morosidad_left <- left_join(morosidad16, morosidad17, by= "id")

La cantidad de instancias es menor a la que tiene full_joint

morosidad_inner <- inner_join(morosidad16, morosidad17, by= "id")

La cantidad de instancias es menor a la que tiene full_joint y left_joint

Exploración de los datos

Con la nueva base de datos morosidad, resultante del full joint, podemos explorar sus contenidos. Usemos las siguientes funciones:

  • View() : Para ver la base de datos completa desplegada.
  • dim() : Esta función nos permite ver la dimensión de la base de datos, en este caso tenemos 10 variables y 78.703 observaciones.
  • head() : Nos permite ver las primeras filas de la base de datos y el tipo de variable. Podemos seleccionar la cantidad de filas a ver así: head(base, n=20), nos muestra las primeras 20 filas. También podemos ver que nos muestra.
  • tail(): Nos permite ver las últimas filas. Tiene la misma sintaxis que head().
  • glimpse() : nos permite exploarar las variables. Nos dice, al lado de cada variable cuál es el tipo. Por ejemplo nos dice que nombre.x es caracter y que deuda17 es “double”, el cual es un formato numérico.

Veamos el ejemplo

# ejemplo con los datos morosidad
View(morosidad)
dim(morosidad)
head(morosidad)
tail(morosidad)
glimpse(morosidad)

Manipulación y cración de datos

La función select()

  • El paquetes dplyr tiene, entre otras, cinco funciones para manipular datos: select(), filter(), arrange(), mutate() y summarize().

Uso de select()

La función select() nos permite seleccionar columnas. select(dataframe, col1, col2), donde: col1, col2, son los nombres de las columnas seleccionadas.

Ejemplo 1: supongamos que queremos seleccionar únicamente las columnas de id y deuda:

select(morosidad, id, deuda17, deuda16)

Ejemplo 2: podemos seleccionar todas las columnas menos algunas, suando “-”. Por ejemplo, si queremos todas las columnas menos Estado.

select(morosidad, -Estado)

Ejemplo 3: Si queremos seleccionar un rango de columnas por ejemplo de id a situacion usamos “:”.

select(morosidad, id:situacion.x)

Ejemplo 4: Almacenar una nueva base, excluyendo: nombre.y, situacion.y, lugar.pago.y

morosidad1 <- select(morosidad, -nombre.y, -situacion.y, -lugar.pago.y)
morosidad1

La función filter()

Uso de filter()

La función filter() nos permite filtrar filas. filter(dataframe, condicion), donde condición es la condión lógica por la que queremos filtrar datos. Para ello usamos operadores lógicos.

  • >: mayor que
  • <: menor que
  • >=: mayor o igual que
  • <=: menor o igual que
  • ==: igual que (se ponen dos signos de igual)
  • !=: diferente
  • &: y
  • |: o
  • is.na(variable): filtra los valores en blanco de la variable seleccionada.
  • !is.na(variable): filtra los valores que no están en blanco de la variable.

Ejemplo 5: si queremos filtrar solamente las deudas superiores a un millón:

filter(morosidad1, deuda17>1000000)

La función filter() (continuación)

Ejemplo 6: si queremos filtrar las deudas que crecieron entre 2016 y 2017:

filter(morosidad1, deuda17>deuda16)

Ejemplo 7: si queremos filtrar solamente las deudas mayores a un millón y de díficil cobro:

filter(morosidad1, deuda17>1000000 & situacion.x=="DIFICIL COBRO")

Ejemplo 8: En este ejemplo, tenemos deudas del 2016 y del 2017, y nos interesa analizar únicamente los casos de las empresas o personas que han estado morosas por los dos años. Para ello podemos usar la función filter:

morosidad1 <- filter(morosidad1, !is.na(deuda17), !is.na(deuda16))

El código de arriba lo que hace es filtrar la base por todos aquellos registros que no tengan valores vacíos en 2017 y luego por todos los que no tienen registros vacíos en 2016. Como podemos ver, esto nos da como resultado menos registros en nuestra base de datos.

La funcióna función mutate()

Uso de mutate()

La función mutate(data.frame, nueva.variable = operacion_variable), nos permite crear nuevas columnas de forma fácil.

Ejemplo 9: Podemos crear una variable que me diga cuánto cambió la deuda, que es la diferencia entre deuda17 y deuda16.

morosidad1 <- mutate(morosidad1, cambio.deuda=deuda17-deuda16)

Ejemplo 10: Podemos crear una nueva variable que me categorice el cambio en la deuda en si aumentó o no. Esto podemos hacerlo con la función if_else() o ifelse (funcionar igual). La sintaxis es: ifelse(condición, valor cierto, valor falso). (Es similar a la función if en Excel).

morosidad1 <- mutate(morosidad1, tipo.cambio=ifelse(cambio.deuda < 0,"disminuyó", "aumentó"))

Ejemplo 11: Con mutate podemos crear multiples variables a la vez, separando cada una por coma, es decir:

var1 = deuda17-deuda16 # creamos la variable 1
var2 = ifelse(cambio.deuda<0,"disminuyó", "aumentó") # creamos la variable 2

morosidad1 <- mutate(morosidad1,  cambio.deuda = var1, tipo.cambio = var2)

La función arrange()

Uso de arrange()

La función arrange(data.frame, nueva.variable = operacion_variable) Arrange nos permite ordenar las base por una o varias columnas.

Ejemplo 12: si queremos ordenar la base en orden ascendente por deuda17 y por cambio.deuda:

morosidad1 <- arrange(morosidad1, deuda17, cambio.deuda)

Ejemplo 13: Si lo queremos en orden descendente, usamos la fucnión desc()

morosidad1 <- arrange(morosidad1, desc(deuda17), desc(cambio.deuda))

El operador %>% (pipe o tubería) de la librería magrittr

  • Aunque no es obligatorio, los paquetes tidyr y dplyr utilizan el operador %>% desarrollado por Stefan Milton Bache en el paquete R magrittr.
  • Todas las funciones de tidyr y dplyr se pueden usar sin el operador de tubería, una de las grandes ventajas que ofrecen estos paquetes es la capacidad de encadenar varias funciones al incorporar %>%.

Este operador enviará un valor, o el resultado de una expresión, a la siguiente expresión/llamada de función. Por ejemplo, una función para filtrar datos se puede escribir como:

Simplificar el trabajo con %>%

  • Es un operador muy útil cuando trabajamos con dplyr es pipe operator que visualmente se ve así %>%.
  • Este operador nos va a facilitar muchísimo el trabajo con funciones y nos permite hacer comando con menos líneas de código.

¿Cómo funciona el %>%? Lo primero es poner el objeto (tabla o dataframe) al cual queremos aplicar las operaciones de la forma base %>% funcion(). Esto nos ahorra estar poniendo como primer argumento de las funciones de dplyr al objeto.

Simplificar el trabajo con %>% - Ejemplo

Ejemplo 14: recapitulemos todas las líneas de código que usamos anteriormente para manipular la base de datos morosidad:

morosidad1 <- select(morosidad, -nombre.y, -situacion.y, -lugar.pago.y)
morosidad1 <- filter(morosidad1, !is.na(deuda17), !is.na(deuda16))
morosidad1 <- mutate(morosidad1, cambio.deuda=deuda17-deuda16)
morosidad1 <- mutate(morosidad1, tipo.cambio=ifelse(cambio.deuda<0,"disminuyó", "aumentó"))
morosidad1 <- arrange(morosidad1, desc(deuda17), desc(cambio.deuda))

Todos los pasos realizados anteriormente podríamos haberlos hecho de forma más simple usando el %>%:

morosidad2 <- morosidad %>%
  select(-nombre.y, -situacion.y, -lugar.pago.y) %>%
  filter(!is.na(deuda17), !is.na(deuda16)) %>%
  mutate(cambio.deuda=deuda17-deuda16,
       tipo.cambio=ifelse(cambio.deuda<0,"disminuyó", "aumentó")) %>%
  arrange(desc(deuda17), desc(cambio.deuda))

En el siguiente link, pueden ver múltiples ejemplos. https://www.datacamp.com/tutorial/pipe-r-tutorial