Code for producing the SoJSM Employment Outlook.
# ============================================================
# 1. Install and load required packages
# ============================================================
if (!require("tidyverse"))
install.packages("tidyverse")
if (!require("plotly"))
install.packages("plotly")
library(tidyverse)
library(plotly)
library(scales)
options(scipen = 999)
# ============================================================
# 2. Read BLS employment projections data and filter to
# bachelor’s-degree entry jobs with little/no experience
# ============================================================
# Data source:
# https://data.bls.gov/projections/occupationProj
AllData <- read.csv("Employment Projections.csv")
BAjobs <- AllData %>%
filter(
Typical.Entry.Level.Education == "Bachelor's degree" &
Work.Experience.in.a.Related.Occupation %in% c("None", "Less than 5 years")
)
# ============================================================
# 3. Clean and standardize wage, openings, and SOC code fields
# ============================================================
BAjobs$Pay <- as.numeric(gsub(",", "", BAjobs$Median.Annual.Wage.2023))
BAjobs$Openings <- BAjobs$Occupational.Openings..2023.2033.Annual.Average * 1000
BAjobs$Occupation.Code <- gsub('"',"",BAjobs$Occupation.Code)
BAjobs$Occupation.Code <- gsub('=',"",BAjobs$Occupation.Code)
# ============================================================
# 4. Compute overall medians for comparison lines in charts
# ============================================================
MedianPay <- median(BAjobs$Pay)
MedianOpenings <- median(BAjobs$Openings)
# ============================================================
# 5. Filter to media-related occupations using SOC codes
# (SoJSM job list)
# SOC reference: https://www.bls.gov/oes/current/oes_stru.htm
# ============================================================
Mediajobs <- BAjobs %>%
filter(Occupation.Code %in% c(
"11-2032",
"11-2033",
"11-2011",
"27-3041",
"27-3042",
"27-3043",
"27-3031",
"27-3023",
"27-1024",
"15-1254",
"15-1255",
"27-2012",
"27-3011",
"27-4032",
"27-4031"
))
# ============================================================
# 6. Shorten occupation titles for cleaner chart labels
# ============================================================
Mediajobs$Job <- str_split_i(Mediajobs$Occupation.Title," *", 1)
# ============================================================
# 7. Prepare data for pay comparison chart (jobs vs median)
# ============================================================
Job <- "Median"
Pay <- MedianPay
PayLine <- data.frame(Job,Pay)
PayChart <- Mediajobs %>%
select(Job,Pay) %>%
rbind(PayLine) %>%
arrange(desc(Pay))
# ============================================================
# 8. Prepare data for openings comparison chart (jobs vs median)
# ============================================================
Job <- "Median"
Openings <- MedianOpenings
OpeningsLine <- data.frame(Job,Openings)
OpeningsChart <- Mediajobs %>%
select(Job,Openings) %>%
rbind(OpeningsLine) %>%
arrange(desc(Openings))
# ============================================================
# 9. Remove intermediate objects to clean workspace
# ============================================================
rm(AllData,
BAjobs,
Mediajobs,
OpeningsLine,
PayLine,
Job,
MedianOpenings,
MedianPay,
Openings,
Pay)
# ============================================================
# 10. Create horizontal bar chart of median pay by job
# ============================================================
PayChart <- PayChart %>%
mutate(Dollars = dollar(Pay))
PayFig <- PayChart %>%
mutate(Job = forcats::fct_reorder(Job, Pay)) %>%
ggplot(aes( x = Pay, y = Job)) +
geom_col(aes(fill = Job != "Median")) +
scale_fill_manual(values = c("#FF7F3E","#384B70"), guide = "none")+
geom_text(aes(label = Dollars),
color = "white",
hjust = 1, nudge_x = -.1) +
theme(
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.title.y = element_blank(),
panel.background = element_blank())
PayFig
# ============================================================
# 11. Create horizontal bar chart of annual openings (in thousands)
# ============================================================
OpeningsChart <- OpeningsChart %>%
mutate(Openings = Openings / 1000)
OpeningsFig <- OpeningsChart %>%
mutate(Job = forcats::fct_reorder(Job, Openings)) %>%
ggplot(aes( x = Openings, y = Job,)) +
geom_col(aes(fill = Job != "Median")) +
scale_fill_manual(values = c("#FF7F3E","#384B70"), guide = "none")+
geom_text(aes(label = Openings),
color = "white",
hjust = 1, nudge_x = -.1) +
theme(
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.title.y = element_blank(),
panel.background = element_blank())
OpeningsFig