Bienvenidos al meetup de R4HR Club de R para RRHH. Nuestro primer meetup auspiciado por R Consortium.
R4HR Club de R para RRHH es una comunidad de aprendizaje del lenguaje de programación R para las personas que trabajen o quieran trabajar en Recursos Humanos. Las personas que integramos esta comunidad provenimos de distintas partes del mundo, y contamos con distintas experiencias, personalidades, habilidades e historias. De toda esta diversidad se nutre nuestra comunidad. Por eso buscamos:
Todas las personas que participan de nuestros eventos, comunidades y redes tienen que cumplir con nuestro código de conducta. Te invitamos a seguirnos en todas nuestras redes sociales en este link.
También pueden revisar todo nuestro contenido disponible en nuestro Google Drive, en este canal de YouTube y en nuestro repositorio de GitHub
Todo nuestro contenido es abierto, y se puede usar libremente citando la fuente 💪.
Esta obra está bajo una Licencia Creative Commons Atribución 4.0 Internacional.
Si quieren correr el código de este documento es un script común de R pueden hacer lo siguiente. Esto funciona si el archivo está en la misma carpeta del proyecto.
::purl("Sesion_37_Analisis_Exploratorio_Datos.Rmd") knitr
El Análisis Exploratorio de Datos (EDA por sus siglas en inglés) es una etapa fundamental en cualquier proyecto de datos, ya sea un tablero o un modelo predictivo.
Esta etapa es importante en parte porque te permite explorar preguntas iniciales y poner a prueba tus intuiciones. También es un proceso crítico porque hacemos un análisis de la calidad de los datos. El objetivo de la etapa es desarrollar un entendimiento de los datos.
Es un proceso que permite poner en práctica las habilidades de visualización, de limpieza y transformación de datos, y hacer los ajustes que sean necesarios previo al desarrollo de un proyecto.
El libro R para Ciencia de Datos escrito por Hadley Wickham y Garrett Grolemund y traducido por la comunidad de R Latinoamericana tiene un montón de información y guía para hacerlo paso a paso usando el conjuto de paquetes de tidyverse También vamos a explorar otros paquetes que hacen algunas cosas de manera muy simple.
Trabajar con proyectos en RStudio hace que todo el trabajo sea más sencillo. Los proyectos crean una carpeta en nuestra PC en donde se almacenarán los archivos, tablas, scripts, y hace que todo sea más organizado.
Para crear un proyecto tenés podés entrar en: * File * New project
Y luego poner el nombre de la carpeta.
Los paquetes o librerías son extensiones desarrolladas por la comunidad o por empresas que facilitan el uso de R y expanden sus capacidades. En este encuentro vamos a usar los siguientes paquetes:
DataExplorer
: Desarrollado por Boxuan Cui, Link a su web.
funModeling
: Desarrollado por Pablo Casas. Link al libro.
tidyverse
: Desarrollado por Hadley Wickham y muchos más. Link a la web.
Este último paquete, tidyverse
es una colección de paquetes que permiten realizar muchas tareas de exploración, limpieza y transformación de datos.
Para utilizar un paquete, lo primero que tenemos que hacer es instalarlos. Eso lo hacemos con la función install.packages()
y dentro del paréntesis tenemos que poner el nombre del paquete. Tengan en cuenta que:
R es un lenguaje case sensitive o sea que hay que prestar atención a mayúsculas y minúsculas.
Para instalar los paquetes hay que usar comillas
Este es un paso que hacemos una sola vez por computadora.
Para correr el código se tienen que parar en la línea de código que quieren usar y apretar las teclas Ctrl
+ Enter
o bien el triángulo verde (como si fuera un ícono de “Play” ▶️)
# Instalar los paquetes DataExplorer, funModeling, y tidyverse
install.packages("DataExplorer")
install.packages("funModeling")
install.packages("tidyverse")
Esto lo que hace es instalar paquetes desde CRAN, que es un repositorio donde se publican los paquetes, asegurando un estándar de calidad y de documentación que hace que trabajar con cualquier paquete de CRAN sea seguro.
Para usar las funciones de los paquetes que instalamos, ahora tenemos que cargarlos. Esto lo que hace es de alguna manera “activar” el paquete y que podamos empezar sus funciones.
Para cargar un paquete tenemos que usar la función library()
. Recuerden prestar atención a las mayúsculas y minúsculas. Ahora no son necesarias las comillas.
Una de las formas en las que nos damos cuenta que el paquete está instalado es cuando empezamos a escribir su nombre y nos aparece el nombre del paquete para autocompletar. Esta es una de las ventajas de trabajar en RStudio.
# Cargar los paquetes DataExplorer, funModeling, y tidyverse
library(DataExplorer)
library(funModeling)
library(tidyverse)
Vamos a trabajar con dos versiones de la Encuesta KIWI de Sueldos de RH que hicimos el año pasado desde R4HR.
kiwi_ar.RDS
: Una versión limpia y organizada de la encuesta. El formato .RDS
es propio de R y matiene algunas características de los datos. Están filtradas únicamente las respuestas de Argentina.
encuesta_cruda.csv
: La versión cruda de la encuesta con todas las respuestas.
Para cargar los archivos, tenemos que prestar atención:
La ubicación del archivo. En nuestro caso están en una carpeta llamada datos
.
Recuerden que R es case sensitive, atención a mayúsculas y minúsculas.
La ubicación, el nombre y la extensión del archivo tienen que estar entre comillas.
Carguemos los datos. Para cargar el archivo .RDS
vamos a usar la función de R base readRDS()
. Para el archivo .csv
vamos a usar la función read.csv()
también de R base. Usamos esa función porque las columnas están separadas por un punto y coma (;
).
# Cargar la versión limpia de la encuesta
<- readRDS("datos/kiwi_ar.RDS")
kiwi
# Cargar el archivo crudo
<- read.csv("datos/encuesta_cruda.csv", fileEncoding = "latin1", sep = ";") crudo
Recuerden:
La instalación de los paquetes se hace una sola vez por computadora.
La carga de los paquetese se hace cada vez que se abre un script.
R base contiene algunas funciones muy útiles para una primera exploración de datos. Vamos a practicar con la tabla kiwi
.
Una de esas funciones es View()
. En RStudio abre una pestaña mostrando la tabla de datos.
View(kiwi)
Nos hacemos los cancheros programando en R pero siempre miramos una tabla 😜.
Una función que nos permite ver la estructura del dataset es str()
.
# Usar la función str() con el data frame kiwi
str(kiwi)
## tibble [548 × 44] (S3: tbl_df/tbl/data.frame)
## $ genero : chr [1:548] "Masculino" "Femenino" "Masculino" "Femenino" ...
## $ genero_diverso : chr [1:548] "No" "No" "Si" "No" ...
## $ edad : num [1:548] 49 35 33 24 32 32 26 29 30 34 ...
## $ discapacidad : chr [1:548] "No tengo ninguna discapacidad" "No tengo ninguna discapacidad" "No tengo ninguna discapacidad" "No tengo ninguna discapacidad" ...
## $ nivel_formacion : chr [1:548] "Universitario completo" "Universitario completo" "Universitario en curso" "Universitario en curso" ...
## $ carrera_grado : chr [1:548] "RRHH / RRLL / RRTT" "RRHH / RRLL / RRTT" "RRHH / RRLL / RRTT" "RRHH / RRLL / RRTT" ...
## $ tipo_universidad : chr [1:548] "Universidad Privada" "Universidad Privada" "Universidad Pública" "Universidad Privada" ...
## $ provincia : chr [1:548] "Ciudad Autónoma de Buenos Aires" "Buenos Aires" "Chaco" "Buenos Aires" ...
## $ region : chr [1:548] "Centro" "Centro" "NEA" "Centro" ...
## $ id : int [1:548] 1 2 3 4 5 6 7 8 9 10 ...
## $ rubro : chr [1:548] "Servicios financieros; seguros" "Comercio" "Otros" "IT" ...
## $ dotacion : num [1:548] 110 1433 6000 270 700 ...
## $ origen_capital : chr [1:548] "Nacional" "Nacional" "Multinacional" "Nacional" ...
## $ dotacion_rh : num [1:548] 2 10 55 7 4 25 3 9 2 10 ...
## $ puesto : Factor w/ 6 levels "Administrativo",..: 6 2 3 2 6 3 2 3 4 3 ...
## $ tipo_contratacion : chr [1:548] "Full time" "Full time" "Full time" "Full time" ...
## $ funcion_rh : chr [1:548] "Generalista" "Administración de personal" "Relaciones laborales" "Reclutamiento y selección" ...
## $ personas_a_cargo : num [1:548] 1 0 8 0 3 0 0 2 1 0 ...
## $ anios_en_empresa : num [1:548] 5 0 9 1 10 2 3 5 7 2 ...
## $ anios_en_puesto : num [1:548] 5 0 3 1 3 2 3 3 4 2 ...
## $ anios_experiencia : num [1:548] 20 7 8 2 10 14 5 5 4 12 ...
## $ sueldo_bruto : num [1:548] 250000 55700 55000 47000 86747 ...
## $ beneficios : chr [1:548] "Medicina prepaga / Plan de salud, Horarios flexibles, Vacaciones extendidas, Licencias extendidas, Frutas y sna"| __truncated__ "Tarjeta de descuento" "Medicina prepaga / Plan de salud, Horarios flexibles, Abono de celular, Seguro de vida (adicionales a los de le"| __truncated__ "Medicina prepaga / Plan de salud, Seguro de vida (adicionales a los de ley), Idiomas" ...
## $ bono : chr [1:548] "No recibo bono" "Menos de un sueldo" "No recibo bono" "No recibo bono" ...
## $ ajuste : chr [1:548] "2 ajustes" "1 solo" "2 ajustes" "1 solo" ...
## $ ajuste_porcentaje : num [1:548] 23 20 50 25 50 10 15 17 25 30 ...
## $ ajuste_mes : chr [1:548] "Agosto" "Marzo" "Septiembre" "Septiembre" ...
## $ otros_proyectos : chr [1:548] "No" "No" "No" "No" ...
## $ erp : chr [1:548] "Bejerman" "Enlatado propio" "SAP / SuccessFactors" "No tenemos sistema de gestión" ...
## $ nombre_area : chr [1:548] "Gestión de Personas" "Recursos Humanos" "Recursos Humanos" "Recursos Humanos" ...
## $ mate : chr [1:548] "Si, está permitido" "Si, está permitido" "Si, está permitido" "Si, está permitido" ...
## $ idioma_exigencia : chr [1:548] "No" "No" "No" "No" ...
## $ idioma_porcentaje : num [1:548] 0 0 0 0.2 0 0.2 0 0.1 NA 0 ...
## $ contactos_linkedin : num [1:548] 7500 500 100 3000 1474 ...
## $ satisfaccion : num [1:548] 5 3 5 3 5 2 3 4 NA 2 ...
## $ busqueda : chr [1:548] "No, pero escucho ofertas" "No, pero escucho ofertas" "No, pero escucho ofertas" "No, pero escucho ofertas" ...
## $ beneficios_expectativa : chr [1:548] "-" "Vacaciones extendidas, almuerzo,medicina prepaga" "Bono semestral" "mas home, bonificaciones, comedor" ...
## $ rh_una_palabra : chr [1:548] "Gestión" "Servicio" "Indispensable" "Empatia" ...
## $ pregunta_bizarra : chr [1:548] "-" "Si pensaba tener hijos en los próximos meses" "No recuerdo ninguna" "cual es tu signo?" ...
## $ teletrabajo : chr [1:548] "Si" "Voy rotando entre la oficina y el trabajo" "Si" "Voy rotando entre la oficina y el trabajo" ...
## $ elementos : chr [1:548] "Computadora / Laptop, Abono de celular" "Computadora / Laptop" "Computadora / Laptop, Silla ergonómica, Abono de celular, Abono de internet" "Computadora / Laptop" ...
## $ valoracion_gestion_empresa: num [1:548] 4 3 5 3 3 2 4 4 NA NA ...
## $ es_lider : num [1:548] 1 0 0 0 1 0 0 0 1 0 ...
## $ rangos_aumentos : Factor w/ 5 levels "Sin aumentos",..: 4 3 5 4 5 2 3 3 4 4 ...
La función str()
nos brinda esta información:
Qué tipo de objeto es: En este caso es un tibble
que es un tipo de data frame propio de tidyverse
.
Su tamaño: filas y columnas. ¿Se animan a decir cuántas filas y cuántas columnas tiene esta tabla?
El nombre de cada fila:: Después del signo $
.
Qué tipo de variable es: chr
, num
, int
, o Factor
. No tenemos en este dataset, pero también existen las variables logical
o lgl
.
Una muestra de los primeros registros.
En el paquete tidyverse
hay una función similar que se llama glimpse()
. Probemos la función y veamos qué diferencias hay.
# Usar la función glimpse() con el data frame kiwi
glimpse(kiwi)
## Rows: 548
## Columns: 44
## $ genero <chr> "Masculino", "Femenino", "Masculino", "Feme…
## $ genero_diverso <chr> "No", "No", "Si", "No", "Si", "No", "No", "…
## $ edad <dbl> 49, 35, 33, 24, 32, 32, 26, 29, 30, 34, 41,…
## $ discapacidad <chr> "No tengo ninguna discapacidad", "No tengo …
## $ nivel_formacion <chr> "Universitario completo", "Universitario co…
## $ carrera_grado <chr> "RRHH / RRLL / RRTT", "RRHH / RRLL / RRTT",…
## $ tipo_universidad <chr> "Universidad Privada", "Universidad Privada…
## $ provincia <chr> "Ciudad Autónoma de Buenos Aires", "Buenos …
## $ region <chr> "Centro", "Centro", "NEA", "Centro", "Centr…
## $ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, …
## $ rubro <chr> "Servicios financieros; seguros", "Comercio…
## $ dotacion <dbl> 110, 1433, 6000, 270, 700, 7500, 100, 700, …
## $ origen_capital <chr> "Nacional", "Nacional", "Multinacional", "N…
## $ dotacion_rh <dbl> 2, 10, 55, 7, 4, 25, 3, 9, 2, 10, 1, 3, 7, …
## $ puesto <fct> Gerente, Analista, HRBP, Analista, Gerente,…
## $ tipo_contratacion <chr> "Full time", "Full time", "Full time", "Ful…
## $ funcion_rh <chr> "Generalista", "Administración de personal"…
## $ personas_a_cargo <dbl> 1, 0, 8, 0, 3, 0, 0, 2, 1, 0, 0, 0, 0, 0, 9…
## $ anios_en_empresa <dbl> 5, 0, 9, 1, 10, 2, 3, 5, 7, 2, 0, 1, 4, 0, …
## $ anios_en_puesto <dbl> 5, 0, 3, 1, 3, 2, 3, 3, 4, 2, 0, 1, 0, 2, 5…
## $ anios_experiencia <dbl> 20, 7, 8, 2, 10, 14, 5, 5, 4, 12, 10, 13, 9…
## $ sueldo_bruto <dbl> 250000, 55700, 55000, 47000, 86747, 85500, …
## $ beneficios <chr> "Medicina prepaga / Plan de salud, Horarios…
## $ bono <chr> "No recibo bono", "Menos de un sueldo", "No…
## $ ajuste <chr> "2 ajustes", "1 solo", "2 ajustes", "1 solo…
## $ ajuste_porcentaje <dbl> 23, 20, 50, 25, 50, 10, 15, 17, 25, 30, 0, …
## $ ajuste_mes <chr> "Agosto", "Marzo", "Septiembre", "Septiembr…
## $ otros_proyectos <chr> "No", "No", "No", "No", "Si, en emprendimie…
## $ erp <chr> "Bejerman", "Enlatado propio", "SAP / Succe…
## $ nombre_area <chr> "Gestión de Personas", "Recursos Humanos", …
## $ mate <chr> "Si, está permitido", "Si, está permitido",…
## $ idioma_exigencia <chr> "No", "No", "No", "No", "No", "No", "No", "…
## $ idioma_porcentaje <dbl> 0.0, 0.0, 0.0, 0.2, 0.0, 0.2, 0.0, 0.1, NA,…
## $ contactos_linkedin <dbl> 7500, 500, 100, 3000, 1474, 9240, 1000, 980…
## $ satisfaccion <dbl> 5, 3, 5, 3, 5, 2, 3, 4, NA, 2, 5, 2, 3, 5, …
## $ busqueda <chr> "No, pero escucho ofertas", "No, pero esc…
## $ beneficios_expectativa <chr> "-", "Vacaciones extendidas, almuerzo,medic…
## $ rh_una_palabra <chr> "Gestión", "Servicio", "Indispensable", "Em…
## $ pregunta_bizarra <chr> "-", "Si pensaba tener hijos en los próximo…
## $ teletrabajo <chr> "Si", "Voy rotando entre la oficina y el tr…
## $ elementos <chr> "Computadora / Laptop, Abono de celular", "…
## $ valoracion_gestion_empresa <dbl> 4, 3, 5, 3, 3, 2, 4, 4, NA, NA, NA, 4, 4, 5…
## $ es_lider <dbl> 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1…
## $ rangos_aumentos <fct> Entre 21 y 30, Entre 11 y 20, Más de 30, En…
Aporta información similar, excepto por el tipo de objeto, pero glimpse()
tiene una salida un poco más prolija. Además a las variables num
las identifica como dbl
.
Ahora probemos la función summary()
. Como el data frame tiene muchas columnas vamos a seleccionar sólo 4 columnas. Una por cada tipo de variable.
# Creo una tabla con sólo 4 variables
<- kiwi %>%
kiwi_2 select(genero, contactos_linkedin, id, puesto) # Elijo las columnas que deseo
# Correr la función summary() con el data frame kiwi_2
summary(kiwi_2)
## genero contactos_linkedin id puesto
## Length:548 Min. : 0 Min. : 1.0 Administrativo: 41
## Class :character 1st Qu.: 300 1st Qu.:137.8 Analista :211
## Mode :character Median : 700 Median :274.5 HRBP : 57
## Mean : 2562 Mean :274.5 Responsable :125
## 3rd Qu.: 2500 3rd Qu.:411.2 Jefe : 66
## Max. :30000 Max. :548.0 Gerente : 48
## NA's :98
Con las variables de tipo character
lo único que nos indica es la cantidad de filas que tiene. En cambio, con las variables de tipo Factor
como es en este caso la variable puesto
, nos muestra la cantidad de casos para cada rol dentro de la columna.
En cambio, con las variables numéricas, no importa si son numeric
o integer
, obtenemos la siguiente información:
Min.
: el valor mínimo
1st Qu.
: el valor del primer cuartil
Median
: la mediana
Mean
: el promedio
3rd Qu.
: el valor del tercer cuartil
Max
: el valor máximo
NA's
: la cantidad de datos nulos (celdas vacías en esa columna).
La última función que veremos ahora es names()
, que la información que aporta es 🥁🥁🥁 los nombres de las columnas
# Usemos la función names() con kiwi
names(kiwi)
## [1] "genero" "genero_diverso"
## [3] "edad" "discapacidad"
## [5] "nivel_formacion" "carrera_grado"
## [7] "tipo_universidad" "provincia"
## [9] "region" "id"
## [11] "rubro" "dotacion"
## [13] "origen_capital" "dotacion_rh"
## [15] "puesto" "tipo_contratacion"
## [17] "funcion_rh" "personas_a_cargo"
## [19] "anios_en_empresa" "anios_en_puesto"
## [21] "anios_experiencia" "sueldo_bruto"
## [23] "beneficios" "bono"
## [25] "ajuste" "ajuste_porcentaje"
## [27] "ajuste_mes" "otros_proyectos"
## [29] "erp" "nombre_area"
## [31] "mate" "idioma_exigencia"
## [33] "idioma_porcentaje" "contactos_linkedin"
## [35] "satisfaccion" "busqueda"
## [37] "beneficios_expectativa" "rh_una_palabra"
## [39] "pregunta_bizarra" "teletrabajo"
## [41] "elementos" "valoracion_gestion_empresa"
## [43] "es_lider" "rangos_aumentos"
# Usemos la función names() con crudo =P
names(crudo)
## [1] "Género"
## [2] "X.Te.identificás.como.LGBT...lesbiana..gay..bisexual..transexual..otra.minoría.sexual.."
## [3] "Rango.Edad"
## [4] "Discapacidad"
## [5] "Máximo.nivel.de.formación"
## [6] "Carrera"
## [7] "X.En.qué.tipo.de.universidad.estudiaste.tu.carrera.de.grado."
## [8] "País"
## [9] "Provincia.donde.trabajas"
## [10] "Trabajo"
## [11] "Rubro.de.la.empresa"
## [12] "Cantidad.de.Empleados"
## [13] "Origen.del.capital"
## [14] "X.Cuántas.personas.integran.el.área.de.RRHH."
## [15] "X.En.qué.puesto.trabajás."
## [16] "Tipo.de.contratación"
## [17] "X.Cuál.es.tu.función.principal.en.RRHH."
## [18] "X.Cuántas.personas.tenés.a.cargo...poné.0.si.no.tenés.gente.a.cargo."
## [19] "X.Hace.cuántos.años.trabajas.en.la.empresa.donde.estás...0.para.menos.de.un.año."
## [20] "X.Cuántos.años.de.experiencia.tenés.en.RRHH."
## [21] "X.Cuál.es.tu.remuneración.BRUTA.MENSUAL.en.tu.moneda.local...antes.de.impuestos.y.deducciones."
## [22] "X.Qué.beneficios.tenés."
## [23] "X.Recibís.bonos."
## [24] "X.Tuviste.ajustes.por.inflación.en.2020."
## [25] "X.Cuál.fue.el.porcentaje.de.aumento.acumulado.que.tuviste.en.2020."
## [26] "Mes.del.último.ajuste"
## [27] "X.Trabajás.en.proyectos.independientes.además.de.tu.empleo."
## [28] "X.Qué.sistema.de.gestión.de.RRHH.usan.en.tu.empresa."
## [29] "X.Cómo.se.llama.el.área.en.tu.empresa."
## [30] "X.Se.podía.tomar.mate.en.las.oficinas.de.tu.empresa...antes.del.COVID.19."
## [31] "X.Te.exigieron.saber.un.idioma.extranjero..inglés..portugués..etc...para.entrar.a.trabajar.en.tu.empresa."
## [32] "X.Qué.porcentaje.del.tiempo.usas.el.idioma.extranjero.en.tu.puesto.actual."
## [33] "X.Cuántos.contactos.tenés.en.LinkedIn...poné.0.si.no.tenés.cuenta.de.LinkedIn."
## [34] "X.Qué.tan.satisfecho.estás.con.tu.empresa."
## [35] "X.Estás.buscando.trabajo."
## [36] "X.Qué.beneficios.te.gustaría.tener."
## [37] "Definí.a.RRHH.con.una.sola.palabra"
## [38] "X.Cuál.es.la.pregunta.más.bizarra.que.te.han.hecho.has.hecho.en.una.entrevista."
## [39] "X.Estás.trabajando.desde.tu.casa."
## [40] "X.Qué.elementos.te.proveyó.la.empresa.para.que.puedas.trabajar.desde.tu.casa."
## [41] "X.Cómo.valorarías.la.gestión.de.tu.empresa.en.este.nuevo.contexto."
## [42] "X.Cómo.estás.registrado.a.fiscalmente."
## [43] "X.Hace.cuántos.años.trabajás.como.freelance."
## [44] "X.Dónde.trabajás.habitualmente...sin.considerar.la.coyuntura.por.COVID.19."
## [45] "X.Exportás.tus.servicios."
## [46] "Si.exportás.servicios...a.través.de.qué.medios.de.pago.recibís.los.pagos.del.exterior."
## [47] "X.Aceptás.pagos.en.cuotas."
## [48] "X.Trabajás.con.otros.freelancers.de.tu.mismo.rubro."
## [49] "X.Tu.servicio.principal.está.relacionado.con.búsqueda.y.selección."
## [50] "X.Te.dedicás.principalmente.a.realizar.búsquedas.de.IT.Tecnología."
## [51] "X.Trabajás.a.riesgo."
## [52] "X.Cuál.es.el.coeficiente.que.cobrás.por.tus.servicios."
## [53] "El.coeficiente.lo.calculás.sobre."
## [54] "X.Ofrecés.garantía."
## [55] "X.Cuál.es.el.servicio.principal.que.brindas...si.brindás.más.de.un.servicio..elegí.el.que.más.ingresos.genere."
## [56] "X.Cuál.es.el.valor.hora.promedio.que.ofrecés...moneda.local."
😱, no? En las palabras de Morfeo en Matrix:
En la introducción del meetup les decíamos que el análisis exploratorio de datos es también visual. R base tiene la función plot
que permite hacer gráficos. Probemos primero haciendo un gráfico por variable. La lógica de la sintaxis es la siguiente: nombre_dataframe$nombre_variable
. Por ejemplo, para graficar la variable edad
tengo que escribir:
plot(kiwi$edad)
# Prueben graficar la variable puesto
plot(kiwi$puesto)
# Prueben graficar la variable genero
$genero <- as.factor(kiwi$genero)
kiwi
plot(kiwi$genero)
Al final del encuentro veremos otra manera de hacer gráficos.
El paquete DataExplorer
desarrollado por Boxuan Cui tiene tres objetivos principales:
Realizar análisis exploratorios de datos.
Desarrollar tareas de feature engineering
Generar reportes.
Hoy solo veremos los puntos 1 y 3.
Para el análisis exploratorio, una de las primeras funciones que vemos en la documentación del paquete es la función introduce()
. Usando el signo de interrogación delante de la función podemos abrir la ayuda de la función.
# Revisar la ayuda de la función introduce()
introduce()
?
# Usar la función con la tabla kiwi
introduce(kiwi)
## # A tibble: 1 × 9
## rows columns discrete_columns continuous_columns all_missing_columns
## <int> <int> <int> <int> <int>
## 1 548 44 29 15 0
## # … with 4 more variables: total_missing_values <int>, complete_rows <int>,
## # total_observations <int>, memory_usage <dbl>
Esta función nos permite ver:
rows
: la cantidad de filas
columns
: la cantidad de variables
discrete_columns
: la cantidad de variables discretas
continuos_columns
: el número de variables continuas
all_missing_columns
: columnas que sólo contienen valores nulos
total_missing_values
: cantidad de celdas con valores nulos
complete_rows
: total de filas que no tienen ningún dato faltante
total_observations
: Es la cantidad total de celdas
memory_usage
: es el tamaño estimado del data frame en bytes.
Toda esta información también la podemos ver visualmente con la función plot_intro()
. Y con la función plot_missing()
podemos ver el porcentaje de datos nulos por columna, y la misma función establece si es problemático o no.
# Usar la función plot_intro()
plot_intro(kiwi)
# Usar la función plot_missing()
plot_missing(kiwi)
# Usar la función plot_missing() modificando el parámetro missing_only
plot_missing(kiwi, missing_only = TRUE)
Otra función interesante es plot_bar()
que hace gráficos de barra de todas las variables discretas.
# Usar la función plot_bar() con el data frame kiwi
plot_bar(kiwi, maxcat = 20)
El primer intento no sale del todo bien porque hay respuestas con mucho texto. Probemos modificando el parámetro maxcat = 20
.
Otro parámetro interesante dentro de plot_bar()
es by
que le indica a la función que realice los gráficos pero explicados por alguna variable de interés. Lo que hace es generar gráficos de barras apilados al 100% para ver cómo se distribuyen las proporciones de las variables.
# Repitamos el gráfico anterior pero con by = "genero"
plot_bar(kiwi, maxcat = 20, by = "genero")
Algo que siempre debemos hacer con las variables numéricas es analizar su distribución. Para eso podemos usar la función plot_histogram()
.
# Usar la función plot_histogram() para analizar las variables numéricas
plot_histogram(kiwi)
Este análisis ya nos permite detectar algunas anomalías, por ejemplo en las variables anios_en_empresa
y anios_experiencia
tenemos varios valores imposibles. ¿Pueden ver cuáles son? Un tema aparte es el id
que si bien está representado por un número no deberíamos usarlo para los análisis. Una forma de resolverlo es usando la función drop_column()
del paquete DataExplorer
o select()
de tidyverse
.
# Opción 1: drop_column()
<- drop_columns(kiwi,
kiwi_3 ind = "id")
# Opción 2: select()
<- kiwi %>%
kiwi_3b select(-id)
Algo que también podemos apreciar es que las variables satisfaccion
y la variable valoracion_gestion_empresa
si bien están representadas por números, en realidad son variables ordinales y por lo tanto deberíamos cambiarlas a variables de tipo factor. Para eso usaremos la función update_columns()
.
# Sobrescribir un objeto usando la función update_columns()
<- update_columns(kiwi_3, # data frame
kiwi_4 c("satisfaccion", "valoracion_gestion_empresa"), # columnas a modificar
what = as.factor) # a qué tipo
# Probar los cambios
summary(kiwi_4$satisfaccion)
## 1 2 3 4 5 NA's
## 30 61 184 136 50 87
Este paquete tiene varias opciones de gráficos. Prueben crear un nuevo data frame con 4 variables numéricas y una variable categórica usando la función select()
y probar las siguientes funciones.
Para probar las funciones pueden usar algunos de los bloques de código anteriores o bien abrir uno nuevo apretando las teclas Ctrl
+ Alt
+ I
. Prueben modificar los gráficos modificando el parámetro by
con la variable categórica que hayan elegido.
plot_qq()
plot_scatterplot()
plot_boxplot()
Hay varias funciones muy interesantes para descubrir que están explicadas en la página del paquete.
La última función que vamos a ver de este paquete se llama create_report()
y prepárense para 🤯.
# Usar la función create_report()
create_report(kiwi)
Prueben crear un data frame con 5 variables. Una de ellas tiene que ser genero
el resto pueden ser dos categóricas y dos numéricas por ejemplo y corran la función de la siguiente manera: create_report(kiwi_4, y = "genero").
funModeling
es un paquete desarrollado por Pablo Casas, a quien tuvimos el placer de tener en R4HR en la sesión 9. Si todavía están explorando qué lenguajes estudiar pueden explorar sus cursos gratuitos de la Escuela de Datos Vivos. Respecto del paquete, Pablo escribió un libro explicando sus funciones y mucho más, que se llama Libro Vivo de Ciencia de Datos.
Las salidas de este paquete generan mucha información así que para los fines prácticos de este encuentro, seleccionemos 7 variables:
# Seleccionemos 7 variables
<- kiwi %>%
kiwi_7 select(sueldo_bruto, puesto, rubro, anios_experiencia, satisfaccion, dotacion, contactos_linkedin)
La primera función que vamos a explorar se llama status()
. Probemosla con nuestro nuevo data frame reducido.
# Usar la función status()
status(kiwi_7)
## variable q_zeros p_zeros q_na p_na q_inf
## sueldo_bruto sueldo_bruto 0 0.00000000 0 0.0000000 0
## puesto puesto 0 0.00000000 0 0.0000000 0
## rubro rubro 0 0.00000000 0 0.0000000 0
## anios_experiencia anios_experiencia 8 0.01459854 0 0.0000000 0
## satisfaccion satisfaccion 0 0.00000000 87 0.1587591 0
## dotacion dotacion 0 0.00000000 0 0.0000000 0
## contactos_linkedin contactos_linkedin 20 0.03649635 98 0.1788321 0
## p_inf type unique
## sueldo_bruto 0 numeric 241
## puesto 0 factor 6
## rubro 0 character 27
## anios_experiencia 0 numeric 35
## satisfaccion 0 numeric 5
## dotacion 0 numeric 163
## contactos_linkedin 0 numeric 167
Esta función nos aporta la siguiente información:
La cantidad de 0
, NA
y valores infinitos: q_zeros
, q_na,
y q_inf
respectivamente y el porcentaje que representan.
Que tipo de variable contiene cada columna: type
La cantidad de valores únicos que contiene la variable: unique
.
Este último dato es importante especialmente en variables de tipo factor
o character
porque nos da una idea de la cardinalidad de la variable. Por ejemplo la variable puesto
tiene 6 valores únicos (Administrativo, Analista, HRBP, Responsable, Jefe, Gerente), su cardinalidad es mucho menor que el de la variable rubro
donde tenemos 27 valores únicos.
Esto nos sirve para identificar variables que podemos utilizar para agrupar, lo cual también puede hacerse con variables numéricas como satisfaccion
, ya que al tener tan pocos valores únicos, nos da una idea de que puede ser una variable ordinal que podríamos convertir a factor
por ejemplo.
Otra función muy útil para analizar variables categóricas u ordinales es la función freq()
. Veamos que hace:
# Usar la función freq() en kiwi_7
freq(kiwi_7)
## puesto frequency percentage cumulative_perc
## 1 Analista 211 38.50 38.50
## 2 Responsable 125 22.81 61.31
## 3 Jefe 66 12.04 73.35
## 4 HRBP 57 10.40 83.75
## 5 Gerente 48 8.76 92.51
## 6 Administrativo 41 7.48 100.00
## rubro
## 1 IT
## 2 Otros
## 3 Servicios de salud
## 4 Comercio
## 5 Alimentación; bebidas; tabaco
## 6 Servicios de consultoría
## 7 Construcción
## 8 Función pública
## 9 Industria autopartista
## 10 Servicios profesionales
## 11 Servicios financieros; seguros
## 12 Hotelería, restauración, turismo
## 13 Transporte (incluyendo aviación civil; ferrocarriles por carretera)
## 14 Oil & gas
## 15 Agro
## 16 Servicios públicos (agua;gas; electricidad)
## 17 Textiles; vestido; cuero; calzado
## 18 Educación
## 19 Industrias químicas
## 20 Bancos; banca online;
## 21 Minería (carbón, otra minería)
## 22 Servicios de correos, y de telecomunicaciones
## 23 Medios de comunicación; cultura; gráficos
## 24 Producción de metales básicos
## 25 Transporte marítimo; puertos;
## 26 Silvicultura; madera; celulosa; papel
## 27 Ingeniería mecánica
## frequency percentage cumulative_perc
## 1 81 14.78 14.78
## 2 80 14.60 29.38
## 3 59 10.77 40.15
## 4 39 7.12 47.27
## 5 35 6.39 53.66
## 6 31 5.66 59.32
## 7 23 4.20 63.52
## 8 19 3.47 66.99
## 9 19 3.47 70.46
## 10 19 3.47 73.93
## 11 18 3.28 77.21
## 12 14 2.55 79.76
## 13 14 2.55 82.31
## 14 13 2.37 84.68
## 15 11 2.01 86.69
## 16 11 2.01 88.70
## 17 11 2.01 90.71
## 18 10 1.82 92.53
## 19 8 1.46 93.99
## 20 6 1.09 95.08
## 21 6 1.09 96.17
## 22 6 1.09 97.26
## 23 5 0.91 98.17
## 24 4 0.73 98.90
## 25 3 0.55 99.45
## 26 2 0.36 99.81
## 27 1 0.18 100.00
## [1] "Variables processed: puesto, rubro"
Esta función nos provee una tabla de frecuencias, es decir, la cantidad de veces que aparece cada valor (es decir su frecuencia), el porcentaje que representa, y el porcentaje acumulado de cada valor (si quieren cancherear frente a un/a estadístico/a esta última columna esto se llama frecuencia acumulada relativa).
Para las variables núméricas vamos a ver dos funciones. La primera se llama plot_num()
y la siguiente es profiling_num()
.
# Correr la función plot_num() en kiwi_7
plot_num(kiwi_7)
En estos gráficos lo que vemos es la distribución de las variables numéricas en forma de histogramas. O al menos esa es la intención, porque por la presencia de los outliers no podemos apreciar mucho la distribución de los datos con este tipo de gráficos.
Probemos ahora la función profiling_num()
.
# Usar la función profiling_num() en kiwi_7
profiling_num(kiwi_7)
## variable mean std_dev variation_coef p_01 p_05
## 1 sueldo_bruto 90869.195858 1.041184e+05 1.1458047 121.38 34030.1
## 2 anios_experiencia 10.001825 3.240968e+01 3.2403770 0.00 2.0
## 3 satisfaccion 3.249458 1.030315e+00 0.3170729 1.00 1.0
## 4 dotacion 3292.917883 2.473126e+04 7.5104402 10.00 30.0
## 5 contactos_linkedin 2562.097778 4.724548e+03 1.8440154 0.00 8.9
## p_25 p_50 p_75 p_95 p_99 skewness kurtosis iqr
## 1 55000 73300 102000 192600 290000 14.3985038 276.655621 47000
## 2 4 7 12 20 30 21.5063064 487.351842 8
## 3 3 3 4 5 5 -0.2737854 2.765024 1
## 4 115 300 1100 10000 35070 15.1973173 242.732520 985
## 5 300 700 2500 11275 25000 3.4600918 16.772339 2200
## range_98 range_80
## 1 [121.38, 290000] [40000, 150000]
## 2 [0, 30] [2, 15]
## 3 [1, 5] [2, 5]
## 4 [10, 35069.9999999995] [50.7, 4000]
## 5 [0, 25000] [50, 7000]
Acá tenemos un montón de información:
Lo primero que vemos es el promedio (mean)
y el desvío estándar (std_dev
).
Luego vemos el coeficiente de variación (variation_coef
) que es el resultado de dividir el desvío estándar por el promedio.
Luego vemos el valor en los percentiles 1, 5, 25, 50, 75, 95, 99.
Luego vemos el sesgo (skewness
) que tiene que ver con la simetría de la distribución de los datos y el kurtosis
que a grosso modo indica la presencia de valores extremos.
El rango intercuartil (iqr
) que es la diferencia entre el tercer cuartil menos el primer cuartil. O lo que es lo mismo, el percentil 75 menos el percentil 25.
Después tenemos dos rangos, entre los percentiles 1 y 99, y entre los percentiles 10 y 90.
Es mucha información estadística, ¿no? Pero veamos para qué nos puede servir. Los resultados de profiling_num()
los podemos guardar en una tabla y usarlo para limpiar nuestros datos.
# Crear un objeto con el análisis de profiling_num()
<- profiling_num(kiwi_7)
var_num
# Ver el contenido de var_num
# Apretar Ctrl + Enter var_num
## variable mean std_dev variation_coef p_01 p_05
## 1 sueldo_bruto 90869.195858 1.041184e+05 1.1458047 121.38 34030.1
## 2 anios_experiencia 10.001825 3.240968e+01 3.2403770 0.00 2.0
## 3 satisfaccion 3.249458 1.030315e+00 0.3170729 1.00 1.0
## 4 dotacion 3292.917883 2.473126e+04 7.5104402 10.00 30.0
## 5 contactos_linkedin 2562.097778 4.724548e+03 1.8440154 0.00 8.9
## p_25 p_50 p_75 p_95 p_99 skewness kurtosis iqr
## 1 55000 73300 102000 192600 290000 14.3985038 276.655621 47000
## 2 4 7 12 20 30 21.5063064 487.351842 8
## 3 3 3 4 5 5 -0.2737854 2.765024 1
## 4 115 300 1100 10000 35070 15.1973173 242.732520 985
## 5 300 700 2500 11275 25000 3.4600918 16.772339 2200
## range_98 range_80
## 1 [121.38, 290000] [40000, 150000]
## 2 [0, 30] [2, 15]
## 3 [1, 5] [2, 5]
## 4 [10, 35069.9999999995] [50.7, 4000]
## 5 [0, 25000] [50, 7000]
Ahora tenemos una tabla, un data frame, de la cual podemos usar sus celdas. En particular ahora nos interesan de la fila de sueldo_bruto
las celdas correspondientes a los percentiles 5 y 95 para utilizar en un filtro. Para lograr eso tenemos que seguir la siguiente lógica: nombre_dataframe[fila,columna]
.
# Guardamos el valor de los percentiles 5 y 95 en un objeto cada uno.
<- var_num[1,6] # El valor de la fila 1, columna 6
p05 <- var_num[1,10] # El valor de la fila 1, columna 10
p95
# Veamos el contenido de ambos valores
p05
## [1] 34030.1
p95
## [1] 192600
Ahora podemos usar esos valores como filtros de la variable sueldo_bruto
.
# Filtramos las filas que estén por encima de p05 y por debajo de p95
<- kiwi_7 %>%
kiwi_8 filter(between(sueldo_bruto, # Columna a filtrar
# Umbral mínimo
p05, # Umbral máximo
p95))
# Probemos la función summary() en kiwi_8
summary(kiwi_8)
## sueldo_bruto puesto rubro anios_experiencia
## Min. : 34086 Administrativo: 34 Length:492 Min. : 0.000
## 1st Qu.: 55550 Analista :197 Class :character 1st Qu.: 4.000
## Median : 73300 HRBP : 52 Mode :character Median : 7.000
## Mean : 81748 Responsable :122 Mean : 9.905
## 3rd Qu.: 98125 Jefe : 59 3rd Qu.: 11.000
## Max. :190000 Gerente : 28 Max. :746.000
##
## satisfaccion dotacion contactos_linkedin
## Min. :1.00 Min. : 4.0 Min. : 0
## 1st Qu.:3.00 1st Qu.: 119.2 1st Qu.: 300
## Median :3.00 Median : 300.0 Median : 700
## Mean :3.26 Mean : 2672.4 Mean : 2400
## 3rd Qu.:4.00 3rd Qu.: 1025.0 3rd Qu.: 2400
## Max. :5.00 Max. :400000.0 Max. :30000
## NA's :73 NA's :82
# Corramos la función plot_num() en kiwi_8
plot_num(kiwi_8)
Dijimos que el Análisis Exploratorio de Datos sirve también para explorar intuiciones. Una de ellas está relacionada con la satisfacción, ¿está relacionada con el salario? Veamos cómo podemos responder a ello.
Sabemos que la columna satisfaccion
tiene campos nulos, por lo que tenemos que filtrarlos.
# Filtramos todo lo que no sea un NA de la variable satisfaccion
<- kiwi_8 %>%
kiwi_9 filter(!is.na(satisfaccion)) # El signo ! es el operador lógico NOT
# Probemos hacer un boxplot
ggplot(kiwi_9, aes(x = factor(satisfaccion), y = sueldo_bruto)) +
geom_boxplot()
Pueden probar en este documento cambiando variables, usar otro dataset, ya sea el dataset crudo
o alguno propio. Cuando terminen, corran este documento con el botón de knit
o bien con las teclas Ctrl
+ Shift
+ K
. Eso va a generar un documento que pueden publicar en línea y compartir en sus redes lo que aprendieron.
En los resultados que publicamos de la Encuesta KIWI de Sueldos de RH pueden ver cómo utilizamos todas estas técnicas para limpiar el archivo crudo
que usamos en esta sesión y que pueden replicar por su cuenta.
Aprovechen el contenido de nuestro Google Drive y de nuestro repositorio de GitHub. Particularmente busquen las sesiones relacionadas con dplyr, ggplot2, y forcats que son complementos excelentes de este encuentro.
Súmense a nuestro canal de Slack y participen haciendo consultas y compartiendo contenido de valor.