Este informe presenta un análisis completo de la base de datos de integrantes de una empresa, que contiene información sobre 207 empleados activos, incluyendo datos demográficos, salariales, de desempeño y satisfacción laboral.
Contexto de la base de datos:
La base registra información de empleados de una organización con cuatro
departamentos (dpt1 a dpt4), veinte cargos
distintos, y un rango salarial que va desde los 3.080 hasta los 17.600
(unidades monetarias). Los datos incluyen variables como la fecha de
nacimiento, fecha de contratación, índice de satisfacción (escala 1-5) y
registro de desempeño laboral.
Objetivo del análisis:
Explorar y caracterizar el talento humano de la empresa, identificando
patrones en la distribución salarial, el desempeño, la satisfacción
laboral, y las diferencias entre departamentos y géneros.
Preguntas de interés:
# Cargar las librerías necesarias para el análisis
library(readxl) # Leer archivos Excel
library(tidyverse) # Manipulación y visualización de datos
library(dplyr) # Operaciones sobre data frames
library(ggplot2) # Visualización de datos
library(janitor) # Limpieza de datos
library(plotly) # Gráficos interactivos
library(lubridate) # Manejo de fechas
library(knitr) # Tablas formateadas
library(scales) # Formatos en ejes de gráficos
# Leer el archivo Excel con los datos de integrantes
# Ajusta la ruta según donde tengas guardado el archivo
datos <- read_excel("bd_integrantes_Esp (1).xlsx")
# Mostrar las primeras 6 filas para inspección inicial
head(datos)
| Nombre de los miembros | ID | Salario-Cargo | Fecha Nacimiento | Edad | Sexo | Fecha de contratación | Fecha salida | Status do Integrante | Departamento | Reclutamiento de fuentes | Registro de desempeño | Índice de satisfacción |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Isis | A1304055947 | 5060-Técnico de Producción I | 1982-05-21 | 38 | F | 2015-09-01 | NA | Ativo | dpt1 | Página Web compañía | Arriba | 5 |
| Emanuel | A1109029366 | 3520-Técnico de Producción I | 1975-12-21 | 45 | M | 2015-02-03 | NA | Ativo | dpt1 | Recomendación empleados | Dentro de lo esperado | 3 |
| Vinícius | A1501072124 | 4400-Técnico de Producción I | 1972-04-17 | 49 | M | 2017-07-06 | NA | Ativo | dpt1 | Sitio web de empleo | Abajo de lo esperado | 2 |
| João Guilherme | A1302053339 | 3960-Técnico de Producción I | 1994-10-17 | 26 | M | 2018-11-04 | NA | Ativo | dpt1 | Sitio web de empleo | Abajo de lo esperado | 4 |
| Luna | A1204032927 | 3520-Técnico de Producción I | 1985-08-04 | 35 | F | 2017-09-28 | NA | Ativo | dpt1 | Feria de contratación | Arriba | 4 |
| Rebeca | A1404066622 | 4400-Técnico de Producción I | 1979-02-04 | 42 | F | 2017-12-04 | NA | Ativo | dpt1 | Sitio web de empleo | Arriba | 4 |
# Ver la estructura del data frame: tipos de datos y primeros valores
str(datos)
## tibble [207 × 13] (S3: tbl_df/tbl/data.frame)
## $ Nombre de los miembros : chr [1:207] "Isis" "Emanuel" "Vinícius" "João Guilherme" ...
## $ ID : chr [1:207] "A1304055947" "A1109029366" "A1501072124" "A1302053339" ...
## $ Salario-Cargo : chr [1:207] "5060-Técnico de Producción I" "3520-Técnico de Producción I" "4400-Técnico de Producción I" "3960-Técnico de Producción I" ...
## $ Fecha Nacimiento : POSIXct[1:207], format: "1982-05-21" "1975-12-21" ...
## $ Edad : num [1:207] 38 45 49 26 35 42 30 27 35 38 ...
## $ Sexo : chr [1:207] "F" "M" "M" "M" ...
## $ Fecha de contratación : POSIXct[1:207], format: "2015-09-01" "2015-02-03" ...
## $ Fecha salida : logi [1:207] NA NA NA NA NA NA ...
## $ Status do Integrante : chr [1:207] "Ativo" "Ativo" "Ativo" "Ativo" ...
## $ Departamento : chr [1:207] "dpt1" "dpt1" "dpt1" "dpt1" ...
## $ Reclutamiento de fuentes: chr [1:207] "Página Web compañía" "Recomendación empleados" "Sitio web de empleo" "Sitio web de empleo" ...
## $ Registro de desempeño : chr [1:207] "Arriba" "Dentro de lo esperado" "Abajo de lo esperado" "Abajo de lo esperado" ...
## $ Índice de satisfacción : num [1:207] 5 3 2 4 4 4 4 3.1 4 3 ...
# Dimensiones: número de filas y columnas
cat("Número de filas (empleados):", nrow(datos), "\n")
## Número de filas (empleados): 207
cat("Número de columnas (variables):", ncol(datos), "\n")
## Número de columnas (variables): 13
# Nombres de todas las variables
names(datos)
## [1] "Nombre de los miembros" "ID"
## [3] "Salario-Cargo" "Fecha Nacimiento"
## [5] "Edad" "Sexo"
## [7] "Fecha de contratación" "Fecha salida"
## [9] "Status do Integrante" "Departamento"
## [11] "Reclutamiento de fuentes" "Registro de desempeño"
## [13] "Índice de satisfacción"
# Resumen estadístico de todas las variables
summary(datos)
## Nombre de los miembros ID Salario-Cargo
## Length:207 Length:207 Length:207
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
## Fecha Nacimiento Edad Sexo
## Min. :1956-01-31 00:00:00 Min. :23.00 Length:207
## 1st Qu.:1979-08-07 00:00:00 1st Qu.:29.00 Class :character
## Median :1986-04-13 00:00:00 Median :35.00 Mode :character
## Mean :1984-09-06 18:26:05 Mean :35.96
## 3rd Qu.:1991-05-30 00:00:00 3rd Qu.:41.00
## Max. :1997-08-16 00:00:00 Max. :54.00
## Fecha de contratación Fecha salida Status do Integrante
## Min. :2009-08-31 00:00:00 Mode:logical Length:207
## 1st Qu.:2015-05-03 00:00:00 NA's:207 Class :character
## Median :2016-11-10 00:00:00 Mode :character
## Mean :2016-08-25 06:15:39
## 3rd Qu.:2017-12-04 00:00:00
## Max. :2019-08-05 00:00:00
## Departamento Reclutamiento de fuentes Registro de desempeño
## Length:207 Length:207 Length:207
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
##
##
##
## Índice de satisfacción
## Min. :1.000
## 1st Qu.:3.000
## Median :4.000
## Mean :3.869
## 3rd Qu.:5.000
## Max. :5.000
Interpretación:
La base contiene 207 registros y 13
variables. Se identifican variables numéricas
(Edad, Índice de satisfacción), variables de
texto (Salario-Cargo, Departamento,
Sexo, etc.) y variables de fecha
(Fecha Nacimiento, Fecha de contratación). La
columna Fecha salida tiene todos los valores en NA, lo que
indica que todos los integrantes están activos.
# Contar valores nulos por columna
nulos <- colSums(is.na(datos))
cat("Valores nulos por columna:\n")
## Valores nulos por columna:
print(nulos)
## Nombre de los miembros ID Salario-Cargo
## 0 0 0
## Fecha Nacimiento Edad Sexo
## 0 0 0
## Fecha de contratación Fecha salida Status do Integrante
## 0 207 0
## Departamento Reclutamiento de fuentes Registro de desempeño
## 0 0 0
## Índice de satisfacción
## 0
# Verificar si existen filas completamente duplicadas
cat("Filas duplicadas:", sum(duplicated(datos)), "\n")
## Filas duplicadas: 0
# Verificar IDs duplicados (cada empleado debe tener un ID único)
cat("IDs duplicados:", sum(duplicated(datos$ID)), "\n")
## IDs duplicados: 0
La columna Salario-Cargo contiene dos informaciones
juntas (ej: "5060-Técnico de Producción I"). La separamos
en dos columnas independientes para facilitar el análisis.
# Separar el salario (número antes del guion) del cargo (texto después del guion)
datos <- datos %>%
mutate(
Salario = as.numeric(str_extract(`Salario-Cargo`, "^[0-9]+")),
Cargo = str_extract(`Salario-Cargo`, "(?<=^[0-9]{3,5}-).*")
)
# Verificar el resultado
head(datos %>% select(`Salario-Cargo`, Salario, Cargo))
| Salario-Cargo | Salario | Cargo |
|---|---|---|
| 5060-Técnico de Producción I | 5060 | Técnico de Producción I |
| 3520-Técnico de Producción I | 3520 | Técnico de Producción I |
| 4400-Técnico de Producción I | 4400 | Técnico de Producción I |
| 3960-Técnico de Producción I | 3960 | Técnico de Producción I |
| 3520-Técnico de Producción I | 3520 | Técnico de Producción I |
| 4400-Técnico de Producción I | 4400 | Técnico de Producción I |
# Calcular años de antigüedad en la empresa
datos <- datos %>%
mutate(
Antiguedad_anios = as.numeric(difftime(Sys.Date(), `Fecha de contratación`, units = "days")) / 365,
Antiguedad_anios = round(Antiguedad_anios, 1)
)
# Crear grupos de edad
datos <- datos %>%
mutate(
Grupo_edad = case_when(
Edad < 30 ~ "20-29",
Edad < 40 ~ "30-39",
Edad < 50 ~ "40-49",
TRUE ~ "50+"
)
)
# Estandarizar etiquetas de Sexo
datos <- datos %>%
mutate(Sexo_label = ifelse(Sexo == "F", "Femenino", "Masculino"))
# Mostrar las nuevas columnas
head(datos %>% select(Nombre = `Nombre de los miembros`, Salario, Cargo,
Antiguedad_anios, Grupo_edad, Sexo_label))
| Nombre | Salario | Cargo | Antiguedad_anios | Grupo_edad | Sexo_label |
|---|---|---|---|---|---|
| Isis | 5060 | Técnico de Producción I | 10.7 | 30-39 | Femenino |
| Emanuel | 3520 | Técnico de Producción I | 11.3 | 40-49 | Masculino |
| Vinícius | 4400 | Técnico de Producción I | 8.9 | 40-49 | Masculino |
| João Guilherme | 3960 | Técnico de Producción I | 7.6 | 20-29 | Masculino |
| Luna | 3520 | Técnico de Producción I | 8.7 | 30-39 | Femenino |
| Rebeca | 4400 | Técnico de Producción I | 8.5 | 40-49 | Femenino |
# La columna 'Fecha salida' tiene 207 valores NA (todos los empleados están activos)
# Se documenta este hallazgo y se elimina la columna para el análisis
datos <- datos %>% select(-`Fecha salida`)
cat("Columna 'Fecha salida' eliminada. Todos los empleados tienen estatus: Activo.\n")
## Columna 'Fecha salida' eliminada. Todos los empleados tienen estatus: Activo.
# Agrupar y calcular estadísticas por departamento
resumen_dept <- datos %>%
group_by(Departamento) %>%
summarise(
Total_empleados = n(),
Salario_promedio = round(mean(Salario, na.rm = TRUE), 0),
Salario_minimo = min(Salario, na.rm = TRUE),
Salario_maximo = max(Salario, na.rm = TRUE),
Satisfaccion_prom = round(mean(`Índice de satisfacción`, na.rm = TRUE), 2)
) %>%
arrange(desc(Salario_promedio))
resumen_dept
| Departamento | Total_empleados | Salario_promedio | Salario_minimo | Salario_maximo | Satisfaccion_prom |
|---|---|---|---|---|---|
| dpt4 | 47 | 9909 | 5720 | 14300 | 4.04 |
| dpt3 | 8 | 8304 | 3643 | 17600 | 3.50 |
| dpt2 | 27 | 7970 | 4250 | 13200 | 3.89 |
| dpt1 | 125 | 5164 | 3080 | 13200 | 3.82 |
# Top 10 cargos con mayor salario promedio
top_cargos <- datos %>%
group_by(Cargo) %>%
summarise(
Empleados = n(),
Salario_promedio = round(mean(Salario, na.rm = TRUE), 0)
) %>%
arrange(desc(Salario_promedio)) %>%
head(10)
top_cargos
| Cargo | Empleados | Salario_promedio |
|---|---|---|
| Diretor Administrativo | 1 | 17600 |
| Director de TI | 1 | 14300 |
| Director de Producción | 1 | 13200 |
| Diretor Comercial | 1 | 13200 |
| Gerente de TI | 7 | 12351 |
| Gerente Administrativo | 1 | 12100 |
| Gerente Comercial | 2 | 12100 |
| Gerente de Producción | 9 | 11794 |
| Ingeniero de software | 15 | 11028 |
| Analista Comercial III | 4 | 10488 |
# Comparación salarial y de satisfacción por género
resumen_sexo <- datos %>%
group_by(Sexo_label) %>%
summarise(
Total = n(),
Salario_promedio = round(mean(Salario, na.rm = TRUE), 0),
Edad_promedio = round(mean(Edad, na.rm = TRUE), 1),
Satisfaccion_prom = round(mean(`Índice de satisfacción`, na.rm = TRUE), 2),
Antiguedad_prom = round(mean(Antiguedad_anios, na.rm = TRUE), 1)
)
resumen_sexo
| Sexo_label | Total | Salario_promedio | Edad_promedio | Satisfaccion_prom | Antiguedad_prom |
|---|---|---|---|---|---|
| Femenino | 117 | 6566 | 35.8 | 3.92 | 9.9 |
| Masculino | 90 | 6941 | 36.2 | 3.81 | 9.6 |
# Distribución del registro de desempeño
resumen_desempeno <- datos %>%
group_by(`Registro de desempeño`) %>%
summarise(
Empleados = n(),
Porc = round(n() / nrow(datos) * 100, 1),
Salario_promedio = round(mean(Salario, na.rm = TRUE), 0),
Satisfaccion_prom = round(mean(`Índice de satisfacción`, na.rm = TRUE), 2)
) %>%
arrange(desc(Empleados))
resumen_desempeno
| Registro de desempeño | Empleados | Porc | Salario_promedio | Satisfaccion_prom |
|---|---|---|---|---|
| Dentro de lo esperado | 162 | 78.3 | 6623 | 3.97 |
| Arriba | 29 | 14.0 | 7280 | 4.00 |
| Abajo de lo esperado | 16 | 7.7 | 6801 | 2.62 |
# Fuentes de reclutamiento más comunes
resumen_recl <- datos %>%
group_by(`Reclutamiento de fuentes`) %>%
summarise(
Total = n(),
Porc = round(n() / nrow(datos) * 100, 1)
) %>%
arrange(desc(Total))
resumen_recl
| Reclutamiento de fuentes | Total | Porc |
|---|---|---|
| Sitio web de empleo | 87 | 42.0 |
| Feria de contratación | 45 | 21.7 |
| Recomendación empleados | 43 | 20.8 |
| Página Web compañía | 32 | 15.5 |
# Empleados con desempeño "Arriba" y satisfacción >= 4
estrella <- datos %>%
filter(`Registro de desempeño` == "Arriba",
`Índice de satisfacción` >= 4) %>%
select(`Nombre de los miembros`, Cargo, Departamento, Salario,
`Registro de desempeño`, `Índice de satisfacción`) %>%
arrange(desc(Salario))
cat("Empleados destacados (alto desempeño y alta satisfacción):", nrow(estrella), "\n")
## Empleados destacados (alto desempeño y alta satisfacción): 19
head(estrella, 10)
| Nombre de los miembros | Cargo | Departamento | Salario | Registro de desempeño | Índice de satisfacción |
|---|---|---|---|---|---|
| Cecília | Director de TI | dpt4 | 14300 | Arriba | 5 |
| João Pedro | Gerente de TI | dpt4 | 14300 | Arriba | 5 |
| Anthony | Gerente de TI | dpt4 | 14080 | Arriba | 5 |
| Ana Clara | Director de Producción | dpt1 | 13200 | Arriba | 5 |
| José M. | Ingeniero de software | dpt4 | 10560 | Arriba | 5 |
| Emanuelly | Analista de datos | dpt4 | 9405 | Arriba | 5 |
| Maria Luiza | Analista Comercial II | dpt2 | 8600 | Arriba | 5 |
| Murilo | Analista de datos | dpt4 | 7810 | Arriba | 4 |
| Emilly da M. | Técnico de Producción II | dpt1 | 5742 | Arriba | 4 |
| Maria Alice | Analista de soporte de TI | dpt4 | 5720 | Arriba | 4 |
# FUNCIÓN 1: Genera un resumen estadístico completo para una variable numérica
resumen_estadistico <- function(datos, variable, grupo = NULL) {
# Si se especifica un grupo, agrupa primero
if (!is.null(grupo)) {
resultado <- datos %>%
group_by(.data[[grupo]]) %>%
summarise(
N = n(),
Media = round(mean(.data[[variable]], na.rm = TRUE), 2),
Mediana = round(median(.data[[variable]], na.rm = TRUE), 2),
DE = round(sd(.data[[variable]], na.rm = TRUE), 2),
Min = min(.data[[variable]], na.rm = TRUE),
Max = max(.data[[variable]], na.rm = TRUE)
)
} else {
resultado <- datos %>%
summarise(
N = n(),
Media = round(mean(.data[[variable]], na.rm = TRUE), 2),
Mediana = round(median(.data[[variable]], na.rm = TRUE), 2),
DE = round(sd(.data[[variable]], na.rm = TRUE), 2),
Min = min(.data[[variable]], na.rm = TRUE),
Max = max(.data[[variable]], na.rm = TRUE)
)
}
return(resultado)
}
# Aplicar la función: resumen del salario por departamento
resumen_estadistico(datos, "Salario", grupo = "Departamento")
| Departamento | N | Media | Mediana | DE | Min | Max |
|---|---|---|---|---|---|---|
| dpt1 | 125 | 5164.19 | 4840.0 | 2165.06 | 3080 | 13200 |
| dpt2 | 27 | 7970.37 | 8000.0 | 2511.77 | 4250 | 13200 |
| dpt3 | 8 | 8303.88 | 7034.5 | 4498.72 | 3643 | 17600 |
| dpt4 | 47 | 9908.83 | 10000.0 | 2524.68 | 5720 | 14300 |
# Aplicar la función: resumen del índice de satisfacción por desempeño
resumen_estadistico(datos, "Índice de satisfacción", grupo = "Registro de desempeño")
| Registro de desempeño | N | Media | Mediana | DE | Min | Max |
|---|---|---|---|---|---|---|
| Abajo de lo esperado | 16 | 2.62 | 3 | 0.89 | 1 | 4 |
| Arriba | 29 | 4.00 | 4 | 0.94 | 2 | 5 |
| Dentro de lo esperado | 162 | 3.97 | 4 | 0.87 | 2 | 5 |
# FUNCIÓN 2: Clasifica empleados en niveles salariales según cuantiles
clasificar_salario <- function(datos, columna_salario = "Salario") {
q1 <- quantile(datos[[columna_salario]], 0.25, na.rm = TRUE)
q3 <- quantile(datos[[columna_salario]], 0.75, na.rm = TRUE)
datos <- datos %>%
mutate(
Nivel_salarial = case_when(
.data[[columna_salario]] <= q1 ~ "Bajo (Q1)",
.data[[columna_salario]] <= q3 ~ "Medio (Q1-Q3)",
TRUE ~ "Alto (Q3+)"
)
)
resumen <- datos %>%
group_by(Nivel_salarial) %>%
summarise(
Empleados = n(),
Salario_promedio = round(mean(.data[[columna_salario]], na.rm = TRUE), 0),
Satisfaccion_med = round(mean(`Índice de satisfacción`, na.rm = TRUE), 2)
)
cat("Puntos de corte — Q1:", q1, "| Q3:", q3, "\n")
return(list(datos = datos, resumen = resumen))
}
# Aplicar la función y guardar resultados
resultado_fn2 <- clasificar_salario(datos)
## Puntos de corte — Q1: 4400 | Q3: 8600
datos <- resultado_fn2$datos # Agregar la nueva columna al dataframe
resultado_fn2$resumen
| Nivel_salarial | Empleados | Salario_promedio | Satisfaccion_med |
|---|---|---|---|
| Alto (Q3+) | 50 | 11622 | 3.94 |
| Bajo (Q1) | 56 | 3830 | 3.90 |
| Medio (Q1-Q3) | 101 | 5914 | 3.82 |
ggplotly(
ggplot(datos, aes(x = Salario)) +
geom_histogram(binwidth = 500, fill = "steelblue", color = "white", alpha = 0.8) +
labs(
title = "Figura 1. Distribución del Salario de los Empleados",
x = "Salario",
y = "Número de empleados"
) +
theme_minimal()
)
Interpretación Figura 1:
El histograma muestra que la distribución salarial tiene una
marcada asimetría hacia la derecha, es decir, la
mayoría de los empleados gana salarios bajos o medios, mientras que un
número reducido percibe salarios altos (superiores a 10.000). Esto es
típico en estructuras organizacionales piramidales, donde hay muchos
operativos y pocos directivos. El rango más frecuente se encuentra entre
3.000 y 6.000.
datos_cargo <- datos %>%
group_by(Cargo) %>%
summarise(Salario_promedio = mean(Salario, na.rm = TRUE)) %>%
arrange(Salario_promedio)
ggplotly(
ggplot(datos_cargo, aes(x = reorder(Cargo, Salario_promedio), y = Salario_promedio)) +
geom_col(fill = "#2196F3", alpha = 0.85) +
coord_flip() +
labs(
title = "Figura 2. Salario Promedio por Cargo",
x = "Cargo",
y = "Salario promedio"
) +
theme_minimal() +
theme(axis.text.y = element_text(size = 8))
)
Interpretación Figura 2:
Los cargos directivos (Director, Diretor) y
gerenciales (Gerente) encabezan la escala salarial, con
valores que superan ampliamente a los técnicos y analistas. Se observa
una clara jerarquía salarial por nivel de
responsabilidad: los Técnicos de Producción tienen los salarios
más bajos, mientras que directores y gerentes reciben hasta 5 veces más.
Esta brecha podría revisarse para garantizar equidad interna.
ggplotly(
ggplot(datos, aes(x = Departamento, fill = `Registro de desempeño`)) +
geom_bar(position = "fill", alpha = 0.85) +
scale_y_continuous(labels = percent_format()) +
scale_fill_manual(values = c("Arriba" = "#4CAF50",
"Dentro de lo esperado" = "#2196F3",
"Abajo de lo esperado" = "#F44336")) +
labs(
title = "Figura 3. Distribución del Desempeño por Departamento",
x = "Departamento",
y = "Proporción",
fill = "Desempeño"
) +
theme_minimal()
)
Interpretación Figura 3:
El gráfico de barras apiladas al 100% permite comparar la proporción de
empleados en cada categoría de desempeño dentro de cada departamento. Si
algún departamento muestra una mayor proporción de empleados “Abajo de
lo esperado”, podría indicar problemas de gestión, formación o
motivación que requieren intervención. Por el contrario, los
departamentos con mayor proporción “Arriba” tienen un capital humano más
sólido.
ggplotly(
ggplot(datos, aes(x = `Registro de desempeño`,
y = `Índice de satisfacción`,
fill = `Registro de desempeño`)) +
geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.size = 2) +
scale_fill_manual(values = c("Arriba" = "#4CAF50",
"Dentro de lo esperado" = "#2196F3",
"Abajo de lo esperado" = "#F44336")) +
labs(
title = "Figura 4. Satisfacción Laboral según Registro de Desempeño",
x = "Desempeño",
y = "Índice de Satisfacción (1-5)",
fill = "Desempeño"
) +
theme_minimal() +
theme(legend.position = "none")
)
Interpretación Figura 4:
Este boxplot compara la distribución del índice de satisfacción (escala
1 a 5) para cada categoría de desempeño. Se puede analizar si los
empleados con mejor desempeño tienden a estar más satisfechos (relación
positiva), o si por el contrario no existe una relación clara. La
mediana y los cuartiles de cada grupo permiten identificar diferencias
sistemáticas entre categorías.
ggplotly(
ggplot(datos, aes(x = Sexo_label, y = Salario, fill = Sexo_label)) +
geom_violin(alpha = 0.6, trim = FALSE) +
geom_boxplot(width = 0.1, fill = "white", alpha = 0.8) +
scale_fill_manual(values = c("Femenino" = "#E91E8C", "Masculino" = "#2196F3")) +
labs(
title = "Figura 5. Distribución Salarial por Género",
x = "Género",
y = "Salario",
fill = "Género"
) +
theme_minimal() +
theme(legend.position = "none")
)
Interpretación Figura 5:
El gráfico de violín combina la forma de la distribución con el boxplot.
Permite detectar si existe una brecha salarial de
género: si la distribución masculina está más concentrada en
valores altos o si ambos géneros tienen distribuciones similares. Una
distribución más ancha en la parte superior para un género indica mayor
concentración en salarios altos. Esto es clave para políticas de equidad
salarial.
recl_conteo <- datos %>%
count(`Reclutamiento de fuentes`) %>%
mutate(porc = round(n / sum(n) * 100, 1))
ggplotly(
ggplot(recl_conteo, aes(x = reorder(`Reclutamiento de fuentes`, n),
y = n,
fill = `Reclutamiento de fuentes`)) +
geom_col(alpha = 0.85) +
geom_text(aes(label = paste0(porc, "%")), hjust = -0.1, size = 3.5) +
coord_flip() +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Figura 6. Empleados por Fuente de Reclutamiento",
x = "Fuente",
y = "Número de empleados"
) +
theme_minimal() +
theme(legend.position = "none") +
expand_limits(y = max(recl_conteo$n) * 1.15)
)
Interpretación Figura 6:
Esta figura muestra qué canal de reclutamiento ha aportado más empleados
a la organización. Las empresas suelen priorizar los canales más
efectivos y económicos. Si la “Recomendación de empleados” representa
una proporción alta, indica una cultura organizacional sólida. Si domina
el “Sitio web de empleo”, la estrategia digital es más relevante.
ggplotly(
ggplot(datos, aes(x = Antiguedad_anios)) +
geom_histogram(binwidth = 1, fill = "#FF9800", color = "white", alpha = 0.85) +
labs(
title = "Figura 7. Distribución de la Antigüedad de los Empleados",
x = "Años en la empresa",
y = "Número de empleados"
) +
theme_minimal()
)
Interpretación Figura 7:
El histograma de antigüedad revela la madurez del capital
humano en la organización. Una distribución concentrada en
pocos años indica alta rotación o empresa joven. Una distribución amplia
y equilibrada sugiere estabilidad. Picos en ciertos años pueden
coincidir con épocas de expansión o reestructuración de la empresa.
ggplotly(
ggplot(datos, aes(x = Edad, y = Salario, color = `Registro de desempeño`)) +
geom_point(alpha = 0.7, size = 2) +
geom_smooth(method = "loess", se = FALSE, color = "gray40", linetype = "dashed") +
scale_color_manual(values = c("Arriba" = "#4CAF50",
"Dentro de lo esperado" = "#2196F3",
"Abajo de lo esperado" = "#F44336")) +
labs(
title = paste0("Figura 8. Edad vs. Salario (corr: ",
round(cor(datos$Edad, datos$Salario, use = "complete.obs"), 2), ")"),
x = "Edad (años)",
y = "Salario",
color = "Desempeño"
) +
theme_minimal()
)
Interpretación Figura 8:
Este diagrama de dispersión explora la relación entre la edad del
empleado y su salario, coloreado por nivel de desempeño. El coeficiente
de correlación indica la fuerza y dirección de la relación. Si es
positivo y alto (> 0.5), los empleados mayores tienden a ganar más,
lo que podría reflejar la valoración de la experiencia. Si es bajo o
cercano a cero, el salario no depende fuertemente de la edad.
# Resumen ejecutivo con los principales hallazgos numéricos
cat("=== RESUMEN EJECUTIVO ===\n\n")
## === RESUMEN EJECUTIVO ===
cat("Total de empleados analizados:", nrow(datos), "\n")
## Total de empleados analizados: 207
cat("Distribución por género:\n")
## Distribución por género:
print(table(datos$Sexo_label))
##
## Femenino Masculino
## 117 90
cat("\nSalario promedio general:", round(mean(datos$Salario, na.rm=TRUE), 0), "\n")
##
## Salario promedio general: 6729
cat("Salario mínimo:", min(datos$Salario, na.rm=TRUE),
"| Salario máximo:", max(datos$Salario, na.rm=TRUE), "\n")
## Salario mínimo: 3080 | Salario máximo: 17600
cat("\nDesempeño:\n")
##
## Desempeño:
print(round(prop.table(table(datos$`Registro de desempeño`)) * 100, 1))
##
## Abajo de lo esperado Arriba Dentro de lo esperado
## 7.7 14.0 78.3
cat("\nSatisfacción promedio:", round(mean(datos$`Índice de satisfacción`, na.rm=TRUE), 2),
"/ 5.0\n")
##
## Satisfacción promedio: 3.87 / 5.0
cat("\nAntiguedad promedio:", round(mean(datos$Antiguedad_anios, na.rm=TRUE), 1), "años\n")
##
## Antiguedad promedio: 9.8 años
Con base en el análisis realizado, se pueden destacar las siguientes conclusiones:
Estructura salarial piramidal: La distribución salarial es asimétrica, con la mayoría de empleados en rangos bajos-medios y pocos en rangos altos, lo cual es consistente con una estructura organizacional típica.
Jerarquía salarial por cargo: Los directores y gerentes perciben salarios significativamente más altos que los técnicos y analistas, reflejando la valoración por nivel de responsabilidad.
Estado de desempeño: La mayoría de los empleados se encuentran “Dentro de lo esperado”, con proporciones menores en las categorías extremas. Esto indica una fuerza laboral estable con oportunidades de mejora.
Satisfacción laboral: El índice promedio de satisfacción es superior a 3.5 sobre 5, lo que sugiere un clima laboral moderadamente positivo.
Todos los empleados están activos: La columna
Fecha salida no tiene ningún registro, por lo que la base
corresponde únicamente a empleados activos.
Fecha salida no contiene datos, por lo que
no es posible calcular tasas de rotación ni analizar deserción.dpt1 a
dpt4) sin descripción de su función, lo que dificulta la
interpretación contextual.Fecha salida permitiría calcular tasas de retención y
detectar departamentos con mayor rotación.Análisis realizado con R 4.5.0 | Fundamentos de Programación | mayo 2026