1. Introducción

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:

  • ¿Cómo se distribuyen los salarios por cargo y departamento?
  • ¿Existe relación entre el índice de satisfacción y el desempeño?
  • ¿Hay diferencias salariales entre hombres y mujeres?
  • ¿Qué fuente de reclutamiento aporta más empleados?
  • ¿Cuál es el perfil de antigüedad de la empresa?

2. Carga y Comprensión de los Datos

2.1 Instalación y carga de librerías

# 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

2.2 Lectura del archivo Excel

# 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

2.3 Inspección inicial

# 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.


3. Limpieza y Preprocesamiento de Datos

3.1 Detección de valores nulos

# 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

3.2 Detección de duplicados

# 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

3.3 Separación de la columna Salario-Cargo

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

3.4 Creación de nuevas variables útiles

# 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

3.5 Manejo de la columna Fecha salida

# 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.

4. Manipulación y Análisis de Datos

4.1 Análisis por Departamento

# 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

4.2 Análisis por Cargo

# 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

4.3 Análisis por Sexo

# 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

4.4 Análisis de Desempeño

# 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

4.5 Análisis de Reclutamiento

# 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

4.6 Filtrado: empleados con alto desempeño y alta satisfacción

# 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

5. Funciones Propias

Función 1: Resumen estadístico personalizado

# 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: Clasificación de empleados por nivel salarial

# 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

6. Visualización de Datos

Figura 1. Distribución del Salario

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.


Figura 2. Salario promedio por Cargo

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.


Figura 3. Empleados por Departamento y Desempeño

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.


Figura 4. Índice de Satisfacción por Desempeño

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.


Figura 5. Comparación Salarial por Sexo

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.


Figura 6. Fuentes de Reclutamiento

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.


Figura 7. Antigüedad de la Empresa

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.


Figura 8. Edad vs. Salario

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.


7. Hallazgos y Conclusiones

7.1 Hallazgos Principales

# 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

7.2 Conclusiones

Con base en el análisis realizado, se pueden destacar las siguientes conclusiones:

  1. 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.

  2. 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.

  3. 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.

  4. Satisfacción laboral: El índice promedio de satisfacción es superior a 3.5 sobre 5, lo que sugiere un clima laboral moderadamente positivo.

  5. 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.

7.3 Limitaciones de los Datos

  • La columna Fecha salida no contiene datos, por lo que no es posible calcular tasas de rotación ni analizar deserción.
  • No se dispone de información sobre el nivel educativo, lo que limitaría análisis sobre la relación educación-salario.
  • Los departamentos están codificados (dpt1 a dpt4) sin descripción de su función, lo que dificulta la interpretación contextual.
  • El índice de satisfacción tiene solo 9 valores distintos (no es continuo), lo que puede limitar ciertos análisis estadísticos.

7.4 Recomendaciones Futuras

  • Ampliar variables: Incluir nivel educativo, tipo de contrato, ciudad y evaluaciones periódicas permitiría análisis más ricos.
  • Análisis de rotación: Completar la columna Fecha salida permitiría calcular tasas de retención y detectar departamentos con mayor rotación.
  • Seguimiento longitudinal: Registrar cambios de cargo y salario a lo largo del tiempo permitiría construir trayectorias profesionales.
  • Revisión de equidad salarial: Si se detectan diferencias salariales por género para el mismo cargo, se recomienda una auditoría de equidad.
  • Plan de retención: Los empleados con alta satisfacción y alto desempeño deberían identificarse para programas de retención prioritaria.

Análisis realizado con R 4.5.0 | Fundamentos de Programación | mayo 2026