Gender Pay Gap en Tecnología

El Gender Pay Gap consiste en la diferencia que existe en promedio en los sueldos de Hombres vs el de las Mujeres.

Hoy en día existen personas que atribuyen lo anterior a una discriminación, mientras que otros dicen que es debido a las decisiones que en promedio los hombres toman vs las de las mujeres.

Como ambas opiniones tienen fundamento, decidí realizar análisis sobre alguna base de datos que me permitiera develar la realidad, fue entonces cuando me encontré con la base de datos de la encuesta que todos los años stackOverflow realiza, lo interesante de esta es que además de recopilar genero y sueldo, recopila muchos otros atributos como: Sistema operativo favorito, lenguajes que programa, años de experiencia etc..

La encuesta la responden personas del rubro tecnológico de todo el mundo y se realiza anualmente, pero nos vamos a concentrar en los datos del años 2018 para Estados Unidos donde los individuos son empleados (no independientes), con sueldo anual entre USD 50.000 y USD 200.000, esto debido a que es donde se contestaron más encuestas y donde se concentra la mayoría de los sueldo.

En este análisis me guiaré solo por herramientas de Advanced Analytics e interpretare sus resultados, pero ustedes, los lectores son libres de debatir sobre el tema.

Evidencia del Salary Gap

Para comenzar, partiré mostrando que efectivamente existe una diferencia en los sueldos promedio Anual de hombres y mujeres:

aux = dataset %>% 
  group_by(Male) %>% 
  summarise(salario = mean(ConvertedSalary,na.rm=T),
            number = n()) %>% 
  filter(!is.na(Male))

ggplot(aux,(aes(Male,salario))) + geom_bar(stat = 'identity', fill = 'dark orange') + ggtitle('Salario Promedio por Genero') + scale_fill_tableau() 

El cual si miramos su distribución, notamos que las mujeres tienen una concentración mayor en sueldos más bajos:

ggplot(filter(dataset,!is.na(Male)),aes(ConvertedSalary,group = Male, fill = Male)) + 
  geom_density(alpha= 0.3,kernel = 'epanechnikov') + 
  ggtitle('Distribucion de Sueldo por Genero')  + 
  scale_fill_tableau() 

Es mas fácil ver este efecto si miramos el logaritmo de los sueldos, donde claramente se ve que el sueldo de las mujeres está mas a la izquierda que el de los hombres:

ggplot(filter(dataset,!is.na(Male)),aes(log10(ConvertedSalary),group = Male, fill = Male)) + 
  geom_density(alpha= 0.3,kernel='epanechnikov') + 
  ggtitle('Distribucion de Log Sueldo por Genero')  + 
  scale_fill_tableau() 

Por ultimo si realizamos un test de medias de una cola, arroja un p-valor = 0, por lo que se puede afirmar que los promedios son significativamente distintos.

t.test(ConvertedSalary ~ Male, filter(dataset,!is.na(Male)),alternative = 'less')
t.test(ConvertedSalary ~ Male, filter(dataset,!is.na(Male)),alternative = 'less')

## 
##  Welch Two Sample t-test
## 
## data:  ConvertedSalary by Male
## t = -8.452, df = 917.2, p-value < 2.2e-16
## alternative hypothesis: true difference in means is less than 0
## 95 percent confidence interval:
##       -Inf -7793.837
## sample estimates:
## mean in group FALSE  mean in group TRUE 
##            95684.52           105363.99

Análisis con Arboles

Para comenzar utilizaremos Machine Learning para encontrar las variables que mejor explican el sueldo de un programador, a ver si aparece el genero.

Podemos ver que las variables más importantes son:

  • YearsCodingProf, Años desarrollando profesionalmente?, donde más de 5 años significa un aumento del sueldo promedio.
  • OperatingSystem, En que sistema operativo Trabajas?, donde Utilizar Windows significa un Aumento en el sueldo Promedio.
  • AssessBenefits2,“Que tan dispuesto estas a compartir acciones con la empresa 1 es más”, donde las personas dispuestas a tener acciones de la empresa, tienen un mayor sueldo promedio.
