Gender Pay Gap Analysis
Reading salary data
bank_salaries <-read.csv("bank_salaries.csv")
#Glimpse of the data:
skim(bank_salaries)
| Name | bank_salaries |
| Number of rows | 208 |
| Number of columns | 8 |
| _______________________ | |
| Column type frequency: | |
| character | 2 |
| numeric | 6 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| gender | 0 | 1 | 4 | 6 | 0 | 2 | 0 |
| PC_job | 0 | 1 | 2 | 3 | 0 | 2 | 0 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| salary | 0 | 1 | 39921.92 | 11256.15 | 26700 | 33000 | 37000.0 | 44000.00 | 97000 | ▇▃▁▁▁ |
| education | 0 | 1 | 3.16 | 1.47 | 1 | 2 | 3.0 | 5.00 | 5 | ▅▅▇▁▇ |
| job_grade | 0 | 1 | 2.75 | 1.56 | 1 | 1 | 3.0 | 4.00 | 6 | ▇▃▂▂▁ |
| years_bank | 0 | 1 | 9.67 | 6.99 | 2 | 5 | 8.0 | 13.00 | 39 | ▇▃▁▁▁ |
| years_prior | 0 | 1 | 2.38 | 3.14 | 0 | 0 | 1.0 | 4.00 | 18 | ▇▂▁▁▁ |
| age | 0 | 1 | 40.39 | 10.32 | 22 | 32 | 38.5 | 47.25 | 65 | ▅▇▆▃▂ |
Effect of gender on salary
#Looking at mean salaries by gender with confidence intervals
gender_mean_salaries <- bank_salaries %>%
group_by(gender) %>%
summarise(
mean = mean(salary),
SD = sd(salary),
count = n(),
t_critical = qt(0.975, count - 1),
SE = SD / sqrt(count),
margin_of_error = t_critical * SE,
CI_low = mean - margin_of_error,
CI_high = mean + margin_of_error
)
gender_mean_salaries
| gender | mean | SD | count | t_critical | SE | margin_of_error | CI_low | CI_high |
|---|---|---|---|---|---|---|---|---|
| Female | 3.72e+04 | 6.71e+03 | 140 | 1.98 | 567 | 1.12e+03 | 3.61e+04 | 3.83e+04 |
| Male | 4.55e+04 | 1.58e+04 | 68 | 2 | 1.92e+03 | 3.83e+03 | 4.17e+04 | 4.93e+04 |
Since the two intervals do not overlap, it is clear that there is a significant difference in female and male salaries. We now look at contributing factors.
Visualizing Salary progression by Gender
bank_salaries %>%
ggplot() +
geom_point(aes(x = years_bank, y = salary, color=gender, shape=factor(job_grade))) +
geom_smooth(aes(x = years_bank, y = salary, color=gender), method = "lm") +
labs(title = "Difference in Salary progression with experience based on Gender",
x= "Experience in Bank (yrs)",
y = "Salary")
## `geom_smooth()` using formula 'y ~ x'

