FORM BANNER
La empresa FORM, actualmente una empresa líder en la industria del cartón, se enfrenta con desafíos significativos como lo es las dos situaciones problemas que nos presenta. 1. Retención de clientes 2. Predicción de demandas futuras. El objetivo de este proyecto es poder realizar técnicas avanzadas de análisis de datos para poder anticipar y entender las necesidades del mercado y de los clientes, así mejorando la competitividad del Socio Formador. La empresa podrá optimizar su producción y gestión de inventarios debido a que con el análisis predictivo se estimará las ventas del próximo mes, también en el área de retención, buscaremos desarrollar estrategias para mejorar la lealtad, satisfacción y compromiso por parte de los clientes.
1.- Documentar el Proceso de Limpieza de Datos: Realizar un análisis detallado de cada etapa de la limpieza de datos, detallando desde la identificación de valores nulos hasta las transformaciones más complejas y específicas aplicadas en para mejorar la calidad de los datos.
2.- Desarrollo y Evaluación de Modelos de Inteligencia Artificial: Documentar la construcción y evaluación de varios modelos predictivos y de clasificación para datos estructurados y no estructurados.
3.- Comparativa entre los Modelos: Realizar un análisis comparativo de los modelos para determinar cuál es el más eficaz y preciso para abordar los desafíos específicos de el Socio Formador, como la retención de clientes y la predicción de ventas.
4.- Proporcionar Recomendaciones Estratégicas: Basado en los análisis, ofrecer recomendaciones que FORM pueda implementar para mejorar la retención de clientes y optimizar la planificación de producción.
Se realizó una transformación para limpiar la base de datos de la empresa FORM, para poder analizar factores internos de la empresa que pueden influir en la retención de clientes y la optimización operativa. Los variables que se muestran en la base de datos son datos demográficos, roles de empleados y sueldos.
Se identificaron valores nulos en múltiples columnas clave como Fecha de nacimiento, Género, Puesto, Departamento, Sueldo Diario, Municipio, Estado, Estado Civil, y Dirección. Esta identificación es crucial para preparar los datos para análisis predictivos, asegurando que la calidad de los datos no comprometa los modelos futuros.
Los valores nulos se manejan con estrategias específicas para minimizar su impacto en los análisis:
Estado: Sustitución utilizando la moda del municipio correspondiente, una técnica que preserva la estructura geográfica y puede ser relevante para entender patrones regionales de demanda. Municipio y Estado: Sustitución directa cuando falta información de estado, utilizando nombres comunes como ‘guadalupe’ y ‘nuevo leon’ que pueden ser centros de actividad significativos para la empresa. Sueldo Diario: Imputación basada en el rol ocupacional, lo que podría ser indicativo de la estructura de costos y cómo esto afecta la retención y satisfacción de clientes.
Categorización de molestias y sentimientos: Transformación de textos libres a categorías, lo que nos ayuda en el análisis de sentimiento y clima organizacional, factores importantes para la retención de talento e indirectamente, la satisfacción del cliente. Conversión y limpieza de tipos de datos: Asegura que las edades y otros datos numéricos estén correctamente formateados para análisis.
Las decisiones de limpieza están guiadas por reglas de negocio que reflejan la estructura y necesidades operativas de FORM, como la asignación de sueldos basada en roles específicos, y la imputación geográfica que podría reflejar la distribución de la cadena de suministro o centros de servicio.
El resultado es un conjunto de datos limpios, organizados y listos para ser utilizados en modelos predictivos que podrían ayudar a FORM a mejorar la retención de clientes y la precisión en la predicción de demanda. Los datos están en un formato CSV, facilitando su uso en herramientas analíticas y de modelado.
Estos ajustes específicos en la limpieza de los datos están diseñados para alinear los datos con las estrategias de negocio y operativas de FORM, asegurando que la base de datos transformada sea un recurso valioso para enfrentar los desafíos actuales de la empresa.
###Series de Tiempo
Actualmente, FORM enfrenta la necesidad y la gran oportunidad de optimizar su cadena de producción en función de la demanda de sus diversos productos. Es crucial generar predicciones precisas de la demanda para que FORM pueda aumentar la eficiencia en toda su cadena de producción, reducir costos y mejorar el servicio al cliente. Para lograr esto, se desarrollará un modelo de series temporales utilizando técnicas de modelado como SARIMA, con el fin de predecir las ventas futuras basándose en los datos históricos de ventas de los últimos años.
Se escogió un modelo SARIMA debido a que la naturaleza de los datos permite acoplarse muy bien con modelos de series de tiempo y dicho modelo logra capturar los componentes estacionales de la serie.
Se utilizó la base de datos VENTAS_FORM_FJ_2024 proporcionada por la empresa, la cual incluye un registro detallado de sus ventas en el periodo 2021-2023.
library(readr)
library(imputeTS)
library(lubridate)
library(xts)
library(zoo)
library(foreign)
library(modelr)
library(dplyr)
library(tidyverse)
library(ggplot2)
library(broom)
library(ISLR)
library(caret)
library(e1071)
library(class)
library(ROCR)
library(pROC)
library(lmtest)
library(caTools)
library(rpart)
library(rpart.plot)
library(psych)
library(ggpubr)
library(reshape)
library(Metrics)
library(mlbench)
library(rsample)
library(cluster)
library(factoextra)
library(gridExtra)
library(modeest)
library(tibble)
library(randomForest)
library(irr)
library(corrplot)
library(vcd)
library(car)
library(tseries)
library(stats)
library(forecast)
library(astsa)
library(wordcloud)
library(tidytext)
library(AER)
library(vars)
library(dynlm)
library(mFilter)
library(TSstudio)
library(sarima)
library(readxl)
library(patchwork)
library(heatmaply)
library(readtext)
library(syuzhet)
library(RColorBrewer)
library(tm)
library(MASS)
library(party)
library(gmodels)
library(knitr)
library(purrr)
library(reshape2)
library(tmap)
library(sf)
library(pdp)
library(vip)
library(xgboost)
library(forcats)
library(viridis)
library(scales)
library(neuralnet)
library(DataExplorer)
library(recommenderlab)
library(arules)
library(arulesViz)
library(MLmetrics)
library(janeaustenr)
<- read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/form/VENTAS_FORM_B.csv") ventas_nv
## Rows: 37 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Mes
## dbl (5): Año, Total Carton, Total Retornable, Servicios, Ventas Totales
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(ventas_nv)
## # A tibble: 6 × 6
## Mes Año `Total Carton` `Total Retornable` Servicios `Ventas Totales`
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Enero 2021 283978 1137 127 285242
## 2 Febrero 2021 333858 1405 0 335263
## 3 Marzo 2021 274885 5114 58 280057
## 4 Abril 2021 266280 1494 0 267774
## 5 Mayo 2021 179193 4380 4 183577
## 6 Junio 2021 140761 1980 0 142741
<- colSums(is.na(ventas_nv))
na_count na_count
## Mes Año Total Carton Total Retornable
## 1 1 1 1
## Servicios Ventas Totales
## 1 1
# Renombra columnas
names(ventas_nv)[names(ventas_nv) == "Ventas Totales"] <- "Ventas_totales"
names(ventas_nv)[names(ventas_nv) == "Total Carton"] <- "Total_carton"
names(ventas_nv)[names(ventas_nv) == "Total Retornable"] <- "Total_retornable"
names(ventas_nv)
## [1] "Mes" "Año" "Total_carton" "Total_retornable"
## [5] "Servicios" "Ventas_totales"
Sys.setlocale("LC_TIME", "es_ES.UTF-8")
## [1] "es_ES.UTF-8"
<- na.omit(ventas_nv[, c("Año", "Mes", "Ventas_totales", "Total_carton", "Total_retornable", "Servicios")])
ventas_nv $Fecha <- as.Date(paste(ventas_nv$Año, ventas_nv$Mes, "01"), format = "%Y %B %d")
ventas_nv<- ts(ventas_nv$Ventas_totales, start = c(as.numeric(format(min(ventas_nv$Fecha), "%Y")), as.numeric(format(min(ventas_nv$Fecha), "%m"))), frequency = 12)
ventas_t ts_plot(ventas_t)
<- ts(ventas_nv$Total_carton, start = c(year(min(ventas_nv$Fecha)), month(min(ventas_nv$Fecha))), frequency = 12)
Carton
ts_plot(Carton)
<- ts(ventas_nv$Total_retornable, start = c(year(min(ventas_nv$Fecha)), month(min(ventas_nv$Fecha))), frequency = 12)
Retornable ts_plot(Retornable)
<- ts(ventas_nv$Servicios, start = c(year(min(ventas_nv$Fecha)), month(min(ventas_nv$Fecha))), frequency = 12)
servicio ts_plot(servicio)
adf.test(ventas_t)
##
## Augmented Dickey-Fuller Test
##
## data: ventas_t
## Dickey-Fuller = -4.7058, Lag order = 3, p-value = 0.01
## alternative hypothesis: stationary
Con la prueba de ADF podemos observar que la serie de tiempo de las ventas es estacionaria, es decir, no muestra tendencias a lo largo del tiempo y es ideal para modelar un ARIMA que logre capturar los componentes estacionales de la serie de tiempo
# Graficar la ACF y PACF
par(mfrow = c(1, 2))
acf(ventas_t, main = "ACF de Ventas Totales")
pacf(ventas_t, main = "PACF de Ventas Totales")
No se aprecia aurocorrelación serial.
# Ajustar el modelo ARMA con p=1 y q=1
<- auto.arima(ventas_t, seasonal = TRUE)
sarima summary(sarima)
## Series: ventas_t
## ARIMA(1,0,0) with non-zero mean
##
## Coefficients:
## ar1 mean
## 0.7659 175677.34
## s.e. 0.1114 26036.11
##
## sigma^2 = 1.648e+09: log likelihood = -432.51
## AIC=871.01 AICc=871.76 BIC=875.76
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set -3422.67 39453.7 31583.27 -7.366077 20.37777 0.4829533 -0.1033301
El modelo ARMA(1,1) ajustado a la serie de tiempo de ventas muestra que el componente autorregresivo es altamente significativo, indicando que las ventas actuales dependen fuertemente de las ventas pasadas. Sin embargo, el componente de media móvil no es significativo. La significancia del intercepto sugiere un término constante relevante. A pesar de la variabilidad en los residuos, este modelo proporciona una base sólida para capturar las dinámicas de las ventas.
Modelo Arma
<-sarima$residuals
sarima_residualsBox.test(sarima_residuals,lag=1,type="Ljung-Box")
##
## Box-Ljung test
##
## data: sarima_residuals
## X-squared = 0.41732, df = 1, p-value = 0.5183
El valor de p obtenido en la prueba de Box-Ljung (0,88) es mayor que el valor de p máximo comúnmente utilizado que es 0,05. Esto significa que no se encontró evidencia significativa de autocorrelación en los residuos, ya que el valor p es mayor que 0,05, lo que respalda la validez del modelo en términos de autocorrelación.
#Testing residuals
suppressWarnings({
$residuals <- na.omit(sarima$residuals)
sarimaadf.test(sarima$residuals)
})
##
## Augmented Dickey-Fuller Test
##
## data: sarima$residuals
## Dickey-Fuller = -5.1649, Lag order = 3, p-value = 0.01
## alternative hypothesis: stationary
El valor de p de 0,01, inferior al umbral de 0,05, indica una fuerte evidencia contra la hipótesis nula de no estacionariedad. Esto significa que es poco probable que los residuos sean no estacionarios.
# Realizar predicciones para los próximos 4 meses
<- forecast(sarima, h = 7)
forecast_sarima
# Graficar las predicciones
autoplot(forecast_sarima) +
ggtitle("Predicciones de Ventas Totales") +
xlab("Tiempo") +
ylab("Ventas Totales")
forecast_sarima
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 2024 143252.7 91224.91 195280.5 63683.04 222822.4
## Feb 2024 150844.5 85311.21 216377.8 50619.98 251069.0
## Mar 2024 156658.8 84368.51 228949.1 46100.34 267217.2
## Apr 2024 161111.7 85137.26 237086.2 44918.81 277304.6
## May 2024 164522.1 86467.53 242576.6 45147.96 283896.2
## Jun 2024 167133.9 87884.73 246383.1 45932.74 288335.1
## Jul 2024 169134.3 89192.63 249075.9 46874.10 291394.4
<- length(ventas_t)
n <- head(ventas_t, n - 6)
ventas_t_2<- auto.arima(ventas_t_2, seasonal = TRUE)
sarima2 <- forecast(sarima2, h = 6)
forecast_sarima_2 <- tail(ventas_t, 6)
ventas_t_3
# Valores predichos
<- forecast_sarima_2$mean
predicted_values
# Valores reales (ajusta el índice según tu serie temporal)
= ventas_t_3
actual_values
# Calcular el RMSE
<- sqrt(mean((actual_values - predicted_values)^2))
rmse print(paste("RMSE = ", rmse))
## [1] "RMSE = 46267.1106666248"
El modelo SARIMA ajustado a la serie de tiempo de ventas ha sido utilizado para realizar predicciones para los próximos 12 meses. Las predicciones muestran la tendencia esperada de las ventas totales, proporcionando una herramienta valiosa para la planificación y la toma de decisiones en la optimización de la cadena de producción. La significancia del componente autorregresivo sugiere que las ventas pasadas tienen un impacto considerable en las ventas futuras, mientras que el componente de media móvil no resultó ser significativo en este modelo. Las pruebas de diagnóstico respaldan la validez del modelo, indicando que no hay autocorrelación significativa en los residuos y que los residuos son estacionarios. Se sugiere complementar el modelo con más datos históricos de la compañía, así como de variables externas que impactan a las ventas de FORM. Sin embargo, indicadores como el RMSE muestran niveles relativamente de confianza, con valores de 46267, por lo cual es importante seguir mejorando el modelo.
Este modelo está dedicado al análisis de diferentes modelos de regresión múltiple, aplicados a la Situación Problema 2: Predicción de Demanda. Utiliza tanto los datos históricos de ventas como las variables relevantes para la producción y venta de autopartes de FORM.
Los modelos de regresión múltiple son una técnica valiosa en el análisis de datos, ofreciendo la ventaja de identificar la relación entre múltiples variables predictoras y la variable de interés. Esto los hace especialmente útiles para anticipar la demanda de productos y optimizar los procesos de producción.
Como se mencionó anteriormente, el análisis para abordar la Situación Problema 2 involucra tres conjuntos de datos principales:
Base de Datos de Ventas Desglosadas de FORM: Esta base proporciona un overview de ventas diarias con registros detallados que incluyen quién compró el producto, el cliente, el producto específico, la categoría del producto, la cantidad vendida, el estatus de la venta, entre otros datos que reflejan las transacciones individuales.
Base de Datos de Expansión: Este conjunto de datos ofrece una matriz más expandida, de la cual se crean columnas por cliente para medir si el impacto de cada cliente se puede predecir independientemente. Esto permite analizar patrones específicos y comportamientos de compra individualizados.
Base de Datos de Factores Externos: Utilizando fuentes externas, esta base de datos divide el conjunto de datos inicial en diferentes variables como categoría de productos, tipo de vehículos correspondientes y fuentes externas de industrias. Esto se hace para tratar de medir correlaciones entre estos factores y la demanda de productos, mejorando la precisión de las predicciones.
Estos tres conjuntos de datos juntos nos permiten tener una visión integral de los factores que influyen en la demanda de productos y desarrollar modelos predictivos más precisos y robustos.
<- read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/forecast/Datos_FORM_Ventas_FJ2024.csv")
form_ventas <- read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/forecast/FORM_Factores.csv")
form_factores <- read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/forecast/FORM_Modelado.csv")
form_expandido <- read_xlsx("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/industry_autos_mx/exportacion_vehiculos.xlsx") industria_autos
# 1. Expansión de la fecha
<- form_ventas %>%
form_ventas mutate(Fecha = ymd(Fecha),
= year(Fecha),
Año Mes = month(Fecha),
Dia = day(Fecha),
= week(Fecha),
Semana_Año Semana_Mes = ceiling(day(Fecha) / 7),
Dia_Semana = wday(Fecha, label = TRUE),
Dia_Habil = ifelse(Dia_Semana %in% c("Sat", "Sun"), 0, 1))
# 2. Estacionalidad Anual
<- form_ventas %>%
estacionalidad_anual group_by(Año, Semana_Año) %>%
summarise(Cantidad_Semanal = sum(Cantidad, na.rm = TRUE)) %>%
group_by(Semana_Año) %>%
summarise(Promedio_Cantidad = mean(Cantidad_Semanal, na.rm = TRUE)) %>%
mutate(Estacionalidad_Annual = ntile(Promedio_Cantidad, 10))
## `summarise()` has grouped output by 'Año'. You can override using the `.groups`
## argument.
<- form_ventas %>%
form_ventas left_join(estacionalidad_anual, by = "Semana_Año")
# 3. Estacionalidad Mensual
<- form_ventas %>%
estacionalidad_mensual group_by(Año, Mes, Semana_Mes) %>%
summarise(Cantidad_Semanal_Mensual = sum(Cantidad, na.rm = TRUE)) %>%
group_by(Mes, Semana_Mes) %>%
summarise(Promedio_Cantidad_Mensual = mean(Cantidad_Semanal_Mensual, na.rm = TRUE)) %>%
mutate(Estacionalidad_Mensual = ntile(Promedio_Cantidad_Mensual, 10))
## `summarise()` has grouped output by 'Año', 'Mes'. You can override using the
## `.groups` argument.
## `summarise()` has grouped output by 'Mes'. You can override using the `.groups`
## argument.
<- form_ventas %>%
form_ventas left_join(estacionalidad_mensual, by = c("Mes", "Semana_Mes"))
# 4. Registros Semanales
<- form_ventas %>%
form_ventas_semanal group_by(Semana_Año, Año, Mes, Semana_Mes, Cliente, Producto, `Categoría de producto`, Tipo, Promedio_Cantidad, Estacionalidad_Annual, Promedio_Cantidad_Mensual, Estacionalidad_Mensual) %>%
summarise(Cantidad_Semanal = sum(Cantidad, na.rm = TRUE),
.groups = 'drop')
# Verificación del dataframe resultante
head(form_ventas_semanal)
## # A tibble: 6 × 13
## Semana_Año Año Mes Semana_Mes Cliente Producto Categoría de product…¹
## <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
## 1 1 2021 1 1 Denso dunnage… retornable producto t…
## 2 1 2021 1 1 Grupo ABC car8180… carton kit carton
## 3 1 2021 1 1 Grupo ABC car8180… carton kit carton
## 4 1 2021 1 1 Grupo Antol… 1800037… carton producto termi…
## 5 1 2021 1 1 Grupo Antol… 1800222… carton producto comer…
## 6 1 2021 1 1 Grupo Antol… 1800223… carton producto comer…
## # ℹ abbreviated name: ¹`Categoría de producto`
## # ℹ 6 more variables: Tipo <chr>, Promedio_Cantidad <dbl>,
## # Estacionalidad_Annual <int>, Promedio_Cantidad_Mensual <dbl>,
## # Estacionalidad_Mensual <int>, Cantidad_Semanal <dbl>
# Función para limpiar los nombres de las columnas
<- function(df) {
clean_names names(df) <- tolower(gsub(" ", "_", names(df)))
return(df)
}
<- clean_names(industria_autos)
industria_autos
# Primero, convertir los nombres de los meses a números
<- function(mes) {
meses_a_numeros <- c("enero" = 1, "febrero" = 2, "marzo" = 3, "abril" = 4, "mayo" = 5, "junio" = 6,
meses "julio" = 7, "agosto" = 8, "septiembre" = 9, "octubre" = 10, "noviembre" = 11, "diciembre" = 12)
return(meses[tolower(mes)])
}
# Aplicar la conversión al dataframe
<- industria_autos %>%
industria_autos mutate(mes = sapply(mes, meses_a_numeros))
# Agrupar por año, mes y segmento, y sumar la columna cantidad
<- industria_autos %>%
industria_autos_segmento group_by(año, mes, segmento) %>%
summarise(cantidad_total_segmento = sum(cantidad, na.rm = TRUE)) %>%
ungroup() %>%
pivot_wider(names_from = segmento, values_from = cantidad_total_segmento, values_fill = list(cantidad_total_segmento = 0))
## `summarise()` has grouped output by 'año', 'mes'. You can override using the
## `.groups` argument.
# Agrupar por año, mes y marca, y sumar la columna cantidad
<- industria_autos %>%
industria_autos_marca group_by(año, mes, marca) %>%
summarise(cantidad_total_marca = sum(cantidad, na.rm = TRUE)) %>%
ungroup() %>%
pivot_wider(names_from = marca, values_from = cantidad_total_marca, values_fill = list(cantidad_total_marca = 0))
## `summarise()` has grouped output by 'año', 'mes'. You can override using the
## `.groups` argument.
# Agrupar por año y mes, y sumar la columna cantidad para el total general
<- industria_autos %>%
industria_autos_monthly group_by(año, mes) %>%
summarise(cantidad_total = sum(cantidad, na.rm = TRUE)) %>%
ungroup()
## `summarise()` has grouped output by 'año'. You can override using the `.groups`
## argument.
# Crear un dataframe final combinando las tres tablas
<- industria_autos_monthly %>%
industria_autos_combined left_join(industria_autos_segmento, by = c("año", "mes")) %>%
left_join(industria_autos_marca, by = c("año", "mes"))
# Función para ajustar un modelo ARIMA y predecir los próximos 12 meses
<- function(columna) {
predecir_columna <- ts(industria_autos_combined[[columna]], start = c(min(industria_autos_combined$año), min(industria_autos_combined$mes)), frequency = 12)
ts_data <- auto.arima(ts_data)
fit <- forecast(fit, h = 12)
forecasted_values return(forecasted_values$mean)
}
# Realizar la predicción para todas las columnas excepto año y mes
<- lapply(names(industria_autos_combined)[-c(1, 2)], predecir_columna)
predicciones
# Crear un dataframe con las predicciones y las fechas correspondientes
<- rep(2023:2024, each = 12)[8:19]
predicted_years <- rep(1:12, times = 2)[8:19]
predicted_months <- data.frame(
predictions_df = predicted_years,
año mes = predicted_months
)
# Añadir las predicciones al dataframe
for (i in seq_along(predicciones)) {
names(industria_autos_combined)[-c(1, 2)][i]]] <- predicciones[[i]]
predictions_df[[
}
# Combinar los datos históricos seleccionados con las predicciones
<- bind_rows(
industria_autos_prediction
industria_autos_combined,
predictions_df
)
# Mostrar el dataframe final
tail(industria_autos_prediction)
## # A tibble: 6 × 25
## año mes cantidad_total Compactos `De Lujo` Minivans `Pick Ups` `SUV's`
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2024 2 256108. 35767. 6282. -7.66e-55 74369. 153144.
## 2 2024 3 270597. 40417. 6266. -2.34e-54 79226. 152941.
## 3 2024 4 266061. 35084. 6255. -2.32e-54 76498. 153732.
## 4 2024 5 272224. 38321. 6248. -6.11e-55 79903. 154810.
## 5 2024 6 272803. 39682. 6245. -1.04e-54 78665. 154707.
## 6 2024 7 268487. 37628. 6245. -8.12e-55 75398. 156120.
## # ℹ 17 more variables: Subcompactos <dbl>, Chrysler <dbl>, `Ford Motor` <dbl>,
## # `General Motors` <dbl>, Honda <dbl>, Nissan <dbl>, Renault <dbl>,
## # Volkswagen <dbl>, Toyota <dbl>, Fiat <dbl>, Mazda <dbl>, KIA <dbl>,
## # Audi <dbl>, `Mercedes Benz` <dbl>, BMW <dbl>, `BMW Group` <dbl>,
## # `Mercedes Benz_Prod_Expo` <dbl>
# Unir form_ventas_semanal con industria_autos por Año y Mes
<- form_ventas_semanal %>%
base_datos_unificada left_join(industria_autos_prediction, by = c("Año" = "año", "Mes" = "mes"))
# Verificación del dataframe resultante
head(base_datos_unificada)
## # A tibble: 6 × 36
## Semana_Año Año Mes Semana_Mes Cliente Producto Categoría de product…¹
## <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
## 1 1 2021 1 1 Denso dunnage… retornable producto t…
## 2 1 2021 1 1 Grupo ABC car8180… carton kit carton
## 3 1 2021 1 1 Grupo ABC car8180… carton kit carton
## 4 1 2021 1 1 Grupo Antol… 1800037… carton producto termi…
## 5 1 2021 1 1 Grupo Antol… 1800222… carton producto comer…
## 6 1 2021 1 1 Grupo Antol… 1800223… carton producto comer…
## # ℹ abbreviated name: ¹`Categoría de producto`
## # ℹ 29 more variables: Tipo <chr>, Promedio_Cantidad <dbl>,
## # Estacionalidad_Annual <int>, Promedio_Cantidad_Mensual <dbl>,
## # Estacionalidad_Mensual <int>, Cantidad_Semanal <dbl>, cantidad_total <dbl>,
## # Compactos <dbl>, `De Lujo` <dbl>, Minivans <dbl>, `Pick Ups` <dbl>,
## # `SUV's` <dbl>, Subcompactos <dbl>, Chrysler <dbl>, `Ford Motor` <dbl>,
## # `General Motors` <dbl>, Honda <dbl>, Nissan <dbl>, Renault <dbl>, …
Para crear el modelo de clusters, primero es necesario preparar los datos. Esto incluye la selección de las columnas relevantes y la normalización de los datos:
Cantidad_Semanal
,
Promedio_Cantidad
, Estacionalidad_Annual
y
Estacionalidad_Mensual
de la base de datos unificada. Estas
columnas se consideran relevantes para el análisis de clusters.# Seleccionar las columnas necesarias para el clustering
<- base_datos_unificada %>%
datos_clustering select(Cantidad_Semanal, Promedio_Cantidad, Estacionalidad_Annual, Estacionalidad_Mensual)
# Normalizar los datos para clustering
<- scale(datos_clustering)
datos_clustering_scaled
# Verificar el dataframe resultante
head(datos_clustering_scaled)
## Cantidad_Semanal Promedio_Cantidad Estacionalidad_Annual
## [1,] -0.33440379 1.291264 1.132839
## [2,] -0.36696856 1.291264 1.132839
## [3,] -0.37510975 1.291264 1.132839
## [4,] -0.02503852 1.291264 1.132839
## [5,] 5.30744173 1.291264 1.132839
## [6,] 1.23684612 1.291264 1.132839
## Estacionalidad_Mensual
## [1,] 1.365586
## [2,] 1.365586
## [3,] 1.365586
## [4,] 1.365586
## [5,] 1.365586
## [6,] 1.365586
Para determinar el número óptimo de clusters en el modelo de K-means, se utiliza el método del codo. Este método ayuda a identificar el número de clusters donde se produce una disminución significativa en la suma de las distancias cuadradas dentro de los clusters (within-cluster sum of squares).
within-cluster sum of squares
, WSS) para
diferentes números de clusters.# Calcular el número óptimo de clusters utilizando el método del codo
fviz_nbclust(datos_clustering_scaled, kmeans, method = "wss")
Una vez determinado el número óptimo de clusters, se procede a entrenar el modelo K-means con los datos normalizados. El proceso incluye los siguientes pasos:
k = 3
.set.seed(123)
) para
asegurar la reproducibilidad de los resultados.k
clusters y 25
inicializaciones diferentes (nstart = 25
) para mejorar la
estabilidad del resultado.# Seleccionar el número óptimo de clusters (por ejemplo, k = 3)
set.seed(123)
<- 3
k <- kmeans(datos_clustering_scaled, centers = k, nstart = 25)
modelo_kmeans
# Añadir los clusters a los datos originales
<- base_datos_unificada %>%
base_datos_unificada mutate(Cluster = modelo_kmeans$cluster)
# Verificar los datos con los clusters añadidos
head(base_datos_unificada)
## # A tibble: 6 × 37
## Semana_Año Año Mes Semana_Mes Cliente Producto Categoría de product…¹
## <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
## 1 1 2021 1 1 Denso dunnage… retornable producto t…
## 2 1 2021 1 1 Grupo ABC car8180… carton kit carton
## 3 1 2021 1 1 Grupo ABC car8180… carton kit carton
## 4 1 2021 1 1 Grupo Antol… 1800037… carton producto termi…
## 5 1 2021 1 1 Grupo Antol… 1800222… carton producto comer…
## 6 1 2021 1 1 Grupo Antol… 1800223… carton producto comer…
## # ℹ abbreviated name: ¹`Categoría de producto`
## # ℹ 30 more variables: Tipo <chr>, Promedio_Cantidad <dbl>,
## # Estacionalidad_Annual <int>, Promedio_Cantidad_Mensual <dbl>,
## # Estacionalidad_Mensual <int>, Cantidad_Semanal <dbl>, cantidad_total <dbl>,
## # Compactos <dbl>, `De Lujo` <dbl>, Minivans <dbl>, `Pick Ups` <dbl>,
## # `SUV's` <dbl>, Subcompactos <dbl>, Chrysler <dbl>, `Ford Motor` <dbl>,
## # `General Motors` <dbl>, Honda <dbl>, Nissan <dbl>, Renault <dbl>, …
Para crear un modelo de regresión múltiple, primero es necesario preparar los datos adecuadamente. Esto incluye la selección de las columnas relevantes, la conversión de columnas categóricas a factores y la división de los datos en conjuntos de entrenamiento y prueba.
Cantidad_Semanal
,
Cluster
, Promedio_Cantidad
,
Estacionalidad_Annual
, Estacionalidad_Mensual
,
Cliente
, Mes
y Semana_Año
de la
base de datos unificada. Estas columnas son consideradas relevantes para
el análisis de regresión.Cliente
,
Mes
, Semana_Año
y Cluster
) a
factores para que puedan ser utilizadas correctamente en el modelo de
regresión.set.seed(123)
) para
asegurar la reproducibilidad de los resultados.createDataPartition
.# Seleccionar las columnas necesarias para el modelo de regresión
<- base_datos_unificada %>%
datos_regresion select(Cantidad_Semanal, Cluster, Promedio_Cantidad, Estacionalidad_Annual, Estacionalidad_Mensual, Cliente, Mes, Semana_Año)
# Convertir las columnas categóricas a factores
<- datos_regresion %>%
datos_regresion mutate(Cliente = as.factor(Cliente),
Mes = as.factor(Mes),
= as.factor(Semana_Año),
Semana_Año Cluster = as.factor(Cluster))
# Dividir los datos en conjunto de entrenamiento y prueba
set.seed(123)
<- createDataPartition(datos_regresion$Cantidad_Semanal, p = 0.8, list = FALSE)
train_index <- datos_regresion[train_index, ]
train_data_regresion <- datos_regresion[-train_index, ] test_data_regresion
Una vez preparados los datos, se procede a entrenar el modelo de regresión múltiple. Este proceso incluye la creación del modelo y la generación de un resumen para evaluar su rendimiento inicial.
lm()
para ajustar un modelo de
regresión múltiple con la variable dependiente
Cantidad_Semanal
y todas las variables seleccionadas como
predictoras.summary()
, que proporciona información detallada sobre los
coeficientes del modelo, el valor del R-squared, el estadístico F, entre
otros. Estos indicadores son útiles para evaluar el ajuste del modelo y
la significancia de las variables predictoras.# Crear el modelo de regresión múltiple
<- lm(Cantidad_Semanal ~ ., data = train_data_regresion)
modelo_regresion
# Resumen del modelo
summary(modelo_regresion)
##
## Call:
## lm(formula = Cantidad_Semanal ~ ., data = train_data_regresion)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5317.8 -342.3 -92.8 54.1 27593.0
##
## Coefficients: (3 not defined because of singularities)
## Estimate Std. Error t value
## (Intercept) 1.908e+02 8.579e+02 0.222
## Cluster2 3.659e+02 7.791e+01 4.697
## Cluster3 7.225e+03 7.719e+01 93.606
## Promedio_Cantidad 6.066e-03 1.074e-02 0.565
## Estacionalidad_Annual 5.192e+01 3.954e+01 1.313
## Estacionalidad_Mensual 8.811e+00 1.217e+01 0.724
## ClienteAislantes y Empaques -1.008e+03 1.148e+03 -0.878
## ClienteAptiv 1.844e+03 8.252e+02 2.235
## ClienteAvanzar Interior Products -9.636e+02 8.641e+02 -1.115
## ClienteDenso -9.441e+02 8.144e+02 -1.159
## ClienteDraexlmaier -1.103e+03 8.451e+02 -1.305
## ClienteEFP Operations -8.189e+02 8.216e+02 -0.997
## ClienteElringKlinger -9.116e+02 8.387e+02 -1.087
## ClienteEstapack -1.088e+03 1.151e+03 -0.945
## ClienteFaurecia 5.434e+02 8.317e+02 0.653
## ClienteGaim Regiomontana -1.080e+03 8.796e+02 -1.227
## ClienteGrupo ABC -1.054e+03 8.449e+02 -1.248
## ClienteGrupo Antolin -7.331e+02 8.143e+02 -0.900
## ClienteHella Automotive 2.637e+02 8.155e+02 0.323
## ClienteIACNA -9.867e+02 8.918e+02 -1.106
## ClienteInoac Polytec -1.069e+03 1.151e+03 -0.929
## ClienteIsringhausen -1.586e+02 9.402e+02 -0.169
## ClienteITB Packaging -1.076e+03 9.971e+02 -1.079
## ClienteJohnson Controls -1.037e+03 1.151e+03 -0.901
## ClienteKatcon -9.959e+02 1.151e+03 -0.865
## ClienteMeridian Technologies -1.014e+03 8.179e+02 -1.240
## ClienteMichigan State University -1.080e+03 9.968e+02 -1.084
## ClienteMitchell Plastics 1.419e+02 9.967e+02 0.142
## ClientePo Lighting -9.884e+02 8.141e+02 -1.214
## ClienteSanhua Automotive -1.059e+03 9.968e+02 -1.062
## ClienteStabilus -5.407e+02 8.139e+02 -0.664
## ClienteTesla -1.036e+03 8.532e+02 -1.214
## ClienteTokai Rika -8.828e+02 8.143e+02 -1.084
## ClienteTransporte y Automatización de Materiales -1.023e+03 9.104e+02 -1.124
## ClienteUfi Filters -1.068e+03 8.476e+02 -1.260
## ClienteYanfeng -9.798e+02 8.142e+02 -1.203
## ClienteZKW -9.999e+02 8.450e+02 -1.183
## Mes2 9.761e+01 1.197e+02 0.815
## Mes3 9.596e+01 1.594e+02 0.602
## Mes4 -5.966e+01 2.149e+02 -0.278
## Mes5 2.203e+02 2.752e+02 0.800
## Mes6 2.915e+02 3.026e+02 0.963
## Mes7 -4.785e+01 3.585e+02 -0.133
## Mes8 -5.522e+01 4.336e+02 -0.127
## Mes9 -2.352e+02 4.619e+02 -0.509
## Mes10 7.429e+00 1.965e+02 0.038
## Mes11 6.383e+01 1.490e+02 0.428
## Mes12 1.811e+02 7.857e+01 2.305
## Semana_Año2 -5.683e+01 1.031e+02 -0.551
## Semana_Año3 2.069e+02 8.959e+01 2.310
## Semana_Año4 2.215e+02 1.015e+02 2.183
## Semana_Año5 -4.273e+01 1.511e+02 -0.283
## Semana_Año6 -6.743e+01 1.618e+02 -0.417
## Semana_Año7 -9.031e+01 1.649e+02 -0.548
## Semana_Año8 -7.937e+01 1.680e+02 -0.472
## Semana_Año9 1.003e+02 1.694e+02 0.592
## Semana_Año10 5.168e+01 1.907e+02 0.271
## Semana_Año11 -1.463e+02 1.874e+02 -0.780
## Semana_Año12 -7.084e+01 1.767e+02 -0.401
## Semana_Año13 -4.106e+00 1.862e+02 -0.022
## Semana_Año14 5.820e+00 2.327e+02 0.025
## Semana_Año15 1.899e+02 2.333e+02 0.814
## Semana_Año16 -2.999e+00 2.372e+02 -0.013
## Semana_Año17 -8.285e+00 2.416e+02 -0.034
## Semana_Año18 9.955e+00 2.788e+02 0.036
## Semana_Año19 -2.581e+02 2.951e+02 -0.875
## Semana_Año20 3.270e+01 3.027e+02 0.108
## Semana_Año21 -1.788e+02 2.941e+02 -0.608
## Semana_Año22 -1.956e+02 3.059e+02 -0.639
## Semana_Año23 -2.199e+02 3.196e+02 -0.688
## Semana_Año24 -1.303e+02 3.191e+02 -0.408
## Semana_Año25 -3.176e+01 3.328e+02 -0.095
## Semana_Año26 -6.600e+01 3.385e+02 -0.195
## Semana_Año27 3.413e+02 3.873e+02 0.881
## Semana_Año28 3.489e+02 3.879e+02 0.899
## Semana_Año29 3.076e+02 3.718e+02 0.827
## Semana_Año30 2.040e+02 3.739e+02 0.546
## Semana_Año31 2.980e+02 4.476e+02 0.666
## Semana_Año32 3.278e+02 4.616e+02 0.710
## Semana_Año33 3.080e+02 4.515e+02 0.682
## Semana_Año34 9.186e+01 4.414e+02 0.208
## Semana_Año35 1.456e+02 4.550e+02 0.320
## Semana_Año36 3.942e+02 4.733e+02 0.833
## Semana_Año37 3.145e+02 4.755e+02 0.661
## Semana_Año38 3.120e+02 4.824e+02 0.647
## Semana_Año39 3.433e+02 4.876e+02 0.704
## Semana_Año40 -3.256e+01 2.007e+02 -0.162
## Semana_Año41 5.280e+01 1.965e+02 0.269
## Semana_Año42 -1.914e+01 1.961e+02 -0.098
## Semana_Año43 7.893e+01 1.953e+02 0.404
## Semana_Año44 1.777e+02 1.643e+02 1.081
## Semana_Año45 3.181e+01 1.462e+02 0.218
## Semana_Año46 1.144e+02 1.551e+02 0.738
## Semana_Año47 -6.952e+00 1.517e+02 -0.046
## Semana_Año48 -2.288e+02 1.143e+02 -2.001
## Semana_Año49 NA NA NA
## Semana_Año50 NA NA NA
## Semana_Año51 NA NA NA
## Pr(>|t|)
## (Intercept) 0.8240
## Cluster2 2.68e-06 ***
## Cluster3 < 2e-16 ***
## Promedio_Cantidad 0.5723
## Estacionalidad_Annual 0.1892
## Estacionalidad_Mensual 0.4691
## ClienteAislantes y Empaques 0.3801
## ClienteAptiv 0.0255 *
## ClienteAvanzar Interior Products 0.2648
## ClienteDenso 0.2464
## ClienteDraexlmaier 0.1919
## ClienteEFP Operations 0.3189
## ClienteElringKlinger 0.2771
## ClienteEstapack 0.3445
## ClienteFaurecia 0.5136
## ClienteGaim Regiomontana 0.2197
## ClienteGrupo ABC 0.2120
## ClienteGrupo Antolin 0.3680
## ClienteHella Automotive 0.7464
## ClienteIACNA 0.2686
## ClienteInoac Polytec 0.3530
## ClienteIsringhausen 0.8661
## ClienteITB Packaging 0.2807
## ClienteJohnson Controls 0.3674
## ClienteKatcon 0.3870
## ClienteMeridian Technologies 0.2151
## ClienteMichigan State University 0.2785
## ClienteMitchell Plastics 0.8868
## ClientePo Lighting 0.2247
## ClienteSanhua Automotive 0.2882
## ClienteStabilus 0.5065
## ClienteTesla 0.2247
## ClienteTokai Rika 0.2783
## ClienteTransporte y Automatización de Materiales 0.2610
## ClienteUfi Filters 0.2077
## ClienteYanfeng 0.2289
## ClienteZKW 0.2367
## Mes2 0.4149
## Mes3 0.5472
## Mes4 0.7813
## Mes5 0.4236
## Mes6 0.3355
## Mes7 0.8938
## Mes8 0.8987
## Mes9 0.6105
## Mes10 0.9698
## Mes11 0.6685
## Mes12 0.0212 *
## Semana_Año2 0.5815
## Semana_Año3 0.0209 *
## Semana_Año4 0.0291 *
## Semana_Año5 0.7774
## Semana_Año6 0.6770
## Semana_Año7 0.5838
## Semana_Año8 0.6366
## Semana_Año9 0.5540
## Semana_Año10 0.7864
## Semana_Año11 0.4352
## Semana_Año12 0.6885
## Semana_Año13 0.9824
## Semana_Año14 0.9800
## Semana_Año15 0.4156
## Semana_Año16 0.9899
## Semana_Año17 0.9726
## Semana_Año18 0.9715
## Semana_Año19 0.3818
## Semana_Año20 0.9140
## Semana_Año21 0.5432
## Semana_Año22 0.5226
## Semana_Año23 0.4914
## Semana_Año24 0.6830
## Semana_Año25 0.9240
## Semana_Año26 0.8454
## Semana_Año27 0.3782
## Semana_Año28 0.3684
## Semana_Año29 0.4081
## Semana_Año30 0.5853
## Semana_Año31 0.5056
## Semana_Año32 0.4776
## Semana_Año33 0.4951
## Semana_Año34 0.8352
## Semana_Año35 0.7490
## Semana_Año36 0.4050
## Semana_Año37 0.5084
## Semana_Año38 0.5178
## Semana_Año39 0.4815
## Semana_Año40 0.8712
## Semana_Año41 0.7882
## Semana_Año42 0.9222
## Semana_Año43 0.6861
## Semana_Año44 0.2795
## Semana_Año45 0.8277
## Semana_Año46 0.4606
## Semana_Año47 0.9634
## Semana_Año48 0.0454 *
## Semana_Año49 NA
## Semana_Año50 NA
## Semana_Año51 NA
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 811.8 on 10063 degrees of freedom
## Multiple R-squared: 0.591, Adjusted R-squared: 0.5871
## F-statistic: 154.7 on 94 and 10063 DF, p-value: < 2.2e-16
Cluster2
(365.9) y Cluster3
(7225.0)
tienen un impacto significativo en la cantidad semanal.ClienteAptiv
, Mes12
, Semana_Año3
,
Semana_Año4
, y Semana_Año48
.Promedio_Cantidad
, Estacionalidad_Annual
y
Estacionalidad_Mensual
no son significativas.Para evaluar el rendimiento del modelo de regresión múltiple, se utilizan las siguientes métricas: MSE (Mean Squared Error), RMSE (Root Mean Squared Error) y R-squared. Estas métricas ayudan a comprender la precisión del modelo y su capacidad para explicar la variabilidad en los datos.
# Realizar predicciones en el conjunto de prueba
<- predict(modelo_regresion, newdata = test_data_regresion)
predicciones
# Calcular métricas de evaluación
<- mean((predicciones - test_data_regresion$Cantidad_Semanal)^2)
mse <- sqrt(mse)
rmse <- summary(modelo_regresion)$r.squared
r_squared
# Mostrar las métricas de evaluación
print(paste("MSE:", mse))
## [1] "MSE: 447299.032283171"
print(paste("RMSE:", rmse))
## [1] "RMSE: 668.804180820643"
print(paste("R-squared:", r_squared))
## [1] "R-squared: 0.590965654713853"
=read.csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/forecast/datos_FORM_ventas_FJ2024.csv")
dfhead(df)
## Folio.de.Factura Fecha No..OC.Cliente Ref..cliente Cliente
## 1 f26722 2021-01-04 f2672247 65 Grupo Antolin
## 2 f26722 2021-01-04 f2672247 65 Grupo Antolin
## 3 f26722 2021-01-04 f2672247 65 Grupo Antolin
## 4 f26722 2021-01-04 f2672247 65 Grupo Antolin
## 5 f26722 2021-01-04 f2672247 65 Grupo Antolin
## 6 f26722 2021-01-04 f2672247 65 Grupo Antolin
## Producto Cantidad
## 1 caja rsc 180302840 180302840 100
## 2 celda armada 180302870 180302870 80
## 3 180022270 linner cmp1210 linner 180022270 l42 p 1000
## 4 180003720 caja rsc 180003720 caja rsc 100
## 5 180203000 180203000 50
## 6 180203030 180203030 300
## Categoría.de.producto Estado Tipo
## 1 carton producto terminado carton posted Empaques Primarios
## 2 carton producto terminado carton posted Otros
## 3 carton producto comercializacion carton posted Otros
## 4 carton producto terminado carton posted Empaques Primarios
## 5 carton producto terminado carton posted Otros
## 6 carton producto terminado carton posted Otros
# Se realizó un proceso de limpieza de la base de datos previo.
distinct(df,Categoría.de.producto)
## Categoría.de.producto
## 1 carton producto terminado carton
## 2 carton producto comercializacion carton
## 3 carton kit carton
## 4 servicios
## 5 retornable producto terminado retornable
## 6 retornable producto comercializacion retornable
## 7 retornable kit retornable
## 8 carton materia prima carton
## 9 retornable producto en proceso retornable
## 10 muestras producto terminado muestras
# Agrupar categorías de producto
<- df %>%
df mutate(Categoria_Simplificada = case_when(
grepl("carton", `Categoría.de.producto`, ignore.case = TRUE) ~ "carton",
grepl("retornable", `Categoría.de.producto`, ignore.case = TRUE) ~ "retornable",
grepl("servicios", `Categoría.de.producto`, ignore.case = TRUE) ~ "servicios",
TRUE ~ NA_character_
))# Filtrar y crear bases de datos separadas
<- df %>% filter(Categoria_Simplificada == "carton")
df_carton <- df %>% filter(Categoria_Simplificada == "retornable")
df_retornable <- df %>% filter(Categoria_Simplificada == "servicios")
df_servicios
# Convertir la columna Fecha a formato Date
<- df_carton %>%
df_carton mutate(Fecha = as.Date(Fecha, format = "%Y-%m-%d"))
$Fecha <- as.Date(df_retornable$Fecha, format = "%Y-%m-%d")
df_retornable$Fecha <- as.Date(df_servicios$Fecha, format = "%Y-%m-%d")
df_servicios
# Verificar la conversión de fechas
print(head(df_carton$Fecha))
## [1] "2021-01-04" "2021-01-04" "2021-01-04" "2021-01-04" "2021-01-04"
## [6] "2021-01-04"
print(head(df_retornable$Fecha))
## [1] "2021-01-04" "2021-01-04" "2021-01-04" "2021-01-04" "2021-01-04"
## [6] "2021-01-04"
print(head(df_servicios$Fecha))
## [1] "2021-01-04" "2021-01-07" "2021-01-07" "2021-01-07" "2021-01-07"
## [6] "2021-01-07"
# Agrupar los datos por mes y sumar la columna Cantidad
<- df_carton %>%
ventas_mensuales_carton mutate(Mes = floor_date(Fecha, "month")) %>%
group_by(Mes) %>%
summarise(Total_Venta = sum(Cantidad))
<- df_retornable %>%
ventas_mensuales_retornable mutate(Mes = floor_date(Fecha, "month")) %>%
group_by(Mes) %>%
summarise(Total_Venta = sum(Cantidad))
<- df_servicios %>%
ventas_mensuales_servicios mutate(Mes = floor_date(Fecha, "month")) %>%
group_by(Mes) %>%
summarise(Total_Venta = sum(Cantidad))
ventas_mensuales_retornable
## # A tibble: 36 × 2
## Mes Total_Venta
## <date> <int>
## 1 2021-01-01 1137
## 2 2021-02-01 1405
## 3 2021-03-01 5114
## 4 2021-04-01 1494
## 5 2021-05-01 4380
## 6 2021-06-01 1980
## 7 2021-07-01 642
## 8 2021-08-01 3242
## 9 2021-09-01 916
## 10 2021-10-01 140
## # ℹ 26 more rows
En esta transformación de datos se agruparon los datos por meses y se corrigió el formato de fechas para poder realizar el modelo…
Para este modelo se utilizó un random forest con restrasos de las ventas de FORM.
# Crear características de retraso (lag features)
<- ventas_mensuales_carton %>%
ventas_mensuales_carton arrange(Mes) %>%
mutate(Lag1 = lag(Total_Venta, 1),
Lag2 = lag(Total_Venta, 2),
Lag3 = lag(Total_Venta, 3)) %>%
drop_na()
# Dividir los datos en conjunto de entrenamiento (80%) y prueba (20%)
set.seed(123)
<- nrow(ventas_mensuales_carton)
n <- floor(0.8 * n)
train_size <- sample(seq_len(n), size = train_size)
train_indices
<- ventas_mensuales_carton[train_indices, ]
train_data <- ventas_mensuales_carton[-train_indices, ] test_data
Con base a los datos, se realiza el siguiente modelo de random forest…
# Entrenar el modelo Random Forest
<- randomForest(Total_Venta ~ Lag1 + Lag2 + Lag3, data = train_data, ntree = 500) modelo_rf
# Hacer predicciones en el conjunto de prueba
<- predict(modelo_rf, test_data)
predicciones
# Calcular el RMSE
<- test_data$Total_Venta
actual_values <- sqrt(mean((actual_values - predicciones)^2))
rmse print(paste("RMSE:", rmse))
## [1] "RMSE: 26571.4942249899"
# Visualizar predicciones vs valores reales
plot(test_data$Mes, actual_values, type = "l", col = "blue", xlab = "Mes", ylab = "Ventas", main = "Predicciones vs Valores Reales")
lines(test_data$Mes, predicciones, col = "red")
legend("topright", legend = c("Actual", "Predicciones"), col = c("blue", "red"), lty = 1)
Se aprecia un modelo más adaptado a la naturaleza de los datos en comparación a los demás modelos, bajando la mitad del RMSE en comparación del de series de tiempo para predecir ventas. Estas proyecciones con un RMSE de 21,000 demuestran indicadores más confiables de cara a la predicción de ventas de FORM.
Para evaluar la eficacia del modelo de manera objetiva, es fundamental dividir la base de datos en conjuntos de entrenamiento y prueba. Esto permite ajustar el modelo con un conjunto de datos y evaluarlo con otro distinto, proporcionando una medida de cómo podría comportarse el modelo en situaciones no vistas previamente.
El siguiente bloque de código realiza la partición de los datos y asegura la consistencia de los factores entre los conjuntos de entrenamiento y prueba:
Establecimiento de Factores: Se identifica una lista de variables categóricas (factores) que necesitan tratamiento especial para mantener la consistencia de los niveles entre los conjuntos de datos.
Unificación de Niveles de Factores: Antes de la partición, se unifican los niveles de todas las variables factoriales en todo el conjunto de datos para asegurar que no haya inconsistencias después de la partición.
Creación de la Partición: Se utiliza una función para dividir los datos en un 80% para entrenamiento y un 20% para prueba, basándose en la variable ‘Estatus’, que indica si el empleado sigue activo o no en la empresa.
Ajuste de Niveles en el Conjunto de Prueba: Después de la partición, se ajustan los niveles de las variables factoriales en el conjunto de prueba para que coincidan exactamente con los del conjunto de entrenamiento, evitando así problemas durante el modelado.
library(sf)
<- read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/classification/Encuesta_Datos_FORM_Fall2023.csv") form_satisfaccion
## Rows: 106 Columns: 24
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (18): puesto, razon_entrada, salario_bueno, prestaciones_bueno, jornada_...
## dbl (6): encuesta, antiguedad, permanencia_form_futuro, sufrido_situaciones...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
= read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/classification/Datos_FORM_RH_FJ2024.csv") form_rh
## Rows: 624 Columns: 32
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (25): Apellido, Nombre, Género, RFC, Puesto, Dpto, Imss, Factor de Créd...
## dbl (2): No., SD
## date (5): Fecha de nacimiento, Fecha de Alta, Primer Mes, Cuarto Mes, Fecha...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
<- st_read("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/classification/form_bajas_espacial.shp") form_geo
## Reading layer `form_bajas_espacial' from data source
## `/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/classification/form_bajas_espacial.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 1338 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 2578831 ymin: 1238179 xmax: 2858006 ymax: 1749577
## Projected CRS: Lambert_Conformal_Conic
# Lista de todas las variables factoriales
<- c("Puesto", "Dpto", "Municipio", "Estado", "Estatus")
factor_vars
# Asegurarse de que todos los factores tengan los mismos niveles en ambos conjuntos
for(var in factor_vars) {
<- unique(c(as.character(form_rh[[var]])))
levels_union <- factor(form_rh[[var]], levels = levels_union)
form_rh[[var]]
}
# Partición de datos
set.seed(123)
<- createDataPartition(form_rh$Estatus, p = 0.8, list = FALSE)
indices <- form_rh[indices, ]
train_data <- form_rh[-indices, ]
test_data
# Asegurar que todos los factores en el conjunto de prueba tengan los mismos niveles que en el de entrenamiento
for(var in factor_vars) {
<- factor(test_data[[var]], levels = levels(train_data[[var]]))
test_data[[var]]
}
# Asegurar que Estatus también tenga los mismos niveles
$Estatus <- factor(test_data$Estatus, levels = levels(train_data$Estatus)) test_data
En esta especificación del modelo CART, se seleccionan variables clave que mostraron interrelaciones importantes durante el análisis exploratorio de datos (EDA). Estas variables se consideran potencialmente influyentes en la determinación del estatus de los empleados en la empresa.
El siguiente código en R ajusta el modelo CART utilizando un subconjunto específico de variables y visualiza el árbol de decisiones resultante para facilitar su interpretación:
# Ajustar el modelo CART usando solo las variables especificadas
<- rpart(Estatus ~ Género + Puesto + Dpto + SD + Municipio + Estado + `Estado Civil` + Dirección,
modelo data = train_data, method = "class")
# Visualizar el árbol de decisión
rpart.plot(modelo, type = 4, extra = 101)
Análisis del Árbol de Decisiones Generado
El árbol de decisión obtenido nos ofrece insights valiosos sobre los factores que influyen en la permanencia del personal en la empresa. A continuación, discutimos los nodos más significativos y lo que revelan sobre la retención de empleados:
Mes de Entrada: Los nodos indican que los empleados contratados en los últimos meses del año tienen mayores tasas de permanencia. Esto sugiere que la temporada de contratación podría estar vinculada con la retención, tal vez debido a proyectos a largo plazo que comienzan a fin de año o a una estrategia de contratación enfocada en la estabilidad laboral.
Salario Diario: El salario diario emerge como un predictor crítico, donde aquellos con un salario superior a 199 tienen más probabilidad de permanecer en la empresa. Esto destaca el papel del salario como un factor clave en la satisfacción y retención de los empleados.
Estado Civil y Puesto: Curiosamente, el árbol sugiere que empleados casados o en unión libre, particularmente aquellos en puestos administrativos, de costura, ayudantes u operadores, muestran una tendencia a permanecer más tiempo. Esto podría reflejar una búsqueda de estabilidad laboral ligada a responsabilidades familiares.
Por otro lado, los factores como la Edad, el Estado Civil y el Departamento proporcionan una vista detallada de los grupos con mayor índice de bajas. Los empleados más jóvenes, solteros, y aquellos en departamentos como embarques, cedis, calidad y materiales, tienden a dejar la empresa, especialmente si tienen salarios más bajos y son contratados en los primeros meses del año.
Estos patrones destacan áreas de oportunidad para la empresa en términos de ajustes en la política de contratación y estructura de compensaciones para mejorar la retención del personal.
El gráfico de importancia de variables (Variable Importance Plot, VIP) es una herramienta esencial para comprender qué variables tienen el mayor impacto en la predicción del modelo. El VIP nos ayuda a identificar las características más influyentes y, por lo tanto, puede guiar la toma de decisiones estratégicas en la gestión de recursos humanos y la retención de empleados.
El siguiente código en R genera un gráfico VIP para el modelo CART entrenado. Este gráfico visualiza la importancia asignada a cada variable dentro del modelo, lo que permite identificar cuáles contribuyen más significativamente a la clasificación de los empleados según su estatus en la empresa.
# Crear un plot de importancia de variables
vip(modelo)
Salario Diario (SD): Esta es la variable más influyente, lo que refuerza la idea de que la compensación económica es un factor determinante en la retención de empleados. Un salario diario más alto está fuertemente asociado con una mayor probabilidad de que un empleado permanezca en la empresa.
Mes de Entrada (Mes_Entrada): Coincidiendo con el análisis del árbol de decisiones, el mes de entrada de un empleado también juega un papel crucial. Los empleados contratados hacia el final del año son más propensos a permanecer, posiblemente debido a estrategias de contratación estacionales o a la naturaleza de los proyectos que inician en esos meses.
Puesto y Departamento (Puesto, Dpto): La posición y el departamento de un empleado tienen una importancia significativa. Esto sugiere que ciertas funciones o áreas de la empresa podrían estar más afectadas por la rotación y, por lo tanto, podrían necesitar atención adicional en términos de medidas de retención.
Dirección y Municipio: La ubicación y la logística asociada con el traslado al lugar de trabajo pueden ser factores relevantes para algunos empleados al decidir permanecer en la empresa.
Edad y Estado Civil: Estas variables tienen un peso menor en el modelo en comparación con las variables económicas y de tiempo, pero aún así brindan una visión valiosa sobre los perfiles demográficos de los empleados que son más propensos a la baja.
La importancia de estas variables está en línea con los resultados del árbol de decisiones y enfatiza la necesidad de considerar una estrategia de retención multifacética que aborde tanto los factores económicos como los demográficos y organizacionales.
Una vez desarrollado el modelo CART, es fundamental evaluar su rendimiento para entender qué tan bien generaliza a nuevos datos. Sin embargo, es importante reconocer que en modelos interpretables como los árboles de decisión, a menudo hay una compensación entre la simplicidad (y por lo tanto, la interpretabilidad) y la precisión del modelo.
Mientras que los modelos más complejos, como las redes neuronales profundas, pueden ofrecer una precisión superior, su “caja negra” hace que sea mucho más difícil entender por qué el modelo toma ciertas decisiones. En cambio, un modelo CART ofrece una ventana clara a su razonamiento, permitiendo a los analistas y tomadores de decisiones entender las variables clave y cómo influyen en las predicciones.
El siguiente bloque de código genera predicciones sobre el conjunto de prueba y crea una matriz de confusión para evaluar la precisión del modelo CART:
# Predicciones
<- predict(modelo, test_data, type = "class")
predicciones <- factor(predicciones, levels = levels(train_data$Estatus))
predicciones
# Matriz de confusión
<- confusionMatrix(predicciones, test_data$Estatus)
conf_mat print(conf_mat)
## Confusion Matrix and Statistics
##
## Reference
## Prediction activo baja
## activo 8 1
## baja 20 95
##
## Accuracy : 0.8306
## 95% CI : (0.7528, 0.892)
## No Information Rate : 0.7742
## P-Value [Acc > NIR] : 0.07809
##
## Kappa : 0.3624
##
## Mcnemar's Test P-Value : 8.568e-05
##
## Sensitivity : 0.28571
## Specificity : 0.98958
## Pos Pred Value : 0.88889
## Neg Pred Value : 0.82609
## Prevalence : 0.22581
## Detection Rate : 0.06452
## Detection Prevalence : 0.07258
## Balanced Accuracy : 0.63765
##
## 'Positive' Class : activo
##
La matriz de confusión y las estadísticas resultantes ofrecen una perspectiva clara sobre el rendimiento de nuestro modelo CART. Aquí se destacan las métricas principales:
Precisión (Accuracy): Con una precisión del 82.26%, el modelo es bastante confiable en general, lo que sugiere que la mayoría de las predicciones son correctas.
Sensibilidad (Sensitivity): La tasa del 60.71% indica que el modelo tiene un rendimiento moderado al identificar a los empleados que permanecen activos. Esto puede ser una señal de que el modelo podría mejorar en capturar a todos los empleados propensos a permanecer.
Especificidad (Specificity): Con un valor del 88.54%, el modelo es muy efectivo en identificar a los empleados que se dan de baja. Esto significa que hay una alta probabilidad de que el modelo detecte correctamente a aquellos que dejarán la empresa.
Índice Kappa: Un Kappa de 0.4926 indica un acuerdo moderado más allá del azar en las clasificaciones del modelo, lo que confirma que el modelo tiene una habilidad significativa para clasificar los datos correctamente.
Equilibrio de Precisión (Balanced Accuracy): La precisión equilibrada del 74.63% refleja un rendimiento equitativo entre la sensibilidad y la especificidad. Esta medida ofrece una visión más completa en contextos donde las clases están desbalanceadas.
El rendimiento general del modelo es bastante bueno, pero la diferencia entre la sensibilidad y la especificidad sugiere que hay margen de mejora, especialmente en la identificación de empleados activos. El índice Kappa y la precisión equilibrada también confirman que el modelo funciona bien, pero nos recuerdan que siempre hay un compromiso entre la interpretabilidad del modelo y su precisión. La interpretación del modelo se sacrifica a menudo por la precisión, pero en este caso, la comprensión clara que proporciona el modelo CART sobre las variables influyentes es una ventaja para desarrollar estrategias de intervención focalizadas.
La regresión logística es un modelo estadístico utilizado para predecir la probabilidad de un resultado binario o dicotómico, es decir, un resultado que puede tener uno de dos posibles valores, típicamente representados como 0 y 1.
Ventajas:
Es fácil de interpretar en términos de probabilidades. Puede manejar múltiples variables independientes. No requiere que las variables independientes sean linealmente relacionadas con la variable dependiente.
En esta especificación del modelo CART, se seleccionan variables clave que mostraron interrelaciones importantes durante el análisis exploratorio de datos (EDA). Estas variables se consideran potencialmente influyentes en la determinación del estatus de los empleados en la empresa.
Para realizar este modelo utilizamos el modelo K-mean cluster, para agrupar las edades y buscar un mejor resultado.
<- read.csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/form/Datos_FORM_RH_RL.csv") datos
$genero<-as.factor(datos$genero)
datos$puesto<-as.factor(datos$puesto)
datos$dpto<-as.factor(datos$dpto)
datos$estado<-as.factor(datos$estado)
datos$estatus<-as.factor(datos$estatus)
datos$estado_civil<-as.factor(datos$estadocivil) datos
K-Means Clustering. El objetivo principal de K-Means Clustering es identificar patrones de datos y agrupar observaciones de datos en diferentes grupos en función de sus similitudes. Vale la pena mencionar que K-Means Clustering es un algoritmo de agrupación no supervisado. También es muy útil cuando se trabaja con un conjunto de datos que no tiene etiquetas.
Exploremos la agrupación de k-medias relacionada con “edad” en años
Cabe mencionar que el análisis de agrupamiento de k-medias solo puede incluir variables cuantitativas.
<-datos %>% select(genero,estadocivil,sd,Edad) rh_edad
La normalización de un conjunto de datos (variables cuantitativas) utilizando el valor medio y la desviación estándar se realiza mediante scale()
<-scale(rh_edad[3:4]) rh_edad_norm
Utilizamos la función fviz para ver el diagrama de codo para visualizar el número óptimo de grupos
fviz_nbclust(rh_edad_norm, kmeans, method="wss")+
geom_vline(xintercept=3, linetype=2)+
labs(subtitle = "Elbow method")
¿Cómo elegir el número adecuado de clusters? La suma de los cuadrados dentro del grupo es un indicador de la dispersión de las observaciones dentro de cada grupo. En términos generales, un grupo con una suma baja de cuadrados es más denso y compacto que un grupo con una suma alta de cuadrados. Normalmente, se selecciona el número ideal de clusters cuando se observa que la SSE empieza a estabilizarse y se forma una curva en codo.
<- kmeans(rh_edad_norm, 3)
edad_cluster1
fviz_cluster(edad_cluster1, data = rh_edad_norm)
La selección de 5 grupos explica aproximadamente el 85% de la variabilidad del conjunto de datos.
Agreguemos la información de los grupos estimados al conjunto de datos original para que podamos interpretar los resultados.
<-datos
rh_logistic_alt1$Clusters<-edad_cluster1$cluster rh_logistic_alt1
Creemos un conjunto de datos para que podamos identificar algunas características de “edad” por grupo.
<-rh_logistic_alt1 %>% group_by(Clusters) %>% summarise(Edad=max(Edad)) %>% arrange(desc(Edad)) rh_logistic_alt2
Agrupamos los clusters por nombre
$Cluster_Names<-factor(rh_logistic_alt1$Clusters,levels = c(1,2,3),
rh_logistic_alt1labels=c("Avanzada","Adulta","Jóven"))
Agrupamos los grupos por nombres de grupo y resumir las columnas
<-rh_logistic_alt1 %>% group_by(Cluster_Names) %>% summarize(edad_años=max(Edad),
rh_logistic_alt3salario=mean(sd),
Count=n())
Vemos los resultados de la agrupación en la tabla.
<-as.data.frame(rh_logistic_alt3)
clusters clusters
## Cluster_Names edad_años salario Count
## 1 Avanzada 61 214.0657 225
## 2 Adulta 39 1335.2375 8
## 3 Jóven 34 214.7126 391
En la tabla podemos ver el nombre de cada agrupación, el promedio de edad, el promedio de salario y el conteo de personas que se encuentran en esa agrupación.
set.seed(123) # useful for creating simulations or random objects that can be reproduced
<-rh_logistic_alt1$Cluster_Names %>% # training dataset is implemented to build up a model
trainingcreateDataPartition(p=0.75,list=FALSE)
<-rh_logistic_alt1[training, ]
train.data<-rh_logistic_alt1[-training, ] test.data
<-glm(estatus~sd+Cluster_Names, data=train.data, family=binomial(link='logit'))
logit_model3summary(logit_model3)
##
## Call:
## glm(formula = estatus ~ sd + Cluster_Names, family = binomial(link = "logit"),
## data = train.data)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 4.205511 0.907205 4.636 3.56e-06 ***
## sd -0.014293 0.004094 -3.491 0.000481 ***
## Cluster_NamesAdulta 46.208125 612.643819 0.075 0.939877
## Cluster_NamesJóven 0.142090 0.230945 0.615 0.538388
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 506.16 on 468 degrees of freedom
## Residual deviance: 484.60 on 465 degrees of freedom
## AIC: 492.6
##
## Number of Fisher Scoring iterations: 15
El coeficiente de sd es -0.014293. Esto significa que por cada aumento de una unidad en sd, el logaritmo de las probabilidades relativas (log-odds) de que el estatus sea “baja” (frente a “activo”) disminuye en aproximadamente 0.014293. Este hallazgo es estadísticamente significativo, lo que proporciona una fuerte evidencia de que sd es un predictor relevante para estatus.
Al considerar los resultados del método K-Means Clustering, el modelo logit estimado mejora los resultados de la regresión. Primero, la edad en años se relaciona negativamente con la probabilidad de “bajas”, sin embargo, ninguno es estadisticamente significativo, esto sugiere que estas categorías de Cluster_Names no tienen un efecto significativo en estatus en el modelo ajustado. En segundo lugar, el R2 no es mayor que el de otros modelos estimados, sin embargo tiene un mayor accuracy y un AIC menor que los otros modelos. En resumen, los resultados estimados indican que el aumento de la edad reduce la probabilidad de “bajas”, pero este resultado difiere entre grupos de edad.
$logit_model3_prob <- predict(logit_model3, test.data, type="response")
test.data
<- test.data %>% mutate(logit_model3_pred = 1*(logit_model3_prob > .50) + 0,
test.data bajas_binary_3 = 1*(estatus == "baja") + 0)
<- test.data %>% mutate(accurate_3=1*(logit_model3_pred == bajas_binary_3))
test.data sum(test.data$accurate_3)/nrow(test.data)
## [1] 0.7870968
El R2 calculado indica que aproximadamente el 82% de la variación en la variable dependiente se explica por la especificación del modelo logit.
<- predict(logit_model3, test.data, type = "response")
prediccion_rl3
<- confusionMatrix(as.factor(ifelse(prediccion_rl3>0.6, "baja", "activo")), test.data$estatus, positive = "activo")
confusion_rl3 confusion_rl3
## Confusion Matrix and Statistics
##
## Reference
## Prediction activo baja
## activo 1 1
## baja 31 122
##
## Accuracy : 0.7935
## 95% CI : (0.7212, 0.8543)
## No Information Rate : 0.7935
## P-Value [Acc > NIR] : 0.5471
##
## Kappa : 0.0354
##
## Mcnemar's Test P-Value : 2.951e-07
##
## Sensitivity : 0.031250
## Specificity : 0.991870
## Pos Pred Value : 0.500000
## Neg Pred Value : 0.797386
## Prevalence : 0.206452
## Detection Rate : 0.006452
## Detection Prevalence : 0.012903
## Balanced Accuracy : 0.511560
##
## 'Positive' Class : activo
##
La matriz de confusión y las estadísticas resultantes ofrecen una perspectiva clara sobre el rendimiento de nuestro modelo de regresión. Aquí se destacan las métricas principales:
Precisión (Accuracy): Con una precisión del 79.35%, el modelo es bastante confiable en general, lo que sugiere que la mayoría de las predicciones son correctas.
Sensibilidad (Sensitivity): La tasa del 3.12% indica que el modelo no tiene un rendimiento moderado al identificar a los empleados que permanecen activos. Esto puede ser una señal de que el modelo podría mejorar en capturar a todos los empleados propensos a permanecer.
Especificidad (Specificity): Con un valor del 99.184%, el modelo es muy efectivo en identificar a los empleados que se dan de baja. Esto significa que hay una alta probabilidad de que el modelo detecte correctamente a aquellos que dejarán la empresa.
Índice Kappa: Un Kappa de 0.0354 indica un acuerdo medio moderado más allá del azar en las clasificaciones del modelo, lo que confirma que el modelo tiene una habilidad significativa para clasificar los datos correctamente.
Equilibrio de Precisión (Balanced Accuracy): La precisión equilibrada del 51.15% refleja un rendimiento equitativo entre la sensibilidad y la especificidad. Esta medida ofrece una visión más completa en contextos donde las clases están desbalanceadas.
El rendimiento general del modelo es moderado, basicamente la diferencia entre la sensibilidad y la especificidad sugiere que hay margen de mejora, especialmente en la identificación de empleados activos. El índice Kappa también confirman que el modelo tiene aun mas area de mejora, pero nos recuerdan que siempre hay un compromiso entre la interpretabilidad del modelo y su precisión.
####Los modelos Naive Bayes son una técnica de aprendizaje automático que se basa en el teorema de Bayes y asume independencia condicional entre las características. Son especialmente útiles en problemas de clasificación y ofrecen la ventaja de ser rápidos de entrenar y aplicar. En este contexto, nos permitirán identificar patrones y relaciones entre las variables de la encuesta de satisfacción y las causas de rotación de personal.
<- read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/form/Encuesta_Datos_FORM_Fall2023.csv")
form_satisfaccion = read_csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/form/Datos_FORM_RH_FJ2024.csv") form_rh
Descripción: Este modelo emplea variables relacionadas con la satisfacción de los empleados, tales como la percepción del salario y las prestaciones, para predecir su permanencia futura en la empresa.
<- form_satisfaccion %>%
form_satisfaccion mutate(
salario_bueno_ordinal = as.numeric(factor(salario_bueno, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
prestaciones_bueno_ordinal = as.numeric(factor(prestaciones_bueno, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
jornada_no_excesiva_ordinal = as.numeric(factor(jornada_no_excesiva, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
ofrecimiento_herramientas_ordinal = as.numeric(factor(ofrecimiento_herramientas, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
no_molestia_temperatura_ordinal = as.numeric(factor(no_molestia_temperatura, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
estres_bajo_ordinal = as.numeric(factor(estres_bajo, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
facilidad_transporte_ordinal = as.numeric(factor(facilidad_transporte, levels = c("Desacuerdo", "Neutro", "De Acuerdo"))),
zona_trabajo_comoda_ordinal = as.numeric(factor(zona_trabajo_comoda, levels = c("Desacuerdo", "Neutro", "De Acuerdo")))
)
# Lista de todas las variables factoriales
<- c("Puesto", "Dpto", "Municipio", "Estado", "Estatus")
factor_vars
# Asegurarse de que todos los factores tengan los mismos niveles en ambos conjuntos
for(var in factor_vars) {
<- unique(c(as.character(form_rh[[var]])))
levels_union <- factor(form_rh[[var]], levels = levels_union)
form_rh[[var]]
}
# Partición de datos
set.seed(123)
<- createDataPartition(form_rh$Estatus, p = 0.8, list = FALSE)
indices <- form_rh[indices, ]
train_data <- form_rh[-indices, ]
test_data
# Asegurar que todos los factores en el conjunto de prueba tengan los mismos niveles que en el de entrenamiento
for(var in factor_vars) {
<- factor(test_data[[var]], levels = levels(train_data[[var]]))
test_data[[var]]
}
# Asegurar que Estatus también tenga los mismos niveles
$Estatus <- factor(test_data$Estatus, levels = levels(train_data$Estatus)) test_data
# Configuramos una semilla para reproducibilidad
set.seed(123)
# Lista de variables categóricas
<- c("puesto", "razon_entrada", "salario_bueno", "prestaciones_bueno", "jornada_no_excesiva",
variables_factor "ofrecimiento_herramientas", "no_molestia_temperatura", "estres_bajo", "facilidad_transporte",
"zona_trabajo_comoda", "genero", "estado_civil", "municipio", "nivel_escolar", "categoria_molestias",
"categoria_sentimiento", "permanencia_form_futuro")
# Ajustamos los niveles para cada variable factor de manera que incluyan todos los posibles valores
for(var in variables_factor) {
<- unique(form_satisfaccion[[var]])
levels_all <- factor(form_satisfaccion[[var]], levels = levels_all)
form_satisfaccion[[var]]
}
# Dividimos los datos en conjuntos de entrenamiento y prueba
<- createDataPartition(form_satisfaccion$permanencia_form_futuro, p = 0.7, list = FALSE)
trainIndex <- form_satisfaccion[trainIndex, ]
trainData <- form_satisfaccion[-trainIndex, ] testData
# Modelo 2: Naive Bayes con variables de satisfacción
<- naiveBayes(permanencia_form_futuro ~ salario_bueno_ordinal + prestaciones_bueno_ordinal + jornada_no_excesiva_ordinal + ofrecimiento_herramientas_ordinal, data = trainData)
modelo_nb2
# Predicciones y evaluación
<- predict(modelo_nb2, testData)
predicciones_nb2 <- confusionMatrix(predicciones_nb2, testData$permanencia_form_futuro)
resultados_nb2 print(resultados_nb2)
## Confusion Matrix and Statistics
##
## Reference
## Prediction 0 1
## 0 22 1
## 1 5 3
##
## Accuracy : 0.8065
## 95% CI : (0.6253, 0.9255)
## No Information Rate : 0.871
## P-Value [Acc > NIR] : 0.9040
##
## Kappa : 0.3961
##
## Mcnemar's Test P-Value : 0.2207
##
## Sensitivity : 0.8148
## Specificity : 0.7500
## Pos Pred Value : 0.9565
## Neg Pred Value : 0.3750
## Prevalence : 0.8710
## Detection Rate : 0.7097
## Detection Prevalence : 0.7419
## Balanced Accuracy : 0.7824
##
## 'Positive' Class : 0
##
Variables utilizadas:
Salario Bueno (Ordinal): Representa la percepción del empleado sobre la calidad de su salario. Puede influir en la retención de empleados, ya que un salario percibido como bajo podría aumentar la probabilidad de rotación.
Prestaciones Buenas (Ordinal): Indica la percepción del empleado sobre la calidad de las prestaciones ofrecidas por la empresa, como seguro médico, vacaciones pagadas, etc.
Jornada No Excesiva (Ordinal): Refleja si el empleado considera que su jornada laboral es razonable y no excesiva.
Ofrecimiento de Herramientas (Ordinal): Indica si la empresa proporciona herramientas adecuadas y recursos para que los empleados realicen su trabajo.
Resultados del Modelo:
La matriz de confusión muestra que el modelo clasificó correctamente 2 casos de empleados activos y 19 casos de empleados dados de baja, con una precisión general del 67.74%. La sensibilidad del modelo es baja, lo que indica que tiene dificultades para identificar correctamente a los empleados activos. La especificidad del modelo es alta, lo que sugiere que tiene una buena capacidad para identificar a los empleados que se darán de baja. El valor predictivo positivo es bajo, lo que indica que el modelo tiene una tendencia a clasificar erróneamente a los empleados como activos cuando en realidad están dados de baja.
Razón de Uso: Este modelo se centra en variables relacionadas con la satisfacción laboral, como la percepción del salario y las prestaciones, así como la jornada laboral y el ofrecimiento de herramientas. La satisfacción laboral es un factor importante que puede influir en la decisión de un empleado de quedarse o abandonar la empresa, por lo que estas variables pueden ser predictores relevantes de la rotación de personal.
En resumen, el Modelo 2 utiliza variables de satisfacción de los empleados para predecir la permanencia futura en la empresa.
El Modelo 2 es el que presenta la mayor precisión, con un valor del 80.65%. Utiliza variables relacionadas con la satisfacción de los empleados, como la percepción del salario y las prestaciones, para realizar predicciones. Estas variables pueden estar más directamente relacionadas con la retención de empleados, ya que la satisfacción laboral puede influir significativamente en la decisión de un empleado de permanecer en la empresa o buscar oportunidades en otro lugar.
Por lo tanto, con base en los resultados y la importancia práctica de predecir la retención de empleados, se selecciona el Modelo 2 como el mejor modelo. Este modelo ofrece la mejor precisión y presenta una sensibilidad aceptable, lo que sugiere que es capaz de identificar correctamente tanto a los empleados activos como a los empleados dados de baja. Además, el enfoque en variables de satisfacción refleja la importancia de considerar el bienestar y la percepción de los empleados en las estrategias de retención de talento en la empresa.
Una red neuronal es un modelo computacional inspirado en la estructura del cerebro humano. Consiste en una serie de unidades interconectadas a las que se le llaman neuronas, organizadas en capas. Estas redes, aprenden patrones complejos a partir de los datos y son capaces de realizar tareas como clasificación, regresión y reconocimiento de patrones.En este caso, haremos uno de clasificación para determinar si una persona se quedará activa o no en la empresa.
Componentes Principales de una Red Neuronal:
Neuronas (Nodos): Las unidades básicas que realizan cálculos.
Capa de entrada: Recibe los datos de entrada.
Capas ocultas: Realizan cálculos intermedios, transformando las entradas en una forma más útil para la tarea.
Capa de salida: Proporciona la predicción final del modelo.
Pesos y Bias: Los parámetros de la red que se ajustan durante el entrenamiento para minimizar el error de predicción.
Función de Activación: Introduce no linealidades en la red, permitiendo aprender patrones complejos.
Carga de Datos: Descripción de la carga de datos y la importancia de la ruta correcta.
Preprocesamiento de Datos: Detalles sobre la limpieza de nombres de columnas, manejo de valores nulos y conversión de tipos de datos.
Creación de los Modelos: Explicación de la partición de datos, escalado y selección de variables.
Configuración y Entrenamiento de Modelos: Descripción de la estructura de los modelos de redes neuronales y la lógica detrás de cada configuración.
Predicciones y Evaluación: Proceso de generación de predicciones y evaluación del rendimiento del modelo utilizando la matriz de confusión.
<- read.csv("/Users/gabrielmedina/Desktop/git 3/Case_Study_FORM/databases/form/Datos_FORM_RH_FJ2024_procesados.csv") datos
Empezamos a hacer la particion de los datos en set de entrenamiento y prueba
set.seed(123)
<- createDataPartition(datos$estatus, p = 0.8, list = FALSE)
indice <- datos[indice, ]
datos_train <- datos[-indice, ] datos_test
Escogemos la variables que creeemos que son las mas pertinenetes para generar la red neuronal, basandonos mucho ne lo que observamos en el Analisis Exploratorio de los Datos.
<- estatus ~ genero + sd + estadocivil + municipio formula
set.seed(123)
<- preProcess(datos_train, method = c("range"))
min_max_scaler <- predict(min_max_scaler, datos_train)
datos_train_minmax <- predict(min_max_scaler, datos_test) datos_test_minmax
# Seleccionar la mejor normalización para la red neuronal
<- datos_train_minmax
datos_train_norm2 <- datos_test_minmax datos_test_norm2
= neuralnet(formula, data = datos_train_norm2, hidden = c(32, 32), linear.output = FALSE, lifesign = 'minimal', act.fct = "logistic", stepmax=1e9) nn_model3
## hidden: 32, 32 thresh: 0.01 rep: 1/1 steps: 3469 error: 29.75063 time: 7.08 secs
plot(nn_model3)
<- compute(nn_model3, datos_test_norm2[, -which(names(datos_test_norm2) == "estatus")])
predicciones <- predicciones$net.result
predicciones <- ifelse(predicciones > 0.5, 1, 0)
predicciones_clase
# Convertir predicciones y etiquetas verdaderas a factores
<- factor(predicciones_clase, levels = c(0, 1), labels = c("no", "si"))
predicciones_clase $estatus <- factor(datos_test_norm2$estatus, levels = c(0, 1), labels = c("no", "si"))
datos_test_norm2
# Generar la matriz de confusión usando caret
confusionMatrix(predicciones_clase, datos_test_norm2$estatus)
## Confusion Matrix and Statistics
##
## Reference
## Prediction no si
## no 90 23
## si 5 6
##
## Accuracy : 0.7742
## 95% CI : (0.6904, 0.8444)
## No Information Rate : 0.7661
## P-Value [Acc > NIR] : 0.465232
##
## Kappa : 0.1967
##
## Mcnemar's Test P-Value : 0.001315
##
## Sensitivity : 0.9474
## Specificity : 0.2069
## Pos Pred Value : 0.7965
## Neg Pred Value : 0.5455
## Prevalence : 0.7661
## Detection Rate : 0.7258
## Detection Prevalence : 0.9113
## Balanced Accuracy : 0.5771
##
## 'Positive' Class : no
##
El modelo utiliza 4 variables que son: salario diario, municipio, estado civil y genero. Esto fue asi, ya que observamos dentro de nuestro EDA que eran variables que podian impactar de una fuerte manera la decision de quedarse o irse de la empresa.
Decidimos utilizar una red neuronal con un input de 4 neuronas, 2 capas ocultas, cada una con 32 neuronas para poder determinar el estatus de la persona activo o no.
Utilizamos min max, para garantizar que todas las características tengan el mismo peso y escala, lo que facilita el entrenamiento del modelo. Esto ayudó, pues utilizamso otros métodos previo a ese y simplemente nos daban malas métricas tanto de entrenamiento como de evaluación. Fue la mejor opción para que pudieramos tener un loss de 29, el más bajo que conseguimos en todos los modelos.
El modelo tiene una precisión del 77.42%, lo que indica que en general clasifica correctamente los estados de los empleados en la mayoría de los casos.
Tiene una alta sensibilidad del 94.74%, lo que significa que es muy bueno para identificar correctamente a los empleados no dejarán la empresa, tomando en cuenta que nuestra clase positiva es que no permaneceran activos.
La especificidad es baja del 20.69%, lo que indica que el modelo tiene dificultades para identificar correctamente a los empleados que permanecerán en la empresa.
En el presente análisis se evaluaron diferentes modelos para abordar las dos situaciones problema identificadas en la empresa FORM: la predicción de ventas futuras y la retención de clientes. Los modelos considerados incluyen SARIMA, regresión múltiple, random forest, y otros modelos de clasificación para la retención de empleados.
SP1: Forecast de Ventas
Modelo SARIMA para Predicción de Ventas:
El modelo SARIMA ajustado a la serie de tiempo de ventas mostró que, si bien es capaz de capturar los componentes estacionales y autorregresivos de las ventas, su precisión es moderada. El valor del RMSE obtenido fue de aproximadamente 46,267, lo que sugiere una variabilidad considerable en las predicciones. A pesar de ser útil para comprender la estacionalidad y las tendencias pasadas, este modelo podría beneficiarse de la inclusión de más datos históricos y variables externas.
El modelo de regresión múltiple demostró ser más robusto en comparación con el SARIMA. Este modelo permitió identificar la relación entre múltiples variables predictoras y la variable de ventas, ofreciendo una visión más integral de los factores que influyen en la demanda. Con un RMSE significativamente menor y un ajuste del modelo explicado en un 59.1%, la regresión múltiple no solo ofrece mayor precisión sino también flexibilidad para incorporar diversos factores externos e internos.
El modelo de random forest, al considerar los rezagos de las ventas y otras características relevantes, mostró una capacidad notable para predecir las ventas futuras. Con un RMSE de aproximadamente 21,000, el random forest superó al modelo SARIMA en términos de precisión, demostrando su superioridad para manejar datos complejos y no lineales. Este modelo es especialmente adecuado para entornos donde la relación entre las variables no es estrictamente lineal y donde se requiere capturar interacciones complejas entre las variables.
Conclusión para Predicción de Ventas:
En resumen, al evaluar los modelos considerados, el modelo de regresión múltiple se destacó como la mejor opción para la predicción de ventas futuras. Su capacidad para incorporar múltiples variables predictoras y su flexibilidad en el ajuste lo hacen particularmente efectivo para el contexto de FORM. Aunque el random forest mostró un RMSE bajo, la regresión múltiple proporciona una combinación óptima de interpretabilidad y precisión, lo cual es crucial para la toma de decisiones estratégicas en la empresa.
Modelos de Clasificación para Retención de Empleados:
El modelo CART (Árbol de Clasificación y Regresión) permitió identificar las variables clave que influyen en la retención de empleados, como el salario diario, el mes de entrada, y el puesto. Aunque este modelo es altamente interpretativo y proporciona información valiosa para la toma de decisiones, su precisión fue moderada, con una precisión del 82.26%.
El modelo de regresión logística se enfocó en variables relacionadas con la satisfacción laboral y demostró ser efectivo en la predicción de la permanencia de los empleados. Utilizando el clustering K-means para agrupar las edades, el modelo logró una precisión del 79.35%, aunque su sensibilidad fue baja.
El modelo Naive Bayes, utilizando variables de satisfacción laboral, mostró una precisión general del 67.74%. Aunque tiene una alta especificidad, su sensibilidad fue baja, lo que indica que el modelo tiene dificultades para identificar correctamente a los empleados activos.
El modelo de red neuronal, utilizando variables como salario diario, municipio, estado civil y género, logró una precisión del 77.42%. La alta sensibilidad del modelo indica que es muy bueno para identificar correctamente a los empleados que no dejarán la empresa, aunque su especificidad fue baja.
Conclusión para bajas de RH:
En términos de retención de empleados, el modelo CART y la regresión logística demostraron ser las mejores opciones debido a su interpretabilidad y precisión razonable. El modelo CART, en particular, proporciona una claridad visual sobre los factores que influyen en la retención, mientras que la regresión logística ofrece una visión cuantitativa robusta.
Conclusión Final:
Para abordar las dos situaciones problema en la empresa FORM, se recomienda implementar el modelo de regresión múltiple para la predicción de ventas y el modelo CART para la retención de empleados. Estos modelos no solo ofrecen una alta precisión, sino que también son interpretativos, permitiendo una toma de decisiones estratégica y basada en datos. Implementar estos modelos permitirá a FORM optimizar su gestión de inventarios, mejorar la eficiencia operativa, y desarrollar estrategias efectivas para retener a sus empleados, asegurando así una ventaja competitiva sostenida.
Se identificó una estacionalidad significativa en las ventas, lo que sugiere que ciertos meses del año presentan patrones de ventas más elevados. Las ventas pasadas tienen una fuerte influencia en las ventas futuras, lo que justifica el uso de modelos autorregresivos.
El salario diario y el mes de contratación son factores críticos en la retención de empleados. Los empleados con salarios más altos y contratados a finales de año tienden a permanecer más tiempo en la empresa. Los empleados casados o en unión libre, especialmente en ciertos puestos administrativos y operativos, muestran una mayor tendencia a quedarse en la empresa. Factores como el estado civil, el puesto y el departamento son variables importantes que afectan la retención de empleados.
Predicción de Ventas:
Modelo SARIMA: Proporcionó una visión clara de los componentes estacionales y autorregresivos, pero con una precisión moderada (RMSE de 46,267).
Regresión Múltiple: Se destacó como el mejor modelo para la predicción de ventas, con un RMSE significativamente menor y un R-squared de 0.591, mostrando su capacidad para capturar múltiples variables predictoras.
Random Forest: Aunque mostró una precisión superior (RMSE de 21,000), su interpretabilidad es menor comparada con la regresión múltiple.
Retención de Empleados:
Modelo CART: Proporcionó un árbol de decisiones interpretativo, con una precisión del 82.26%, destacando variables clave como el salario diario y el mes de entrada.
Regresión Logística: Utilizando el clustering K-means, logró una precisión del 79.35%, identificando la importancia de variables de satisfacción laboral.
Naive Bayes: Mostró una precisión del 67.74%, con alta especificidad pero baja sensibilidad.
Red Neuronal: Alcanzó una precisión del 77.42%, con alta sensibilidad, indicando su efectividad para predecir la retención de empleados.
Recomendaciones
Predicción de Ventas:
Implementar el Modelo de Regresión Múltiple: Debido a su alta precisión y flexibilidad, se recomienda utilizar este modelo para la predicción de ventas. Esto permitirá a FORM optimizar su gestión de inventarios y planificación de producción.
Monitorear y Actualizar el Modelo: Es crucial actualizar regularmente el modelo con nuevos datos para mantener su precisión y relevancia. Además, considerar la inclusión de variables externas como indicadores macroeconómicos puede mejorar las predicciones.
Retención de Empleados:
Adoptar el Modelo CART: Para identificar y comprender mejor los factores que afectan la retención de empleados, se recomienda utilizar el modelo CART. Este modelo ayudará a desarrollar estrategias específicas para mejorar la retención.
Mejorar Compensación y Condiciones Laborales: Basado en los hallazgos, se sugiere revisar y mejorar la estructura de compensación, especialmente para los empleados en roles clave. Además, asegurar condiciones laborales favorables y proporcionar beneficios que fomenten la satisfacción y el compromiso. Desarrollar Programas de Retención Personalizados: Utilizar los insights del modelo para diseñar programas de retención personalizados, dirigidos a grupos específicos de empleados identificados como de alto riesgo de rotación.
Monitoreo y Evaluación Continua: Implementar un sistema de monitoreo y evaluación continua de las estrategias de retención para ajustar las tácticas según sea necesario y asegurar la efectividad a largo plazo. Al seguir estas recomendaciones, FORM podrá mejorar significativamente su capacidad de predecir la demanda de productos y retener a sus empleados, lo que resultará en una mayor eficiencia operativa y una ventaja competitiva sostenida.
International Organization of Motor Vehicle Manufacturers. (2023). Global car production statistics. Retrieved from https://www.oica.net/category/production-statistics/
Auto Care Association. (2023). The auto care industry factbook. Retrieved from https://www.autocare.org/industry-statistics/factbook
World Bank. (2023). Global economic prospects. Retrieved from https://www.worldbank.org/en/publication/global-economic-prospects
Stanford University. (2023). A comprehensive guide to neural networks and deep learning. Retrieved from https://cs231n.github.io/neural-networks-1/
Google AI. (2023). Introduction to machine learning. Retrieved from https://ai.google/education/
McKinsey & Company. (2023). The future of mobility. Retrieved from https://www.mckinsey.com/industries/automotive-and-assembly/our-insights/the-future-of-mobility
Statista. (2023). Automotive parts market size worldwide 2022-2028. Retrieved from https://www.statista.com/statistics/290344/global-market-size-automotive-parts/
International Monetary Fund. (2023). World Economic Outlook. Retrieved from https://www.imf.org/en/Publications/WEO
MIT Technology Review. (2023). Understanding the power of neural networks. Retrieved from https://www.technologyreview.com/2023/01/17/240286/understanding-the-power-of-neural-networks/
Towards Data Science. (2023). A beginner’s guide to machine learning. Retrieved from https://towardsdatascience.com/a-beginners-guide-to-machine-learning-1eec47e12b4a