fitTree = rpart(ConvertedSalary ~ .,dataset)
fancyRpartPlot(fitTree)

Dado que el genero no aparece en el árbol, veamos que diferencias existen entre hombre y mujeres en estas tres variables.

Lo primero que podemos ver es que en promedio las mujeres tienen casi 3 años menos de experiencia programando que los hombres.

aux = dataset %>% 
  group_by(Male) %>% 
  summarise(YearsCodingProf = mean(YearsCodingProf,na.rm=T),
            AssessBenefits2 = mean(AssessBenefits2,na.rm=T),
            number = n()) %>% 
  filter(!is.na(Male))

ggplot(aux,(aes(Male,YearsCodingProf))) + geom_bar(stat = 'identity', fill = 'dark orange') + ggtitle('Años Promedio Programando')

Por otros lado las Mujeres tienen una menor preferencia por tener participación en acciones de la empresa que trabajan:

ggplot(aux,(aes(Male,AssessBenefits2))) + geom_bar(stat = 'identity', fill = 'dark orange') + ggtitle('Preferencia por Acciones de Empresa, Menor es Mayor Preferencia')

Y por ultimo, los hombres en promedio prefieren Windows mientras que las mujeres Apple:

aux = dataset %>%
  filter(!is.na(OperatingSystem) & !is.na(Male) ) %>% 
  group_by(Male,OperatingSystem) %>% 
  summarise(number = n()) %>% 
  group_by(Male) %>% 
  mutate(os_portion = number/sum(number))

ggplot(aux,aes(Male,os_portion, fill = OperatingSystem)) + geom_bar(position = 'stack',stat = 'identity') +
  ggtitle('Porcion de Sistema operativo por Genero') + scale_fill_tableau()

Ahora si intentamos dar vuelta el problema y problema y tratamos de predecir genero en función de las variables a ver en que se diferencian (principalmente, para ver si aparece el sueldo), podemos ver que:

  • La variable que mejor discrimina es AssessJob9, Las Mujeres prefieren ambientes de trabajo inclusivos:
  • En promedio las mujeres tienen menos años programando (Profesional o no profesionalmente) que los hombres.
  • Por ultimo Hobby representa si el encuestado programa por hobby o no, donde en promedio los hombres lo hacen mas a menudo.
fitTree = rpart(Male ~ .,dataset, cp = 0.008)
fancyRpartPlot(fitTree) 

Usando Random Forest

El Random Forest nos permitirá 2 cosas, medir la importancia de las variables en el modelo, esto le realiza midiendo cuanto empeora el modelo cuando no entra la variable al Árbol y por otro lado, simular cuanto cambia el sueldo de una persona si su genero cambia.

Al realizar el análisis de importancia de variables, lo primero que detectamos es que al intentar predecir genero, nuevamente no aparece la variable Genero dentro de las primeras 10, quedando aproximadamente en la posición 60. Para analizar, graficamos las 10 mas importantes en magnitud.

Las 3 de las 4 variables más importantes están relacionadas con años, ya sea de vida o programando, volvemos a ver AssessBeneffits2 y aparecen las personas con cargo de Enginieering.manager, después las variables ya son poco relevantes por lo que nos las veremos.

srv = h2o.init(nthreads = -1)
h2o.aux = mutate_if(dataset,is.ordered,as.character)
dataset.h2o = as.h2o(h2o.aux,destination_frame = "dataset_train")
salary_fit = h2o.randomForest(y = "ConvertedSalary",
                              x = setdiff(colnames(dataset),"ConvertedSalary"),
                              training_frame = dataset.h2o,
                              model_id = "salary_balanced",
                              ntrees = 1000)
h2o.saveModel(salary_fit,'data/models/',force = T)
importance = data.frame(h2o.varimp(salary_fit))
importance = head(importance,10)
ggplot(importance,aes(variable,scaled_importance)) + 
  geom_bar(stat = 'identity',fill='dark orange') + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Lo primero interesante es que los hombres son mas viejos en promedio que las mujeres, un poco más de 1.5 años más viejos:

