La población del dataset de salarios de Data Science presenta las siguientes características:
Variables Numéricas
work_year: Los datos se extienden principalmente hasta el año 2024, con un promedio en 2023.
salary: Los salarios varían ampliamente, desde 14,000 hasta 30,400,000 (sin especificar la moneda en esta columna).
salary_in_usd: Convertidos a dólares, los salarios oscilan entre 15,000 y 800,000 USD, con una media de aproximadamente 149,875 USD.
remote_ratio: La proporción de trabajo remoto va de 0% (sin trabajo remoto) a 100% (trabajo completamente remoto), con una media de 32.76%.
Variables Categóricas
experience_level: Incluye 4 niveles (por ejemplo, Senior, Mid), siendo el más frecuente el nivel Senior (SE), con 9,696 registros.
employment_type: Predomina el tipo de empleo a tiempo completo (FT), que representa casi toda la población (14,772 registros).
job_title: Existen 153 títulos de puestos, siendo “Data Engineer” el más común (3,162 registros).
salary_currency: Se registran 23 monedas, aunque la mayoría de los salarios están en USD (13,682 registros).
employee_residence y company_location: La mayoría de los empleados residen en EE. UU. (12,926 registros), y las empresas también se localizan principalmente en EE. UU. (12,975 registros).
company_size: Las empresas de tamaño mediano son las más frecuentes (13,674 registros), con otras de tamaño pequeño y grande.
set.seed(975)
DB <- read_csv("DataScience_salaries_2024.csv", show_col_types = FALSE)
DB=as.data.frame(unclass(DB), stringsAsFactors = TRUE)
str(DB)
## 'data.frame': 14838 obs. of 11 variables:
## $ work_year : num 2021 2021 2020 2021 2022 ...
## $ experience_level : Factor w/ 4 levels "EN","EX","MI",..: 3 3 3 3 4 3 4 1 2 1 ...
## $ employment_type : Factor w/ 4 levels "CT","FL","FT",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ job_title : Factor w/ 153 levels "Admin & Data Analyst",..: 90 22 90 131 114 131 87 90 109 145 ...
## $ salary : num 30400000 11000000 11000000 8500000 7500000 7000000 7000000 6600000 6000000 5500000 ...
## $ salary_currency : Factor w/ 23 levels "AUD","BRL","CAD",..: 5 10 10 13 12 13 12 10 12 13 ...
## $ salary_in_usd : num 40038 36259 35735 77364 95386 ...
## $ employee_residence: Factor w/ 88 levels "AD","AE","AM",..: 16 39 39 48 43 48 43 39 43 48 ...
## $ remote_ratio : num 100 50 50 50 50 50 50 100 50 50 ...
## $ company_location : Factor w/ 77 levels "AD","AE","AM",..: 15 75 35 43 39 43 39 35 39 43 ...
## $ company_size : Factor w/ 3 levels "L","M","S": 1 1 1 3 1 3 1 2 1 1 ...
sprintf("El número de filas para la base de datos es: %d", nrow(DB))
## [1] "El número de filas para la base de datos es: 14838"
# Calcular el total de cada nivel en el dataset completo
experience_counts <- table(DB$experience_level)
experience_counts
##
## EN EX MI SE
## 1148 441 3553 9696
Este dataset contiene información sobre salarios de profesionales en ciencia de datos. Algunas de las variables clave que podrían servir para estratificar la muestra son:
experience_level: Nivel de experiencia del empleado (e.g., Junior, Mid, Senior, Experto).
employment_type: Tipo de empleo (e.g., tiempo completo, contrato, freelance).
job_title: Título del puesto (e.g., Data Scientist, ML Engineer).
company_size: Tamaño de la empresa (e.g., pequeña, mediana, grande).
remote_ratio: Nivel de trabajo remoto (0%, 50%, 100%).
# Definir los parámetros
N <- 14838 # Tamaño de la población
Z <- 1.96 # Valor Z para un 95% de nivel de confianza
p <- 0.5 # Proporción estimada
E <- 0.05 # Margen de error
# Calcular el tamaño de muestra
n <- (N * Z^2 * p * (1 - p)) / ((N - 1) * E^2 + Z^2 * p * (1 - p))
n <- ceiling(n) # Redondear al siguiente número entero
# Mostrar el tamaño de muestra
sprintf("La muestra significativa de la población es: %d", n)
## [1] "La muestra significativa de la población es: 375"
# Se saca el tamaño representativo de la muestra del estrato
# n_h = (N_h/N)*n
N = 14838
N_h.EN=nrow(subset(DB, experience_level == "EN"))
n_h.EN= (N_h.EN/N)*n
sprintf("El tamaño de la muestra para el primer estrato es: %s", round(n_h.EN,0))
## [1] "El tamaño de la muestra para el primer estrato es: 29"
N_h.EX=nrow(subset(DB, experience_level == "EX"))
n_h.EX= (N_h.EX/N)*n
sprintf("El tamaño de la muestra para el segundo estrato es: %s", round(n_h.EX,0))
## [1] "El tamaño de la muestra para el segundo estrato es: 11"
N_h.MI=nrow(subset(DB, experience_level == "MI"))
n_h.MI= (N_h.MI/N)*n
sprintf("El tamaño de la muestra para el tercer estrato es: %s", round(n_h.MI,0))
## [1] "El tamaño de la muestra para el tercer estrato es: 90"
N_h.SE=nrow(subset(DB, experience_level == "SE"))
n_h.SE= (N_h.SE/N)*n
sprintf("El tamaño de la muestra para el cuarto estrato es: %s", round(n_h.SE,0))
## [1] "El tamaño de la muestra para el cuarto estrato es: 245"
# Se saca la muestra aleatoria de cada estrato, con el tamaño especificado para cada estrato
# Definir el tamaño de la muestra redondeado para el nivel de experiencia "EN"
tamañomuestra.EN <- round(n_h.EN, 0)
# Filtrar el dataset para el nivel de experiencia "EN" y tomar una muestra aleatoria sin reemplazo
muestra.EN <- DB %>%
filter(experience_level == "EN") %>%
sample_n(size = tamañomuestra.EN, replace = FALSE)
# Mostrar la muestra seleccionada
sprintf("El número de filas para la muestra del primer estrato es: %d", nrow(muestra.EN))
## [1] "El número de filas para la muestra del primer estrato es: 29"
tamañomuestra.EX <- round(n_h.EX, 0)
muestra.EX <- DB %>%
filter(experience_level == "EX") %>%
sample_n(size = tamañomuestra.EX, replace = FALSE)
sprintf("El número de filas para la muestra del segundo estrato es: %d", nrow(muestra.EX))
## [1] "El número de filas para la muestra del segundo estrato es: 11"
tamañomuestra.MI <- round(n_h.MI, 0)
muestra.MI <- DB %>%
filter(experience_level == "MI") %>%
sample_n(size = tamañomuestra.MI, replace = FALSE)
sprintf("El número de filas para la muestra del tercer estrato es: %d", nrow(muestra.MI))
## [1] "El número de filas para la muestra del tercer estrato es: 90"
tamañomuestra.SE <- round(n_h.SE, 0)
muestra.SE <- DB %>%
filter(experience_level == "SE") %>%
sample_n(size = tamañomuestra.SE, replace = FALSE)
sprintf("El número de filas para la muestra del cuarto estrato es: %d", nrow(muestra.SE))
## [1] "El número de filas para la muestra del cuarto estrato es: 245"
# Unión de las muestras para el totala de la muestra estratificada
muestra.estratificada = rbind(muestra.EN, muestra.EX, muestra.MI, muestra.SE)
sprintf("El número de filas para la muestra estratificada es: %d", nrow(muestra.estratificada))
## [1] "El número de filas para la muestra estratificada es: 375"
# Densidad del salario en dolares
options(scipen=10)
plot(density(DB$salary_in_usd, na.rm = TRUE),
main = "Densidad de Salarios",
xlab = "Salario",
ylab = "Densidad",
col = "blue",
lwd = 2)
# Media poblacional
salario_promedio <- mean(DB$salary_in_usd)
sprintf("El salario promedio de la muestra problacional es: %s", round(salario_promedio,2))
## [1] "El salario promedio de la muestra problacional es: 149874.72"
# Densidad de salario en dolares normalizado
options(scipen=10)
DB$salary_log <- log(DB$salary_in_usd)
plot(density(DB$salary_log, na.rm = TRUE),
main = "Densidad de Salarios Normalizada",
xlab = "Salario",
ylab = "Densidad",
col = "blue",
lwd = 2)
# Densidad de la muestra
options(scipen=10)
plot(density(muestra.estratificada$salary_in_usd, na.rm = TRUE),
main = "Densidad de la muestra estratificada de salarios",
xlab = "Salario",
ylab = "Densidad",
col = "green",
lwd = 2)
# Media muestral de la muestra 1
salario_estratificado_promedio <- mean(muestra.estratificada$salary_in_usd)
sprintf("El salario estratificado promedio de la muestra 1 es: %s", round(salario_estratificado_promedio,2))
## [1] "El salario estratificado promedio de la muestra 1 es: 149400.89"
# Densidad de la muestra del salario en dolares normalizado
options(scipen=10)
muestra.estratificada$salary_log <- log(muestra.estratificada$salary_in_usd)
plot(density(muestra.estratificada$salary_log, na.rm = TRUE),
main = "Densidad de la muestra estratificada de Salarios Normalizada",
xlab = "Salario",
ylab = "Densidad",
col = "green",
lwd = 2)
# Densidad de salarios problacionales - muestrales
plot(density(DB$salary_log, na.rm = TRUE),
main = "Densidad de Salarios",
xlab = "Salario",
ylab = "Densidad",
col = "blue",
lwd = 2)
lines(density(muestra.estratificada$salary_log, na.rm = TRUE), col = "red", lwd = 2)
# Agregar una leyenda para identificar cada curva
legend("topright",
legend = c("Salario Poblacional", "Salario Muestral"),
col = c("blue", "red"),
lwd = 2)
# Se saca el tamaño representativo de la muestra del estrato
# n_h = (N_h/N)*n
n2 = 1000
N2 = 14838
N_h.EN2=nrow(subset(DB, experience_level == "EN"))
n_h.EN2= (N_h.EN2/N2)*n2
sprintf("El tamaño de la muestra 2 para el primer estrato es: %s", round(n_h.EN2,0))
## [1] "El tamaño de la muestra 2 para el primer estrato es: 77"
N_h.EX2=nrow(subset(DB, experience_level == "EX"))
n_h.EX2= (N_h.EX2/N2)*n2
sprintf("El tamaño de la muestra 2 para el segundo estrato es: %s", round(n_h.EX2,0))
## [1] "El tamaño de la muestra 2 para el segundo estrato es: 30"
N_h.MI2=nrow(subset(DB, experience_level == "MI"))
n_h.MI2= (N_h.MI2/N2)*n2
sprintf("El tamaño de la muestra 2 para el tercer estrato es: %s", round(n_h.MI2,0))
## [1] "El tamaño de la muestra 2 para el tercer estrato es: 239"
N_h.SE2=nrow(subset(DB, experience_level == "SE"))
n_h.SE2= (N_h.SE2/N2)*n2
sprintf("El tamaño de la muestra 2 para el cuarto estrato es: %s", round(n_h.SE2,0))
## [1] "El tamaño de la muestra 2 para el cuarto estrato es: 653"
# Se saca la muestra aleatoria de cada estrato, con el tamaño especificado para cada estrato
# Definir el tamaño de la muestra redondeado para el nivel de experiencia "EN"
tamañomuestra.EN2 <- round(n_h.EN2, 0)
# Filtrar el dataset para el nivel de experiencia "EN" y tomar una muestra aleatoria sin reemplazo
muestra.EN2 <- DB %>%
filter(experience_level == "EN") %>%
sample_n(size = tamañomuestra.EN2, replace = FALSE)
# Mostrar la muestra seleccionada
sprintf("El número de filas para la muestra 2 del primer estrato es: %d", nrow(muestra.EN2))
## [1] "El número de filas para la muestra 2 del primer estrato es: 77"
tamañomuestra.EX2 <- round(n_h.EX2, 0)
muestra.EX2 <- DB %>%
filter(experience_level == "EX") %>%
sample_n(size = tamañomuestra.EX2, replace = FALSE)
sprintf("El número de filas para la muestra 2 del segundo estrato es: %d", nrow(muestra.EX2))
## [1] "El número de filas para la muestra 2 del segundo estrato es: 30"
tamañomuestra.MI2 <- round(n_h.MI2, 0)
muestra.MI2 <- DB %>%
filter(experience_level == "MI") %>%
sample_n(size = tamañomuestra.MI2, replace = FALSE)
sprintf("El número de filas para la muestra del tercer estrato es: %d", nrow(muestra.MI2))
## [1] "El número de filas para la muestra del tercer estrato es: 239"
tamañomuestra.SE2 <- round(n_h.SE2, 0)
muestra.SE2 <- DB %>%
filter(experience_level == "SE") %>%
sample_n(size = tamañomuestra.SE2, replace = FALSE)
sprintf("El número de filas para la muestra del cuarto estrato es: %d", nrow(muestra.SE2))
## [1] "El número de filas para la muestra del cuarto estrato es: 653"
# Unión de las muestras para el totala de la muestra estratificada
muestra.estratificada2 = rbind(muestra.EN2, muestra.EX2, muestra.MI2, muestra.SE2)
sprintf("El número de filas para la muestra estratificada es: %d", nrow(muestra.estratificada2))
## [1] "El número de filas para la muestra estratificada es: 999"
# Densidad de la muestra 2 del salario en dolares normalizado
muestra.estratificada2$salary_log <- log(muestra.estratificada2$salary_in_usd)
# Media muestral de la muestra 2
salario_estratificado_promedio2 <- mean(muestra.estratificada2$salary_in_usd)
sprintf("El salario estratificado promedio de la muestra 2 es: %s", round(salario_estratificado_promedio2,2))
## [1] "El salario estratificado promedio de la muestra 2 es: 147656.52"
# Varianza de la muestra 1
salario_estratificado_varianza <- var(muestra.estratificada$salary_log)
sprintf("La varianza del salario estratificado de la muestra 1 es: %s", round(salario_estratificado_varianza,2))
## [1] "La varianza del salario estratificado de la muestra 1 es: 0.2"
# Varianza de la muestra 2
salario_estratificado_varianza2 <- var(muestra.estratificada2$salary_log)
sprintf("La varianza del salario estratificado de la muestra 2 es: %s", round(salario_estratificado_varianza2,2))
## [1] "La varianza del salario estratificado de la muestra 2 es: 0.23"
# Calculamos eficiencia varianza.muestra1 < varianza.muestra2
print(sprintf("La varianza de la muestra 1 es %s y la varianza de la muestra 2 es %s, por lo tanto Var.muestra1 < Var.muestra2 lo que nos indica que existe eficiencia en la muestra estratificada con respecto a la segunda muestra.",
round(salario_estratificado_varianza, 2),
round(salario_estratificado_varianza2, 2)))
## [1] "La varianza de la muestra 1 es 0.2 y la varianza de la muestra 2 es 0.23, por lo tanto Var.muestra1 < Var.muestra2 lo que nos indica que existe eficiencia en la muestra estratificada con respecto a la segunda muestra."
Conclusión
Dado que la varianza de la muestra 1 (0.2) es menor que la varianza de la muestra 2 (0.23), se puede concluir que la muestra 1 es más eficiente que la muestra 2 en términos de la precisión de la estimación del parámetro. En el contexto de un muestreo estratificado, esta menor varianza sugiere que la muestra 1 está proporcionando una estimación del parámetro con menor dispersión y, por lo tanto, con mayor exactitud.
Esto indica que la muestra 1, con menor varianza, es más representativa de la población que la muestra 2, lo que valida la eficacia del muestreo estratificado en la muestra 1 para reducir la variabilidad en comparación con la segunda muestra.# Calculamos la consistenta Si la media poblacional es igual a la media muestral
consistencia.muestra1 = ((salario_promedio - salario_estratificado_promedio)/salario_promedio)*100
consistencia.muestra2 = ((salario_promedio - salario_estratificado_promedio2)/salario_promedio)*100
print(sprintf("La consistencia de la muestra 1 es %s y la consistencia de la muestra 2 es %s, lo que nos indica que existe consistencia en la muestra 1 estratificada con respecto a la segunda muestra.",
round(consistencia.muestra1, 2),
round(consistencia.muestra2, 2)))
## [1] "La consistencia de la muestra 1 es 0.32 y la consistencia de la muestra 2 es 1.48, lo que nos indica que existe consistencia en la muestra 1 estratificada con respecto a la segunda muestra."
Conclusión
Dado que los valores de consistencia para la muestra 1 y la muestra 2 son bajos, podemos concluir que ambas muestras estratificadas son consistentes con respecto a la media poblacional de salarios. Esto implica que, a pesar de tener diferentes varianzas y configuraciones, ambas muestras estratificadas son representativas de la población en cuanto al salario promedio.
# Función de verosimilitud para una distribución normal
log_likelihood <- function(par, data) {
mu <- par[1]
sigma <- par[2]
-sum(dnorm(data, mean = mu, sd = sigma, log = TRUE))
}
# Encontrar estimadores de máxima verosimilitud muestra 1
inicializacion <- c(mean(muestra.estratificada$salary_in_usd), sd(muestra.estratificada$salary_in_usd))
estimadores_mle <- optim(par = inicializacion, fn = log_likelihood, data = muestra.estratificada$salary_in_usd)
# Encontrar estimadores de máxima verosimilitud muestra 2
inicializacion2 <- c(mean(muestra.estratificada2$salary_in_usd), sd(muestra.estratificada2$salary_in_usd))
estimadores_mle2 <- optim(par = inicializacion, fn = log_likelihood, data = muestra.estratificada2$salary_in_usd)
# Resultados
cat("Estimador MLE para la media muestra 1:", estimadores_mle$par[1], "\n")
## Estimador MLE para la media muestra 1: 149379.7
cat("Estimador MLE para la desviación estándar muestra 1:", estimadores_mle$par[2], "\n")
## Estimador MLE para la desviación estándar muestra 1: 66647.15
cat("Estimador MLE para la media muestra 2:", estimadores_mle2$par[1], "\n")
## Estimador MLE para la media muestra 2: 147630.6
cat("Estimador MLE para la desviación estándar muestra 2:", estimadores_mle2$par[2], "\n")
## Estimador MLE para la desviación estándar muestra 2: 66658.17
Conclusión
Las estimaciones del MLE para la media y la desviación estándar muestran que ambas muestras representan la población de manera similar. La consistencia entre las medias y desviaciones estándar indica que la estrategia de muestreo utilizada es efectiva para capturar las características centrales de la población. Además, el hecho de que las diferencias sean mínimas sugiere que ambas muestras están bien seleccionadas y son representativas en términos de la tendencia central y dispersión de los datos de salarios.
# Cálculo de la media y la desviación estándar de la muestra 1
media_muestral <- mean(muestra.estratificada$salary_log)
desviacion_muestral <- sd(muestra.estratificada$salary_log)
n <- length(muestra.estratificada$salary_log)
# Cálculo de la media y la desviación estándar de la muestra 2
media_muestral2 <- mean(muestra.estratificada2$salary_log)
desviacion_muestral2 <- sd(muestra.estratificada2$salary_log)
n2 <- length(muestra.estratificada2$salary_log)
# Nivel de confianza muestra 1
nivel_confianza <- 0.95
alpha <- 1 - nivel_confianza
# Nivel de confianza muestra 2
nivel_confianza2 <- 0.95
alpha2 <- 1 - nivel_confianza2
# Valor crítico para un intervalo del 95% (distribución t de Student) de la muestra 1
t_critico <- qt(1 - alpha/2, df = n - 1)
# Valor crítico para un intervalo del 95% (distribución t de Student) de la muestra 2
t_critico2 <- qt(1 - alpha2/2, df = n2 - 1)
# Error estándar de la muestra 1
error_estandar <- desviacion_muestral / sqrt(n)
# Error estándar de la muestra 2
error_estandar2 <- desviacion_muestral2 / sqrt(n)
# Intervalo de confianza de la muestra 1
limite_inferior <- media_muestral - t_critico * error_estandar
limite_superior <- media_muestral + t_critico * error_estandar
# Intervalo de confianza de la muestra 2
limite_inferior2 <- media_muestral2 - t_critico2 * error_estandar2
limite_superior2 <- media_muestral2 + t_critico2 * error_estandar2
cat("Intervalo de Confianza del 95% para la media de la muestra 1: [", limite_inferior, ",", limite_superior, "]\n")
## Intervalo de Confianza del 95% para la media de la muestra 1: [ 11.77368 , 11.86542 ]
Se desea hallar la proporción de empleados que tienen un entry level de la población a partir de la muestra, para ello se va a establecer un intervalo de confianza del 95% y luego comparar la realidad con respecto a la población.
N = 14838
N_h.EN=nrow(subset(DB, experience_level == "EN"))
proporcion_poblacional.EN = N_h.EN/N
print(sprintf("El %s %s de la población son trabajadores que tienen un entry level",round(proporcion_poblacional.EN*100,2),"%"))
## [1] "El 7.74 % de la población son trabajadores que tienen un entry level"
tamaño_muestral = as.numeric(nrow(muestra.estratificada))
n_h.EN = nrow(subset(muestra.estratificada, experience_level == "EN"))
proporcional_muestral.EN = as.numeric(n_h.EN/tamaño_muestral)
valor_critico <- 1.96 #intervalo de confianza del 95%
error_estandar.proporcional = sqrt((proporcional_muestral.EN * (1 - proporcional_muestral.EN)) / tamaño_muestral)
# Intervalo de confianza de la muestra 1
limite_inferior <- proporcional_muestral.EN - valor_critico * error_estandar.proporcional
limite_superior <- proporcional_muestral.EN + valor_critico * error_estandar.proporcional
cat("Con una confianza del 95% podemos inferir que la proporción poblacional de los empleados que se encuentran en un entry level a partir de los datos de la población se encuentra entre un: [", round(limite_inferior*100,2), "%,", round(limite_superior*100,2), "%]\n")
## Con una confianza del 95% podemos inferir que la proporción poblacional de los empleados que se encuentran en un entry level a partir de los datos de la población se encuentra entre un: [ 5.03 %, 10.44 %]
cat("Al compararlo con el valor de la población vemos que el intervalo de confianza es cierto dado a que la proporcion poblacional es de un 7%, ahora revisemos si con un 99% de confianza el intervalo se cierra un poco más")
## Al compararlo con el valor de la población vemos que el intervalo de confianza es cierto dado a que la proporcion poblacional es de un 7%, ahora revisemos si con un 99% de confianza el intervalo se cierra un poco más
valor_critico <- 2.576 #intervalo de confianza del 95%
error_estandar.proporcional = sqrt((proporcional_muestral.EN * (1 - proporcional_muestral.EN)) / tamaño_muestral)
# Intervalo de confianza de la muestra 1
limite_inferior <- proporcional_muestral.EN - valor_critico * error_estandar.proporcional
limite_superior <- proporcional_muestral.EN + valor_critico * error_estandar.proporcional
cat("Con una confianza del 99% podemos inferir que la proporción poblacional de los empleados que se encuentran en un entry level a partir de los datos de la población se encuentra entre un: [", round(limite_inferior*100,2), "%,", round(limite_superior*100,2), "%]\n")
## Con una confianza del 99% podemos inferir que la proporción poblacional de los empleados que se encuentran en un entry level a partir de los datos de la población se encuentra entre un: [ 4.18 %, 11.29 %]
Conclusión El intervalo de confianza a medida que aumenta su severidad (95% a 99%) no se volvió un intervalo más pequeño sino que se aumentó.Esto sucede porque, para ser más seguros de que el verdadero parámetro poblacional está dentro del intervalo, se necesita considerar un rango más amplio de valores.