library(dplyr)
library(tidyverse)
library(pacman)
library(readr)
library(ggplot2)
library(plotly)
library(readr)
library(VIM)
library(reshape2)
Grupo_1 <- read_csv("Grupo_1.csv")
En la base de datos hay pocos datos faltantes; hay 67 datos
faltantes en total. Adicional, hay grandes inconsistencias en las edades
de las personas, pues mencionan tener más años de experiencia que la
edad que tienen. Además, hay personas, por ejemplo, que tienen 22 años
con 11 años de experiencia.
Como se observaron grandes inconsistencias en las edades y los años
de experiencia, se graficó un scatterplot para visualizar mejor en dónde
se encuentran las inconsistencias.
vis_inconsistencias <- Grupo_1$Edad > Grupo_1$Experiencia
p <- ggplot(Grupo_1, aes(x = Edad, y = Experiencia)) +
geom_point(alpha = 0.6) +
geom_point(aes(color = vis_inconsistencias), size = 2) +
scale_color_manual(values = c("FALSE" = "red", "TRUE" = "blue")) +
labs(x = "Edad (años)", y = "Experiencia (años)", title = "Edad vs Experiencia") +
theme_minimal()
ggplotly(p)
Al observar estas inconsistencias de la data, se eliminarán las
filas que tengan mayor experiencia que edad
Grupo_1.4 <- Grupo_1[!(Grupo_1$Experiencia >= Grupo_1$Edad &
is.na(Grupo_1$Experiencia) == FALSE &
is.na(Grupo_1$Edad) == FALSE), ]
Igualmente se eliminó aquellos que lleven trabajando desde antes de
los 13 años, pues la edad en Puerto Rico para trabajar es desde los 14
(Ley Núm. 230 de 12 de mayo de 1942, según enmendada). Se puso desde 13
por el caso de que hayan habido personas trabajando desde los 13 por
razones desconocidas.
Grupo_1.4 <- Grupo_1.4[!((Grupo_1.4$Edad - Grupo_1.4$Experiencia) < 13 &
is.na(Grupo_1.4$Experiencia) == FALSE &
is.na(Grupo_1.4$Edad) == FALSE), ]
Observar la distribución de la data ya habiendo eliminado la data
imposible (no es lógica)
hist_Salario2 <- ggplot(Grupo_1.4, aes(x = Salario)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "skyblue", color = "white", alpha = 0.7) +
labs(title = "Histograma de Salario", x = "Salario",) +
theme_minimal()
ggplotly(hist_Salario2)
Para los datos faltantes de Experiencia, se corroborará si se puede
imputar con regresión lineal con la edad, pues son variables altamente
relacionadas.
Reg_Exp <- lm(Experiencia ~ Edad, data = Grupo_1.4)
summary(Reg_Exp)
##
## Call:
## lm(formula = Experiencia ~ Edad, data = Grupo_1.4)
##
## Residuals:
## Min 1Q Median 3Q Max
## -22.919 -7.831 -1.227 9.251 20.307
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.3790 5.9031 0.064 0.94904
## Edad 0.3522 0.1262 2.791 0.00722 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 10.91 on 55 degrees of freedom
## (13 observations deleted due to missingness)
## Multiple R-squared: 0.124, Adjusted R-squared: 0.1081
## F-statistic: 7.788 on 1 and 55 DF, p-value: 0.007216
Al no existir una relación significativa entre las variables, se
observará la distribución de la data de Experiencia para tomar una
decisión para imputar los datos faltantes:
hist_Exp <- ggplot(Grupo_1.4, aes(x = Experiencia)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "skyblue", color = "white", alpha = 0.7) +
labs(title = "Histograma de Experiencia", x = "Experiencia",) +
theme_minimal()
ggplotly(hist_Exp)
Para los datos de la Ciudad, se estará utilizando la imputación con
la moda debido a que es una variable categórica:
Grupo_1.4$Ciudad[is.na(Grupo_1.4$Ciudad) | Grupo_1.4$Ciudad == ""] <-
mode(Grupo_1.4$Ciudad)
Discretización de los datos
Transformación de variables categóricas
# Verificar variables categóricas
str(Grupo_1.4)
## tibble [70 × 12] (S3: tbl_df/tbl/data.frame)
## $ ID : num [1:70] 1 3 4 5 6 7 8 9 12 13 ...
## $ Edad : num [1:70] 49 22 26 40 26 42 24 62 41 47 ...
## $ Salario : num [1:70] 47164 76886 69046 51575 55348 ...
## $ Experiencia : num [1:70] 8 1 8 4 3 22 1 15 24 6 ...
## $ Ciudad : chr [1:70] "San Juan" "Caguas" "character" "Ponce" ...
## $ Nivel_Educativo : chr [1:70] "Secundaria" "Secundaria" "Primaria" "Universitario" ...
## $ Horas_Trabajo_Semana: num [1:70] 30 46 31 56 57 55 22 50 42 36 ...
## $ Estado_Civil : chr [1:70] "Soltero" "Soltero" "Divorciado" "Casado" ...
## $ Sector_Laboral : chr [1:70] "Independiente" "Público" "Independiente" "Privado" ...
## $ Cantidad_Hijos : num [1:70] 4 4 0 3 5 4 2 2 3 4 ...
## $ Propietario_Vivienda: chr [1:70] "Sí" "No" "Sí" "Sí" ...
## $ Rango_Salario : chr [1:70] "Medio" "Alto" "Alto" "Medio" ...
# Variable Ciudad
# Decisión de convertir a factor nominal puesto que es una etiqueta geográfica sin orden alguno
Grupo_1.4$Ciudad <- as.factor(Grupo_1.4$Ciudad)
levels(Grupo_1.4$Ciudad)
## [1] "Bayamón" "Caguas" "character" "Ponce" "San Juan"
# Variable Nivel educativo
# Decisión de convertir a factor ordenado pues tiene un orden natural
Grupo_1.4$Nivel_Educativo <- factor(Grupo_1.4$Nivel_Educativo, levels = c("Primaria", "Secundaria", "Universitario"),
ordered = TRUE)
levels(Grupo_1.4$Nivel_Educativo)
## [1] "Primaria" "Secundaria" "Universitario"
# Variable de estado civil
# Decisión de convertir a factor nominal puesto que no hay un orden establecido entre estados civiles
Grupo_1.4$Estado_Civil <- as.factor(Grupo_1.4$Estado_Civil)
levels(Grupo_1.4$Estado_Civil)
## [1] "Casado" "character" "Divorciado" "Soltero"
# Variable de sector laboral
# Decisión de convertir a factor nominal pues no hay un orden establecido entre los sectores
Grupo_1.4$Sector_Laboral <- as.factor(Grupo_1.4$Sector_Laboral)
levels(Grupo_1.4$Sector_Laboral)
## [1] "character" "Independiente" "Privado" "Público"
# Variable de propietario de vivienda
# Convertir a factor binario, o variable dummy, para facilitar los modelos de regresión
Grupo_1.4$Propietario_Vivienda_Num <- ifelse(Grupo_1.4$Propietario_Vivienda == "Sí", 1, 0)
# Variable de rango de salario
# Convertir a factor ordenado, pues hay un orden natural en el ingreso
Grupo_1.4$Rango_Salario <- factor(Grupo_1.4$Rango_Salario,
levels = c("Bajo", "Medio", "Alto"),
ordered = TRUE)
levels(Grupo_1.4$Rango_Salario)
## [1] "Bajo" "Medio" "Alto"
Discretización de variables numéricas
# Variable de edad
# Decisión de dividir en 4 rangos de edad laboral para facilitar comparaciones entre generaciones
Grupo_1.4$Grupo_Edad <- cut(Grupo_1.4$Edad,
breaks = c(0, 25, 35, 50, 100),
labels = c("Joven (18-25)",
"Adulto Joven (26-35)",
"Adulto (36-50)",
"Senior (51+)"),
right = TRUE)
table(Grupo_1.4$Grupo_Edad)
##
## Joven (18-25) Adulto Joven (26-35) Adulto (36-50)
## 5 8 31
## Senior (51+)
## 26
# Variable de Horas de trabajo en semana
# Decisión de dividir en tiempo parcial, normal y tiempo extra para establecer los estándares de labor
Grupo_1.4$Carga_Laboral <- cut(Grupo_1.4$Horas_Trabajo_Semana,
breaks = c(0, 35, 45, 168),
labels = c("Tiempo Parcial (<35h)",
"Tiempo Normal (35-45h)",
"Tiempo Extra (>45h)"),
right = TRUE)
table(Grupo_1.4$Carga_Laboral)
##
## Tiempo Parcial (<35h) Tiempo Normal (35-45h) Tiempo Extra (>45h)
## 22 25 23
str(Grupo_1.4)
## tibble [70 × 15] (S3: tbl_df/tbl/data.frame)
## $ ID : num [1:70] 1 3 4 5 6 7 8 9 12 13 ...
## $ Edad : num [1:70] 49 22 26 40 26 42 24 62 41 47 ...
## $ Salario : num [1:70] 47164 76886 69046 51575 55348 ...
## $ Experiencia : num [1:70] 8 1 8 4 3 22 1 15 24 6 ...
## $ Ciudad : Factor w/ 5 levels "Bayamón","Caguas",..: 5 2 3 4 4 4 1 2 5 2 ...
## $ Nivel_Educativo : Ord.factor w/ 3 levels "Primaria"<"Secundaria"<..: 2 2 1 3 1 2 1 1 2 3 ...
## $ Horas_Trabajo_Semana : num [1:70] 30 46 31 56 57 55 22 50 42 36 ...
## $ Estado_Civil : Factor w/ 4 levels "Casado","character",..: 4 4 3 1 4 3 4 1 1 1 ...
## $ Sector_Laboral : Factor w/ 4 levels "character","Independiente",..: 2 4 2 3 2 2 3 3 1 4 ...
## $ Cantidad_Hijos : num [1:70] 4 4 0 3 5 4 2 2 3 4 ...
## $ Propietario_Vivienda : chr [1:70] "Sí" "No" "Sí" "Sí" ...
## $ Rango_Salario : Ord.factor w/ 3 levels "Bajo"<"Medio"<..: 2 3 3 2 2 2 3 1 3 3 ...
## $ Propietario_Vivienda_Num: num [1:70] 1 0 1 1 1 0 1 1 0 1 ...
## $ Grupo_Edad : Factor w/ 4 levels "Joven (18-25)",..: 3 1 2 3 2 3 1 4 3 3 ...
## $ Carga_Laboral : Factor w/ 3 levels "Tiempo Parcial (<35h)",..: 1 3 1 3 3 3 1 3 2 2 ...
summary(Grupo_1.4)
## ID Edad Salario Experiencia
## Min. : 1.00 Min. :22.00 Min. :20069 Min. : 0.00
## 1st Qu.: 26.25 1st Qu.:38.00 1st Qu.:37192 1st Qu.: 8.00
## Median : 51.00 Median :47.00 Median :49879 Median :15.00
## Mean : 50.07 Mean :45.16 Mean :49749 Mean :16.10
## 3rd Qu.: 74.75 3rd Qu.:52.75 3rd Qu.:66126 3rd Qu.:22.75
## Max. :100.00 Max. :64.00 Max. :79793 Max. :39.00
## Ciudad Nivel_Educativo Horas_Trabajo_Semana Estado_Civil
## Bayamón :21 Primaria :21 Min. :21.00 Casado :26
## Caguas :23 Secundaria :20 1st Qu.:31.25 character : 3
## character: 2 Universitario:28 Median :42.00 Divorciado:22
## Ponce :13 NA's : 1 Mean :40.91 Soltero :19
## San Juan :11 3rd Qu.:50.00
## Max. :60.00
## Sector_Laboral Cantidad_Hijos Propietario_Vivienda Rango_Salario
## character : 4 Min. :0.000 Length:70 Bajo :13
## Independiente:26 1st Qu.:1.000 Class :character Medio:35
## Privado :25 Median :2.500 Mode :character Alto :20
## Público :15 Mean :2.514 NA's : 2
## 3rd Qu.:4.000
## Max. :5.000
## Propietario_Vivienda_Num Grupo_Edad
## Min. :0.0000 Joven (18-25) : 5
## 1st Qu.:0.0000 Adulto Joven (26-35): 8
## Median :1.0000 Adulto (36-50) :31
## Mean :0.5857 Senior (51+) :26
## 3rd Qu.:1.0000
## Max. :1.0000
## Carga_Laboral
## Tiempo Parcial (<35h) :22
## Tiempo Normal (35-45h):25
## Tiempo Extra (>45h) :23
##
##
##
Visualización avanzada
Mapa de calor interactivo
# Solo variables numéricas
variables_numericas <- Grupo_1.4[, c("Edad", "Salario", "Experiencia", "Horas_Trabajo_Semana", "Cantidad_Hijos")]
# Matriz de correlación
matriz_cor <- round(cor(variables_numericas, use = "complete.obs"), 2)
# Convertir a formato largo
matriz_melted <- melt(matriz_cor)
# Heatmap
heatmap_plot <- plot_ly(
x = colnames(matriz_cor),
y = rownames(matriz_cor),
z = matriz_cor,
type = "heatmap",
colorscale = list(
c(0, "red"),
c(0.5, "white"),
c(1, "blue")
))
heatmap_plot
Gráfico de barras interactivo
# Calcular promedio de hijos por rango de salario
datos_barras <- aggregate(Cantidad_Hijos ~ Rango_Salario,
data = Grupo_1.4,
FUN = mean)
datos_barras$Cantidad_Hijos <- round(datos_barras$Cantidad_Hijos, 2)
#Gráfico de barras
barras_gg <- ggplot(datos_barras,
aes(x = Rango_Salario,
y = Cantidad_Hijos,
fill = Rango_Salario,
text = paste("Rango:", Rango_Salario,
"<br>Promedio Hijos:", Cantidad_Hijos))) +
geom_bar(stat = "identity", width = 0.6)
barras_gg

ggplotly(barras_gg, tooltip ="text")
# Se observa que las personas con salario medio son las personas que tienen más hijos. Aunque sea con puntos decimales, se puede entender que tienen más hijos que los otros rangos de salario.
dispersion_plot <- plot_ly(
data = Grupo_1.4,
x = ~Experiencia,
y = ~Salario,
type = "scatter",
mode = "markers",
color = ~Rango_Salario,
colors = c("Bajo" = "magenta",
"Medio" = "blue",
"Alto" = "green"),
marker = list(size = 9, opacity = 0.7))
dispersion_plot <- dispersion_plot %>%
add_lines(x = ~Experiencia, y = ~fitted(lm(Salario ~ Experiencia, data = Grupo_1.4)), line = list(color = "darkblue", width = 2, dash = "dash"), name = "Tendencia", hoverinfo = "none")
dispersion_plot
Se observa que, aunque es altamente común que el salario esté
altamente relacionado con los años, no existe esa relación en estas
variables.