aux = dataset %>% 
  group_by(Male) %>% 
  summarise(YearsCoding = mean(YearsCoding,na.rm=T),
            YearsCodingProf = mean(YearsCodingProf,na.rm=T),
            Age = mean(Age,na.rm=T),
            number = n()) %>% 
  filter(!is.na(Male))
ggplot(aux,aes(Male,Age)) + geom_bar(stat = 'identity',fill='dark orange') + ggtitle('Edad por Genero')

Al igual que en los años programando profesionalmente, los hombres tienen más años programando (profesional o no profesionalmente)

ggplot(aux,aes(Male,YearsCoding)) + geom_bar(stat = 'identity',fill='dark orange') + ggtitle('Años Programando por Genero')

Al ver lo anterior me pregunté si la diferencia en años programando se debe a la diferencia en edad, por lo que grafiqué cuantos años más tienen los hombres que las mujeres en las 3 dimensiones temporales, podemos ver que esto explica una parte, pero no todo, en particular, al ajustar por edad, los hombres tienen 2 años mas programando y 1.5 más de experiencia en el rubro.

aux = aux %>% 
  select(-number,-Male) %>% 
  summarize_all(diff) %>% 
  gather(Variable,Difference)
ggplot(aux,aes(Variable,Difference)) + geom_bar(stat='identity',fill='dark orange') +ggtitle('Diferencia entre años Hombre y Mujer')

Si vemos los años de experiencia vs la edad, hay un gap que parte a los 20, se estabiliza a los 30 y crece mucho más a los 40.

aux = dataset %>% 
  filter(!is.na(Male) & !is.na(Age) & Age > 20  & Age < 60) %>% 
  group_by(Male,Age) %>% 
  summarize(YearsCoding = mean(YearsCoding,na.rm = T))
ggplot(aux,aes(Age,YearsCoding,group = Male, color = Male)) + geom_line(size=2) + ggtitle('Años de experiencia laboral vs Edad')

Por ultimo si vemos el Salario vs Años de experiencia por genero, vemos que en el comienzo las mujeres tienen marginal mente mejores sueldos que los hombres, pero que después decae comparativamente. (Elimine los puntos con menos de 15 muestras, por que al final había algo extraños en el sueldo de las mujeres,caía mucho)

aux = dataset %>% 
  filter(!is.na(Male) & !is.na(YearsCoding)) %>% 
  group_by(Male,YearsCoding) %>% 
  summarize(ConvertedSalary = mean(ConvertedSalary,na.rm = T),
            q = n()) %>% 
  filter(q >15)
ggplot(aux,aes(YearsCoding,ConvertedSalary,group = Male, color = Male)) + geom_line(size=2) + ggtitle('Sueldo vs Años de experiencia Laboral')

La otra variable que resulto relevante es tener el cargo de Enginieering.manager, estos reciben una renta más alta que el promedio de la muestra:

aux = dataset %>% 
  mutate(DevType_Engineering.manager = DevType_Engineering.manager==1) %>% 
  group_by(DevType_Engineering.manager) %>% 
  summarise(ConvertedSalary = mean(ConvertedSalary,na.rm = T))
ggplot(aux,aes(DevType_Engineering.manager,ConvertedSalary)) + geom_bar(stat='identity',fill='dark orange') +ggtitle('Sueldo Promedio Engineering Manager vs Resto')

Por otro lado es un cargo en el que la porción de hombres que lo tienen con respecto al total de hombres es el doble que la porcion de mujeres en el cargo:

aux = dataset %>% 
  group_by(Male,DevType_Engineering.manager) %>% 
  summarise(number = n()) %>% 
  group_by(Male) %>% 
  mutate(portion = number/sum(number)) %>% 
  filter(!is.na(Male) & DevType_Engineering.manager)
ggplot(aux,aes(Male,portion)) + geom_bar(stat='identity',fill='dark orange') +ggtitle('Porcion de Engineering Manager por Genero')

veamos que atributos se necesitan para lograr este cargo, principalmente para ver si el genero es un atributo predictor.

