Code for producing the SoJSM Employment Outlook.

# Instaling and loading required packages

if (!require("tidyverse"))
  install.packages("tidyverse")
if (!require("plotly"))
  install.packages("plotly")

library(tidyverse)
library(plotly)
library(scales)

options(scipen = 999)

# Reading data downloaded from
# 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"))

# Date standardization and data cleaning

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)

# Computing median wages and openings

MedianPay <- median(BAjobs$Pay)
MedianOpenings <- median(BAjobs$Openings)

# Filtering for media jobs
# using SOCS codes. See:
# https://www.bls.gov/oes/current/oes_stru.htm

# Filtering for SoJSM jobs

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"))

# Shortening SOC job titles

Mediajobs$Job <- str_split_i(Mediajobs$Occupation.Title,"    *", 1)

# Formatting media pay data

Job <- "Median"
Pay <- MedianPay
PayLine <- data.frame(Job,Pay)

PayChart <- Mediajobs %>% 
  select(Job,Pay) %>% 
  rbind(PayLine) %>% 
  arrange(desc(Pay))

# Formatting media job openings data

Job <- "Median"
Openings <- MedianOpenings
OpeningsLine <- data.frame(Job,Openings)

OpeningsChart <- Mediajobs %>% 
  select(Job,Openings) %>% 
  rbind(OpeningsLine) %>% 
  arrange(desc(Openings))

# Cleanup

rm(AllData,
   BAjobs,
   Mediajobs,
   OpeningsLine,
   PayLine,
   Job,
   MedianOpenings,
   MedianPay,
   Openings,
   Pay)

# Graphing media pay data

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

# Graphing media openings data 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