It can be seen that most women are in lower job grades, while there are more men at grades 5 and 6. It can also be noted that there are men with just 12/ 13 years of experience at grade 6 with salaries around 60000 while women in grade 6 with 36 years of experience might still receive a salary of around 20000.
Regression Models to analyse impact of predictors on slalary
mosaic::favstats (salary ~ gender, data=bank_salaries)
| gender | min | Q1 | median | Q3 | max | mean | sd | n | missing |
|---|---|---|---|---|---|---|---|---|---|
| Female | 2.68e+04 | 3.26e+04 | 3.54e+04 | 4.16e+04 | 6.18e+04 | 3.72e+04 | 6.71e+03 | 140 | 0 |
| Male | 2.67e+04 | 3.44e+04 | 4.25e+04 | 4.86e+04 | 9.7e+04 | 4.55e+04 | 1.58e+04 | 68 | 0 |
model1 <- lm(salary ~ gender , data=bank_salaries)
msummary(model1)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 37209.9 894.5 41.597 < 2e-16 ***
## genderMale 8295.5 1564.5 5.302 2.94e-07 ***
##
## Residual standard error: 10580 on 206 degrees of freedom
## Multiple R-squared: 0.1201, Adjusted R-squared: 0.1158
## F-statistic: 28.12 on 1 and 206 DF, p-value: 2.935e-07
bank_salaries <- bank_salaries %>%
mutate( education = as.factor(education),
job_grade = as.factor(job_grade))
model2 <- lm(salary ~ ., data=bank_salaries)
msummary(model2)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 26930.292 2455.799 10.966 < 2e-16 ***
## education2 -459.564 1402.853 -0.328 0.743575
## education3 519.412 1363.220 0.381 0.703609
## education4 199.212 2415.820 0.082 0.934365
## education5 2724.608 1626.395 1.675 0.095506 .
## job_grade2 1558.467 1189.458 1.310 0.191674
## job_grade3 5236.422 1266.746 4.134 5.32e-05 ***
## job_grade4 8575.398 1501.370 5.712 4.18e-08 ***
## job_grade5 13953.528 1872.157 7.453 2.99e-12 ***
## job_grade6 23967.176 2888.131 8.299 1.80e-14 ***
## years_bank 508.436 99.474 5.111 7.67e-07 ***
## years_prior 152.073 140.535 1.082 0.280559
## age -2.128 57.722 -0.037 0.970634
## genderMale 2650.777 1011.442 2.621 0.009471 **
## PC_jobYes 4970.859 1477.816 3.364 0.000928 ***
##
## Residual standard error: 5666 on 193 degrees of freedom
## Multiple R-squared: 0.7638, Adjusted R-squared: 0.7466
## F-statistic: 44.57 on 14 and 193 DF, p-value: < 2.2e-16
model3 <- lm(salary ~ years_bank + gender + education + job_grade,
data=bank_salaries)
msummary(model3)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 27966.93 1463.97 19.103 < 2e-16 ***
## years_bank 472.44 87.16 5.421 1.73e-07 ***
## genderMale 1810.89 1008.66 1.795 0.0741 .
## education2 -742.01 1407.50 -0.527 0.5987
## education3 704.42 1342.42 0.525 0.6004
## education4 171.97 2467.33 0.070 0.9445
## education5 2646.67 1627.40 1.626 0.1055
## job_grade2 2222.38 1208.22 1.839 0.0674 .
## job_grade3 5578.01 1283.44 4.346 2.22e-05 ***
## job_grade4 9068.03 1531.10 5.923 1.40e-08 ***
## job_grade5 14157.59 1896.60 7.465 2.67e-12 ***
## job_grade6 24608.51 2947.57 8.349 1.23e-14 ***
##
## Residual standard error: 5827 on 196 degrees of freedom
## Multiple R-squared: 0.7463, Adjusted R-squared: 0.7321
## F-statistic: 52.41 on 11 and 196 DF, p-value: < 2.2e-16
model4 <- lm(salary ~ years_bank + gender + job_grade,
data=bank_salaries)
msummary(model4)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 28601.48 1054.03 27.135 < 2e-16 ***
## years_bank 404.62 78.75 5.138 6.58e-07 ***
## genderMale 2011.75 1005.38 2.001 0.0467 *
## job_grade2 2656.22 1183.67 2.244 0.0259 *
## job_grade3 6423.47 1169.34 5.493 1.19e-07 ***
## job_grade4 10511.86 1372.14 7.661 7.78e-13 ***
## job_grade5 16435.21 1546.66 10.626 < 2e-16 ***
## job_grade6 27699.13 2504.49 11.060 < 2e-16 ***
##
## Residual standard error: 5849 on 200 degrees of freedom
## Multiple R-squared: 0.7391, Adjusted R-squared: 0.73
## F-statistic: 80.94 on 7 and 200 DF, p-value: < 2.2e-16
Accounting for interactive variables:
model5 <- lm(salary ~ years_bank*gender, data=bank_salaries)
mosaic::msummary(model5)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 34528.3 1138.0 30.342 < 2e-16 ***
## years_bank 280.0 102.5 2.733 0.00684 **
## genderMale -4098.3 1665.8 -2.460 0.01472 *
## years_bank:genderMale 1247.8 136.7 9.130 < 2e-16 ***
##
## Residual standard error: 6816 on 204 degrees of freedom
## Multiple R-squared: 0.6386, Adjusted R-squared: 0.6333
## F-statistic: 120.2 on 3 and 204 DF, p-value: < 2.2e-16
model6 <- lm(salary ~ years_bank*gender + job_grade, data=bank_salaries)
mosaic::msummary(model6)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 32145.02 989.06 32.501 < 2e-16 ***
## years_bank 52.00 78.64 0.661 0.5092
## genderMale -6106.05 1271.27 -4.803 3.07e-06 ***
## job_grade2 2597.76 1011.26 2.569 0.0109 *
## job_grade3 6221.48 999.26 6.226 2.78e-09 ***
## job_grade4 11050.68 1173.90 9.414 < 2e-16 ***
## job_grade5 15061.14 1330.84 11.317 < 2e-16 ***
## job_grade6 16639.36 2491.68 6.678 2.36e-10 ***
## years_bank:genderMale 1035.00 119.49 8.662 1.60e-15 ***
##
## Residual standard error: 4997 on 199 degrees of freedom
## Multiple R-squared: 0.8105, Adjusted R-squared: 0.8029
## F-statistic: 106.4 on 8 and 199 DF, p-value: < 2.2e-16
While men start with about 6000 lower than women at grade 1, it is possible that they progress faster to higher grades. Men also receive 1035 more than women for every year they are at the bank.
huxreg(model1, model2, model3, model4, model5, model6,
statistics = c('#observations' = 'nobs', 'R squared' = 'r.squared',
'Adj. R Squared' = 'adj.r.squared', 'Residual SE' = 'sigma'),
bold_signif = 0.05, stars = NULL ) %>%
set_caption('Comparison of models')
| (1) | (2) | (3) | (4) | (5) | (6) | |
|---|---|---|---|---|---|---|
| (Intercept) | 37209.929 | 26930.292 | 27966.931 | 28601.475 | 34528.280 | 32145.021 |
| (894.533) | (2455.799) | (1463.973) | (1054.030) | (1137.970) | (989.060) | |
| genderMale | 8295.513 | 2650.777 | 1810.886 | 2011.754 | -4098.252 | -6106.052 |
| (1564.493) | (1011.442) | (1008.662) | (1005.378) | (1665.842) | (1271.268) | |
| education2 | -459.564 | -742.009 | ||||
| (1402.853) | (1407.502) | |||||
| education3 | 519.412 | 704.425 | ||||
| (1363.220) | (1342.418) | |||||
| education4 | 199.212 | 171.966 | ||||
| (2415.820) | (2467.329) | |||||
| education5 | 2724.608 | 2646.671 | ||||
| (1626.395) | (1627.397) | |||||
| job_grade2 | 1558.467 | 2222.379 | 2656.218 | 2597.756 | ||
| (1189.458) | (1208.224) | (1183.668) | (1011.256) | |||
| job_grade3 | 5236.422 | 5578.006 | 6423.473 | 6221.480 | ||
| (1266.746) | (1283.444) | (1169.336) | (999.262) | |||
| job_grade4 | 8575.398 | 9068.034 | 10511.865 | 11050.678 | ||
| (1501.370) | (1531.098) | (1372.136) | (1173.896) | |||
| job_grade5 | 13953.528 | 14157.594 | 16435.206 | 15061.142 | ||
| (1872.157) | (1896.602) | (1546.665) | (1330.839) | |||
| job_grade6 | 23967.176 | 24608.511 | 27699.131 | 16639.360 | ||
| (2888.131) | (2947.572) | (2504.486) | (2491.680) | |||
| years_bank | 508.436 | 472.444 | 404.616 | 279.963 | 51.997 | |
| (99.474) | (87.158) | (78.753) | (102.456) | (78.639) | ||
| years_prior | 152.073 | |||||
| (140.535) | ||||||
| age | -2.128 | |||||
| (57.722) | ||||||
| PC_jobYes | 4970.859 | |||||
| (1477.816) | ||||||
| years_bank:genderMale | 1247.798 | 1034.999 | ||||
| (136.676) | (119.493) | |||||
| #observations | 208 | 208 | 208 | 208 | 208 | 208 |
| R squared | 0.120 | 0.764 | 0.746 | 0.739 | 0.639 | 0.811 |
| Adj. R Squared | 0.116 | 0.747 | 0.732 | 0.730 | 0.633 | 0.803 |
| Residual SE | 10584.260 | 5665.699 | 5826.543 | 5849.143 | 6816.298 | 4997.053 |
Distribution of gender at each job grade level
bank_salaries %>%
group_by(gender, job_grade) %>%
count() %>%
pivot_wider(names_from = gender, values_from = n) %>%
mutate(percent_female = round(100 * Female / (Female+Male), 2),
percent_male = round(100 * Male / (Female+Male), 2))
## # A tibble: 6 × 5
## # Groups: job_grade [6]
## job_grade Female Male percent_female percent_male
## <fct> <int> <int> <dbl> <dbl>
## 1 1 48 12 80 20
## 2 2 29 13 69.0 31.0
## 3 3 36 7 83.7 16.3
## 4 4 17 11 60.7 39.3
## 5 5 9 13 40.9 59.1
## 6 6 1 12 7.69 92.3
bank_salaries %>%
group_by(gender, job_grade) %>%
count() %>%
ggplot(aes(x = job_grade, y=n, fill=gender))+
geom_col(position = "dodge")

Most women are concentrated at lower job grades while the percentage of men clearly exceeds women at higher levels. Possible reasons include women being overlooked for leadership roles and bias against women of certain age groups especially mid-career.