Para este analisis se eliminaron las variables: ConvertedSalary, DevType_Product.manager, DevType_Csuite.executive.CEO.CTO.etc y HopeFiveYears debido a que aparecían en el árbol pero no correspondían a atributos relacionados a la experiencia o genero.

Vemos que nuevamente tener mas de 5 años de experiencia es la variable más importante, seguida de haber trabajado con AWS.

fitTree = rpart(DevType_Engineering.manager ~ .,select(dataset,
                                                       -ConvertedSalary,
                                                       -DevType_Product.manager,
                                                       -DevType_Csuite.executive.CEO.CTO.etc,
                                                       -HopeFiveYears), cp = 0.008)
fancyRpartPlot(fitTree) 

Al ver quienes han trabajado con AWS, vemos que los hombres tienen más experiencia que las mujeres en esta plataforma:

aux = dataset %>% 
  group_by(Male) %>% 
  summarise(PlatformWorkedWith_AWS = mean(PlatformWorkedWith_AWS,na.rm=T),
            number = n()) %>% 
  filter(!is.na(Male))
ggplot(aux,aes(Male,PlatformWorkedWith_AWS)) + geom_bar(stat = 'identity',fill='dark orange') + ggtitle('Trabajo con AWS por Genero')

Simulación

Por último usando el RandomForest predecimos el sueldo de toda la muestra y luego cambiamos el genero a todas las personas y volvemos a predecir, existe una disminución aproximada de 100 dolares anuales al convertir a un hombre en mujer y también el efecto reciproco de misma magnitud al hacer lo contrario:

aux = dataset %>% 
  filter(!is.na(Male)) %>% 
  group_by(Male) %>% 
  summarize(estimado = mean(as.numeric(estimado)),
            sexo_opuesto = mean(as.numeric(sexo_opuesto))
  ) 
tidy_aux = aux %>% gather(escenario,sueldo_promedio,-Male)
ggplot(tidy_aux,aes(Male,sueldo_promedio,fill= escenario)) + geom_bar(stat='identity', position='dodge') +ggtitle('Sueldo estimado vs Sueldo Estimado con genero Opuesto')

El detalle del grafico:

## # A tibble: 2 x 3
##   Male  estimado sexo_opuesto
##   <lgl>    <dbl>        <dbl>
## 1 FALSE   96298.       96351.
## 2 TRUE   105451.      105325.

Conclusiones

En todas las variables que explican el salario, los hombres en promedio toman decisiones mas rentables que las mujeres, como por ejemplo haber usado AWS, usar Windows o participar con acciones de la empresa o partir mas tempranamente programando, posiblemente como hobby, pero la mas importante de todas es el numero de años de experiencia laboral, que en el caso de las mujeres, para la misma edad, tienen menos experiencia, por otro lado si vemos el sueldo vs los años de experiencia en general hombre y mujeres parten en igualdad de condiciones, pero en el tiempo, los hombres hacen crecer más su salario desde los 10 años de experiencia.

Usando los datos recopilados, me inclino por la postura de que el menor salario es por las decisiones que las mujeres toman desde los 10 años de experiencia, punto el cual corresponde a cuando en promedio tienen 40 años y seguramente ya tienen familia y quieren estar con ella. Aunque es un supuesto dado que esos datos familiares no están en los datos, lo que si algo pasa alrededor de los 40 años.

Me gustaría ver como concluyen ustedes en los comentarios, estaré leyéndolos, me gustaría que se armara una sana discusión entre los lectores. si quieren ver los datos están en mi S3 https://s3.console.aws.amazon.com/s3/buckets/danielfm123-public/proyects/salary-gap/ o en la fuente original https://insights.stackoverflow.com/survey
Como siempre los códigos en github: https://github.com/danielfm123/salary-gap

Si te gustó el artículos, me puedes seguir en facebook.com/geekosas o inscribirte para recibir correos cuando publique nuevos artículos.

También quería agradecer a Christian Villarroel por participar en la confección de este sensible articulo.

Print Friendly, PDF & Email