Sacramento City USD Financial and Costing Analysis

Author

Nick Warino, SEIU 1021 Research

Published

November 4, 2024

Show the code
# Load CA Education Summary Data
ca_sum_data_all <- read_csv(here("output_data/2024-05-07_ca_ed_data_rev_and_exp_subs.csv"), show_col_types = FALSE)

ca_yearly_sum_data_analysis <- read_csv(here("output_data/2024-05-07_ca_ed_data_yearly_financial_analysis_data_weighted_averages.csv"), show_col_types = FALSE)

Sacramento_projections_future <- read_excel(here("Districts/Sacramento/raw_data/SacramentoBudgetData.xlsx"), sheet = 1) 

Sacramento_projections_future <- Sacramento_projections_future |> 
  select(-Source) |>
  spread(Type, Value) |>
  mutate(
    Revenue = UnrestrictedRevenue + RestrictedRevenue,
    Expenses = UnrestrictedExpenses + RestrictedExpenses,
    NetRevenue = Revenue - Expenses,
    NetRevenuePerExp = (NetRevenue/Expenses),
    UnrestrictedFundPerExp = (UnrestrictedFund/Expenses)) |>
  gather(Type, Value, 3:14) |> 
  mutate(Value = round(Value,digits=2))
Show the code
labels <- c(
  UnrestrictedFund = "Unrestricted Fund ($ in millions)",
  UnrestrictedFundPerExp = "Unrestricted Fund (% of Total Expenditures)",
  NetRevenue = "Net Revenue ($ in millions)",
  NetRevenuePerExp = "Net Revenue (% of Total Expenditures)",
  Revenue = "Total Revenue (in millions of $)",
  UnrestrictedRevenue = "Unrestricted Revenue (in millions of $)",
  LCFFRevenue = "LCFF Revenue (in millions of $)",
  ClassifiedTotalCompPerRev = "Classified Total Compensation (% of Revenue)",
  ClassifiedSalariesPerRev = "Classified Total Salaries (% of Revenue)", 
  ClassifiedBenefitsPerRev = "Classified Total Benefits (% of Revenue)")
Show the code
DistrictName <- "Sacramento City Unified"

DistrictAcroynm <- "SUSD"

data_hline <- data.frame(hline = c(0, 3))

data_hline_max <- data.frame(hline = c(0, 10))

data_hline_0 <- data.frame(hline = c(0, 0)) 

data_text_min <- data.frame(
  label = c("3% Fund Minimum (CDE Law)"),
  x     = c(2004),
  y     = c(3.5))

data_text_max <- data.frame(
  label = c("10% Fund Cap (EC 42127.01) for 2022-23 (beyond?)"),
  x     = c(2004),
  y     = c(10.5))

data_text_future <- data.frame(
  label = c("Figures after 2024 are \nDistrict projections \n(likely shorting future \nfinances)"),
  x     = c(2024.1),
  y     = c(13))

data_text_future2 <- data.frame(
  label = c("Figures after 2024 are \nDistrict projections \n(likely shorting future \nfinances)"),
  x     = c(2024.1),
  y     = c(60))
Show the code
Sacramento_filtered_all <- ca_sum_data_all |> filter(District=="Sacramento City Unified")

Sacramento_filtered_all_with_future <- Sacramento_filtered_all |> 
  rbind(Sacramento_projections_future)
Show the code
Sacramento_USD_filtered_net_rev_and_urf_exp <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="NetRevenuePerExp" |
    Type=="UnrestrictedFundPerExp") |> 
  mutate(Value = Value*100)

Sacramento_USD_filtered_reserve_fundexp <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="ReserveFundPerExp") |> 
  mutate(Value = Value*100)

Sacramento_USD_filtered_net_rev_and_urf_tot <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="NetRevenue" |
    Type=="UnrestrictedFund")

Sacramento_USD_filtered_ada_tot <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="K12ADA") |> 
  mutate(Value = round(Value, digits=0))

ca_yearly_sum_data_analysis_filtered <- ca_yearly_sum_data_analysis |> 
  filter(
    Type=="NetRevenuePerExp" |
    Type=="UnrestrictedFundPerExp") |> 
  mutate(Summary="CA Mean (Districts with at least 1000 students)") |>
  mutate(Value = Value * 100) |> 
  rename(District="Summary",
         Value="Value") |> 
  relocate(District, .before = "YearEnd")

Sacramento_USD_filtered_revenue <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="Revenue" |
    Type=="UnrestrictedRevenue" |
    Type=="LCFFRevenue") |> 
  # mutate(Value = round(Value, digits=0)) |> 
  arrange(match(Type, c(
    "Revenue", 
    "UnrestrictedRevenue", 
    "LCFFRevenue"))) |> 
  arrange(YearEnd)

Sacramento_USD_filtered_revenue_and_URF <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="Revenue" |
    Type=="UnrestrictedFund") |>
  arrange(match(Type, c(
    "Revenue", 
    "UnrestrictedFund"))) |> 
  arrange(YearEnd)


Sacramento_USD_filtered_classified_exp <- Sacramento_filtered_all_with_future |> 
  filter(
    Type=="ClassifiedTotalCompPerRev" |
    Type=="ClassifiedSalariesPerRev" |
    Type=="ClassifiedBenefitsPerRev") |>
  arrange(match(Type, c(
    "ClassifiedTotalCompPerRev", 
    "ClassifiedSalariesPerRev", 
    "ClassifiedBenefitsPerRev"))) |> 
  mutate(Value = Value * 100) |> 
  arrange(YearEnd)

ca_yearly_sum_data_analysis_filtered_classified_exp  <- ca_yearly_sum_data_analysis |> 
  filter(
    Type=="ClassifiedTotalCompPerRev" |
    Type=="ClassifiedSalariesPerRev" |
    Type=="ClassifiedBenefitsPerRev") |>
  mutate(Summary="CA Mean (Districts with at least 1000 students)") |>
  mutate(Value = Value * 100) |> 
  rename(District="Summary",
         Value="Value") |> 
  relocate(District, .before = "YearEnd")

ca_yearly_sum_data_analysis_filtered_ReserveFundPerExp  <- ca_yearly_sum_data_analysis |> 
  filter(Type=="ReserveFundPerExp") |>
  mutate(Summary="CA Mean (Districts with at least 1000 students)") |>
  mutate(Value = Value * 100) |> 
  rename(District="Summary",
         Value="Value") |> 
  relocate(District, .before = "YearEnd")

ca_yearly_sum_data_analysis_filtered_ada <- 
  ca_yearly_sum_data_analysis |> 
  filter(Type=="K12ADA") |>
  mutate(Summary="CA Total") |>
  rename(District="Summary",
         Value="Value") |> 
  relocate(District, .before = "YearEnd")

Sacramento_USD_filtered_with_state <- bind_rows(
  Sacramento_USD_filtered_net_rev_and_urf_exp, 
  ca_yearly_sum_data_analysis_filtered)

Sacramento_USD_filtered_classified_with_state <- bind_rows(
  Sacramento_USD_filtered_classified_exp, 
  ca_yearly_sum_data_analysis_filtered_classified_exp)

Sacramento_USD_filtered_ada_with_state <- bind_rows(
  Sacramento_USD_filtered_ada_tot, 
  ca_yearly_sum_data_analysis_filtered_ada)

Sacramento_USD_filtered_reserve_with_state <- bind_rows(
  Sacramento_USD_filtered_reserve_fundexp, 
  ca_yearly_sum_data_analysis_filtered_ReserveFundPerExp)

1 Updates

2024-10-31

Sections 4.4, 4.5, and 4.6 have all been updated.

4.4 Includes summary tables for:

  1. Annual Costs (all proposals)
  2. Two-Year Costs (all proposals)
  3. Two-Year Costs (all proposals) with additional costing assumptions

They’ve also been updated to show the costs for both Alternative 2 (2% ranges, 4.25 steps) and 2.1 (2%/4%).

4.5. Same as before, just with both Alt 2 and Alt 2.1

4.6 New section, includes all our proposed salary schedule fixes after 2% raise.

2024-10-17

  • Added 4 new salary schedule idea.
  • Created 2-year costing summary table and plots of all economic proposals
  • Added section comparing distributional analysis of all 6 salary schedule fixes.

2024-10-15

  • New costing analysis for SEIU 1021’s 3 new salary schedule ideas.
  • Updated financial analysis to include 2023-24 Unaudited Actuals. Previous analysis was based on Estimated Actuals from 2024-07-01 Adopted Budget. The financial situation radically flipped from record deficit and rapidly declining reserves to near-record surplus and record reserves.
  • Added two new parts to our staff breakdown:
    • Count of how many employees are in each job title, sorted by salary range.
    • Count of how many employees are in each salary range, sorted by job title.

2024-09-12

  • Spoke with management and clarified base pay data. They are unable to produce fully clean data, so both sides agree to proceed by having me match the roster to the main salary schedule itself (for those on it), and use existing hourly base pay for everyone else. Then use that as the base to cost out everything. I will proceed with this method.

2024-09-06

  • Ran into another issue. Even base pay data is inconsistent. Some members within same salary schedule, with same range and step, have different base pay. Some have different rates from salary schedule. Found 630 Emp ID that have differing base pays from what’s listed on salary schedule. I emailed management to get clarification.
  • Regardless, I costed out everything as of now. Once I get clarification and updated data, will swap out the data and re-cost. Should have some but not a huge impact.
  • However, can’t cost $20 min wage proposal, as several of the disparities involve exactly $20 pay. I will need to wait for clarification.

2024-09-04

  • Salary Schedule data provided. I can now proceed.

2024-08-12

  • Management emails me with corrected wage data. The previous wage data included wage differentials, of which not all are affected by new salary schedule. Accordingly, they provided base wage data for all employees. I will use this data to cost the new salary schedule and the across the board raises.
  • Unfortunately, they did not answer questions about salary schedule data so I’m unable to proceed.

2024-08-08

  • Costed management’s squared salary schedule.
  • After presenting to Casey and Hari, I realized I costed the squared salary schedule incorrectly. I applied the new proposed schedules to all Emp ID on the roster, but it only applied to a subset, because there are 9 different salary schedules. I emailed management to get a list of which schedules are affected by the new proposal.
  • I also realized other oddities in the wage data provided. The hourly wage data was inconsistent by Range and Step, both among alike members and between members and the salary schedule.

2024-08-07

  • Costed our proposal.

2024-08-06

  • Updated the financial analysis to include the 2023-24 Budget.
  • Deleted old costing analysis from Fall and Winter 2023
  • Started new costing analysis

2 Financial Analysis

2.1 Sacramento City Unified finances declined, but are still among healthiest levels ever.

The two primary measurements of a District’s financial health are its net-revenues (revenue minus expenditures) and its ending unrestricted reserve fund balance. Both measurements can be expressed as a percentage of total expenditures.

The budget situation dramatically changed in just two months since the adopted budget (July 1). The adopted budget includes their “Estimated Actuals” for 2023, but the “Unaudited Actuals” contain much more final numbers (only “audited actuals” are more accurate, which don’t happen every year and come out well later). The more accurate numbers contained much better news:

  1. $59m total deficit turns into $40 surplus.
  2. Unrestricted Ending Balance grows from $78m to $172.
Show the code
actualexp <- Sacramento_USD_filtered_net_rev_and_urf_exp |> filter(YearEnd<=2024)
projectedexp <- Sacramento_USD_filtered_net_rev_and_urf_exp |> filter(YearEnd>=2024)

Sacramento_USD_filtered_net_rev_and_urf_tot_divided_by_mil <- Sacramento_USD_filtered_net_rev_and_urf_tot |> mutate(
  Total = round(Value/1000000, digits=1))

actualtot <- Sacramento_USD_filtered_net_rev_and_urf_tot_divided_by_mil |> filter(YearEnd<=2024)
projectedtot <- Sacramento_USD_filtered_net_rev_and_urf_tot_divided_by_mil |> filter(YearEnd>=2024)
Show the code
Sacramento_USD_filtered_net_rev_and_urf_exp |> 
  ggplot(aes(
    x=YearEnd,
    y=Value)) +
  geom_line(linetype=1,
            data=actualexp,
            size=.5,
            color="grey",
            show.legend = FALSE) +
  geom_line(linetype=2,
            data=projectedexp,
            size=.5,
            color="grey",
            show.legend = FALSE) +
  geom_vline(xintercept=2024) +
  geom_text(
    data = data_text_future,
    mapping = aes(
      x = x, 
      y = y, 
      label = label, 
      hjust="left"),
      family = "Avenir Next Condensed") +
  geom_label(
    aes(label=paste(round(Value)), color=Value<0),
    size = 4,
    family = "Avenir Next Condensed",
    fontface="bold",
    show.legend=FALSE) +
  facet_wrap(vars(Type),
             ncol=1,
             scales = "free",
             labeller = labeller(Type = labels)) +
  scale_x_continuous(
    limits=c(2004,2027),
    breaks=c(2004,2008,2012,2016,2020,2024)) +
  xlab("Year End") +
  scale_colour_manual(values=c("black","red")) +
  labs(title = "Sacramento USD: Financial History and Projected Future",
         subtitle = "Sacramento City Unified Ended 2024 With Healthy Finances Yet Again",
         caption = "Created by Nick Warino at SEIU 1021 Research Department on 2024-08-08.\nData comes from CDE SACS files, SCUSD's unaudited actuals") +
  My_Theme_NoY()

Below is the same graph as above, but presented with raw dollar totals instead of percentage of expenditures.

Show the code
Sacramento_USD_filtered_net_rev_and_urf_tot_divided_by_mil |>
  ggplot(aes(
    x=YearEnd,
    y=Value)) +
  geom_line(linetype=1,
            data=actualtot,
            size=.5,
            color="grey",
            show.legend = FALSE) +
  geom_line(linetype=2,
            data=projectedtot,
            size=.5,
            color="grey",
            show.legend = FALSE) +
  geom_vline(xintercept=2024) +
  geom_text(
    data = data_text_future2,
    mapping = aes(
      x = x, 
      y = y, 
      label = label, 
      hjust="left"),
      family = "Avenir Next Condensed") +
  geom_label(
    aes(label=sprintf("%.0f", Total), color=Value<0),
    size = 4,
    family = "Avenir Next Condensed",
    fontface="bold",
    show.legend=FALSE) +
  facet_wrap(vars(Type),
             ncol=1,
             scales = "free",
             labeller = labeller(Type = labels)) +
  scale_x_continuous(
    limits=c(2004,2027),
    breaks=c(2004,2008,2012,2016,2020,2024)) +
  scale_colour_manual(values=c("black","red")) +
  xlab("Year End") +
  labs(title = "Sacramento USD: Financial History and Projected Future",
         subtitle = "Sacramento City Unified Ended 2024 With Healthy Finances Yet Again",
         caption = "Created by Nick Warino at SEIU 1021 Research Department on 2024-08-08.\nData comes from CDE SACS files, SCUSD's unaudited actuals") +
  My_Theme_NoY()

2.2 Attendance History: An Unjustified Source of District Fearmongering

School Districts like to point to declining attendance and then scare school workers and the public about impending financial doom. The problem with this narrative is: 1) declining attendance is a State-wide problem, not a District-wide problem, 2) because of 1, the State has been drastically increasing the amount of funding per student, resulting in overall rising revenue despite falling attendance.

Show the code
Sacramento_USD_filtered_ada_tot |>
  ggplot(aes(
    x=YearEnd,
    y=Value)) +
  geom_line(size=.5) +
   geom_point() +
  geom_label(
    aes(label=paste(Value)),
    size = 4,
    family = "Avenir Next Condensed",
    fontface="bold",
    show.legend=FALSE) +
  scale_x_continuous(
    limits=c(2004,2024),
    breaks=c(2004,2006,2008,2010,2012,2014,2016,2018,2020,2022)) +
  xlab("Year End") +
  scale_colour_manual(values=c("grey","purple")) +
  labs(title = "Sacramento USD: K-12 ADA History",
       subtitle = "Note: Does not include Charter school ADA",
       caption = "Created by Nick Warino at SEIU 1021 Research Department on 2022-10-04.\nData comes from CDE SACS files") +
  My_Theme_NoY() + # show legend on top
  theme(legend.position = "top")

Show the code
Sacramento_USD_filtered_ada_YoY_with_state <-  Sacramento_USD_filtered_ada_with_state |>
  group_by(District) |>
  mutate(Value = ((Value/lag(Value) - 1) * 100))

Sacramento_USD_filtered_ada_YoY_with_state |>
  ggplot(aes(
    x=YearEnd,
    y=Value)) +
  geom_line(
    aes(color=District),
    size=.5) +
  geom_point() +
  geom_hline(data = data_hline_0,
             aes(yintercept = hline),
             linetype=1,
             color = "grey",
             show.legend = FALSE) +
  scale_x_continuous(
    limits=c(2004,2022),
    breaks=c(2004,2006,2008,2010,2012,2014,2016,2018,2020,2024)) +
  xlab("Year End") +
  scale_colour_manual(values=c("grey","purple")) +
  labs(title ="Sacramento USD: K-12 ADA (Annual % Change) History",
       subtitle = "Note: Does not include Charter school ADA",
       caption = "Created by Nick Warino at SEIU 1021 Research Department on 2023-08-29.\nData comes from CDE SACS files") +
  My_Theme_WithY() + # show legend on top
  theme(legend.position = "top")

This suggests that future District finances are much more tied to State TK-14 finances than they are to local ADA trends.

To see more clearly that K-12 finances are improved despite declining ADA, look at the following graph. The graph below compares Sacramento’s net-revenue and unrestricted fund balance to the CA statewide average. Both SCUSD and the State have seen flat or declining ADA since 2008, but both have also seen improving finances since 2008.

Show the code
Sacramento_USD_filtered_with_state |>
  ggplot(aes(
    x=YearEnd,
    y=Value)) +
  geom_line(aes(color=District),
    size=.5) +
   geom_point(aes(color=District)) +
  geom_hline(yintercept = 0, color = "grey") +
  facet_wrap(vars(Type),
             ncol=1,
             scales = "free",
             labeller = labeller(Type = labels)) +
  scale_y_continuous(
    limits=c(-10,30)) +
  scale_x_continuous(
    limits=c(2004,2023),
    breaks=c(2004,2006,2008,2010,2012,2014,2016,2018,2020,2022)) +
  xlab("Year End") +
  ylab("% of Total Expenditures") +
  scale_colour_manual(values=c("grey","purple","black")) +
  labs(title = "Sacramento USD: Financial History",
         subtitle = "Despite declining ADA, both the State and SCUSD have improving finances since 2008",
         caption = "Created by Nick Warino at SEIU 1021 Research Department on 2023-08-29.\nData comes from CDE SACS files") +
  My_Theme_WithY() + # show legend on top
  theme(legend.position = "top")

3 Roster Analysis

Show the code
# Load TPF
tpf <- readxl::read_xlsx(here("Districts/Sacramento/raw_data/2024-08-12 - RFI - Total Payroll Factor.xlsx"))

# Define the file path
file_path <- here("Districts/Sacramento/raw_data/2024-08-06 - Salary Schedule.xlsx")

# Read each tab into a separate data frame
salary_schedule_mgmt_2022_23_current <- read_xlsx(file_path, sheet = 1)
salary_schedule_mgmt_2023_24_increase_4_percent <- read_xlsx(file_path, sheet = 2)
salary_schedule_mgmt_2024_25_correction <- read_xlsx(file_path, sheet = 3)
salary_schedule_mgmt_2024_25_increase_2_percent <- read_xlsx(file_path, sheet = 4)

# Rename all Range columns to Range
salary_schedule_mgmt_2022_23_current <- salary_schedule_mgmt_2022_23_current %>%
  rename(Range = RANGE)

salary_schedule_mgmt_2023_24_increase_4_percent <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  rename(Range = RANGE)

salary_schedule_mgmt_2024_25_correction <- salary_schedule_mgmt_2024_25_correction %>%
  rename(Range = RANGE)

salary_schedule_mgmt_2024_25_increase_2_percent <- salary_schedule_mgmt_2024_25_increase_2_percent %>%
  rename(Range = RANGE)

# salary_schedules <- 
Show the code
tpf_summary <- tpf %>%
  summarise(
    Taxes = median(as.numeric(`Percentage allocated to Taxes`), na.rm = TRUE),
    Pension = median(as.numeric(`Percentage allocated Retirement`), na.rm = TRUE),
    Other = median(as.numeric(`Percentage allocated to Additonal deductions`), na.rm = TRUE)) %>%
  mutate(Combined = Taxes + Pension + Other)

# Pull Combined value and save as `tpf_median`
tpf_median <- tpf_summary$Combined + 1

tpf_summary_2 <- tpf %>%
  summarise(
    Taxes = mean(as.numeric(`Percentage allocated to Taxes`), na.rm = TRUE),
    Pension = mean(as.numeric(`Percentage allocated Retirement`), na.rm = TRUE),
    Other = mean(as.numeric(`Percentage allocated to Additonal deductions`), na.rm = TRUE)) %>%
  mutate(Combined = Taxes + Pension + Other)

# Pull Combined value and save as `tpf_median`
tpf_mean <- tpf_summary_2$Combined + 1
Show the code
# Load roster
roster <- readxl::read_xlsx(here("Districts/Sacramento/raw_data/2024-08-12 - Roster.xlsx"))
roster_temp <- readxl::read_xlsx(here("Districts/Sacramento/raw_data/2024-09-04 - Roster_Temp20.xlsx"))
roster$`Seniority Date` <- as.Date(as.numeric(roster[[17]]), origin = "1899-12-30")

colnames(roster)[c(1,2,3,6,7,9,15)] <- c("Emp ID", "Dept", "Job Class Title", "SalarySchedule", "Range", "Hourly Wage Base", "Annual Hours Paid")

# Select
roster <- roster %>%
  select(`Emp ID`, Dept, `Job Class Title`, `SalarySchedule`, Range, `Hourly Wage Base`, `Annual Hours Paid`, FTE) %>%
  separate(Range, into = c("Range", "Step"), sep = "/", remove = FALSE) %>%
  mutate(
    Range = as.numeric(Range),
    Step = as.numeric(Step)
  )

# Tidy roster_temp
roster_temp <- roster_temp %>%
  select(`Emp Id`, Range, Step) |>  # rename Emp Id to Emp ID
  rename(`Emp ID` = `Emp Id`) |> # filter out rows with Range = 1
  filter(Range != 1)

# In `roster`, for all rows where `SalarySchedule` is TEMP20H or TEMP20M, replace `Range` and `Step` with values from `roster_temp`
roster <- roster %>%
  left_join(roster_temp, by = "Emp ID") %>%
  mutate(
    Range = case_when(
      SalarySchedule %in% c("TEMP20H", "TEMP20M") ~ Range.y,
      TRUE ~ Range.x
    ),
    Step = case_when(
      SalarySchedule %in% c("TEMP20H", "TEMP20M") ~ Step.y,
      TRUE ~ Step.x
    )
  ) %>%
  select(-ends_with(".x"), -ends_with(".y"))
Show the code
# Look for rows that have matching Range and Step, but different Hourly Wage Base
same_range_and_step_diff_pay <- roster %>% # round to 2 decimal places
  mutate(`Hourly Wage Base` = round(`Hourly Wage Base`, 2)) %>%
  group_by(Range, Step) %>%
  filter(n_distinct(`Hourly Wage Base`) > 1) %>%
  arrange(Range, Step, `Hourly Wage Base`)
Show the code
# Match all employees Emp ID to current salary schedule by RANGE and STEP. Pull in wage was "SS Base Wage"

salary_schedule_long_mgmt_2022_23_current <- salary_schedule_mgmt_2022_23_current %>%
  pivot_longer(
    cols = starts_with("Step"),
    names_to = "Step",
    values_to = "SS Base Wage"
  ) %>%
  mutate(Step = as.numeric(gsub("Step", "", Step)))

# Split roster into "main" salary schedule ("C-H", "C-M", "C-M2", "IAC-H", "IAC-M", "TEMP20H", "TEMP20M", "SPECIAL3") and "other" salary schedules. Main being "roster_analyzed_1" and "other" being "roster_analyzed_2". Then after joining SS Base Wage to "roster_analyzed_1", create roster_with_SS_pay, which combines "roster_analyzed_1" and "roster_analyzed_2" into one roster.

roster_analyzed_1 <- roster %>%
  filter(`SalarySchedule` %in% c("C-H", "C-M", "C-M2", "IAC-H", "IAC-M", "TEMP20H", "TEMP20M", "SPECIAL3")) %>%
  left_join(salary_schedule_long_mgmt_2022_23_current, by = c("Range", "Step")) %>%
  mutate(`SS Diff` = round(`SS Base Wage` - `Hourly Wage Base`, digits = 2)) |> # round Hourly Wage Base to 0 decimal places
  mutate(`Hourly Wage Base` = round(`Hourly Wage Base`, 2)) |> # sourt by `SS Diff` Descending
  arrange(desc(`SS Diff`))

roster_analyzed_2 <- roster %>%
  filter(!`SalarySchedule` %in% c("C-H", "C-M", "C-M2", "IAC-H", "IAC-M", "TEMP20H", "TEMP20M", "SPECIAL3"))

roster_with_SS_pay <- bind_rows(roster_analyzed_1, roster_analyzed_2)

# In roster_with_SS_pay$`SS Base Wage`, replace NA with value from roster_with_SS_pay$`Hourly Wage Base`
roster_with_SS_pay$`SS Base Wage` <- ifelse(is.na(roster_with_SS_pay$`SS Base Wage`), roster_with_SS_pay$`Hourly Wage Base`, roster_with_SS_pay$`SS Base Wage`)


# filter out rows where `SS Diff` is not between -.01 and .01
roster_SS_diff <- roster_analyzed_1 %>%
  filter(`SS Diff` < -.01 | `SS Diff` > .01)
Show the code
# Calculate annual salary for each employee (row) by multiplying hourly wage by annual hours and FTE
roster_with_SS_pay <- roster_with_SS_pay %>%
  mutate(Annual_Salary = `SS Base Wage` * `Annual Hours Paid` * FTE) |> # Sort Descending by Annual Salary
  arrange(desc(Annual_Salary))
# 
# # Calculate average for Hourly Wage, Annual Hours Paid, FTE, and Annual Salary, ignore NA, save as tibble, display as kable table
# roster_with_SS_pay %>%
#   summarize(across(`SS Base Wage`:`Annual_Salary`, mean, na.rm = TRUE)) %>%
#   as_tibble() %>%
#   kable()
Show the code
# Visualize the distribution of annual salaries
roster_with_SS_pay %>%
  ggplot(aes(x = Annual_Salary)) +
  geom_histogram(bins = 30, fill = "purple", color = "black") +
  labs(title = "Distribution of Annual Salaries for \nSCUSD SEIU Bargaining Unit (2024-07-26)",
       x = "Annual Salary ($)",
       y = "Number of Employees") +
  My_Theme_WithY()

Show the code
# Create lolipop graph ranking all average Annual Salaries by Job Class Title
roster_with_SS_pay %>%
  group_by(`Job Class Title`) %>%
  summarize(Avg_Annual_Salary = mean(Annual_Salary)) %>%
  ggplot(aes(x = reorder(`Job Class Title`, Avg_Annual_Salary), y = Avg_Annual_Salary)) +
  geom_point(color = "purple", size = 3) +
  geom_segment(aes(xend = `Job Class Title`, yend = 0), color = "purple") +
  coord_flip() +
  labs(title = "Average Annual Salary by Job Class Title (2024-07-26)",
       x = "Job Class Title",
       y = "Average Annual Salary ($)") +
  My_Theme_WithY() + # Change Y Axis Text to font size 8
  theme(axis.text.y = element_text(size = 10))

3.0.1 Job Class Titles by Range (NEW)

To get a first glance at how many members might be impacted by any discontinues in the salary schedule, I counted up all unique Job Class titles by Range.

Highlights:

  • When a Job Class moves up a level (e.g. Applications Spec I > II > III), they don’t necessary up to the next Range. Usually they go up several ranges (57 > 65 > 72 in the case of App. Spec.). This pattern isn’t always true though. Office Tech has 4 levels, going from Ranges 39 > 41 > 42 > 43.
Show the code
# I want a count of all roster_analyzed_1$`Job Class Titles` by Range. I want it displayed as a kable.
roster_analyzed_1 %>%
  count(`Job Class Title`, Range) %>% # add scroll box
  kable(format = "html", escape = FALSE, align = c("l", "r", "r"), caption = "Count of Job Class Titles by Range") %>%
  scroll_box(width = "100%", height = "500px")
Count of Job Class Titles by Range
Job Class Title Range n
Accounting Specialist 49 3
Accts Payable Lead Technician 51 1
Adm & Family Svcs Tech 42 5
Adult Ed Customer Rel Clk 35 1
Adult Ed Specialist 50 1
Adult Edctn Testing Proctor 41 3
Applications Spec I 57 2
Applications Spec II 65 2
Applications Spec III 72 5
Assessment Technician 46 2
Assessor-Translator MOC 48 10
Attendance Tech I 33 1
Attendance Tech I 38 2
Attendance Tech II 41 15
Automotive Service Attendant 37 2
Bus Attendant 29 11
Bus Vehicle Mechanic 53 6
Buyer I 41 1
Buyer II 47 1
Buyer III 65 1
Campus Monitor 34 53
Campus Supervisor I 37 1
Career Information Technician 39 6
Certified Occup Therapy Asst 55 3
Child Care Attendant, Chld Dev 29 32
Child Dev Data Info Tech 50 1
Child Dev Spec I 42 9
Child Develop Prgms Tech 48 1
Child Welfare & Att Spec 46 2
Child Welfare & Attnd Liaison 46 4
Clerk I 29 10
Clerk II 33 58
Clerk III 38 6
Clerk III 42 1
Construction/Bond Accntng Spec 69 1
Controller-Bookkeeper HS 48 6
Controller/Bkkpr Adult Ed. 49 1
Custodian 34 100
Custodian NA 2
Customer Service Specialist 38 4
Education Entrepreneur 66 4
Educational Assistant 39 2
Educational Assistant 43 2
Employee Benefit Tech 45 2
Employment Coach SpEd 45 4
FACE Technician 48 1
Facilities Project Tech 68 1
Family Partnership Facilitator 51 2
Fiscal Services Tech I 44 5
Food Prod Asst, Cent Kit 36 18
Food Prod Lead Cent Kitchen 40 4
Food Service Assistant 35 235
Food Service Assistant NA 1
Food Service Lead, Comp HS 39 5
Food Service Lead, School Site 37 74
Foster Youth Srvs Prog Assct 51 4
Fund Spec 52 6
Gang Violence Prev/Intrvntn Sp 70 1
Gang Violence Prev/Intrvntn Sp 100 1
HAZMAT Risk Comp Lead Worker 78 1
Health Aide 35 6
Health Aide 41 1
Health Aide 47 1
Health Aide, Spec Ed 35 1
Health Aide, Spec Ed 41 1
Health Aide, Spec Ed 47 3
Health Services Clerk 38 4
Health Services Technician 42 3
IEP Desig Inst Para-Sp Ed 29 4
IEP Desig Inst Para-Sp Ed 33 3
IEP Desig Inst Para-Sp Ed 37 3
IEP Desig Inst Para-Sp Ed 41 7
Inst Aid, Comp Lab 39 3
Inst Aid, Spec Ed 29 86
Inst Aid, Spec Ed 33 70
Inst Aid, Spec Ed 34 1
Inst Aid, Spec Ed 37 30
Inst Aid, Spec Ed 41 65
Inst Aid, Spec Ed NA 2
Inst Aide Child Dev 29 2
Inst Aide Child Dev 33 5
Inst Aide Child Dev 37 7
Inst Aide Child Dev 41 15
Inst Aide Child Dev NA 1
Inst Aide/Computer Lab Asst 35 1
Instructional Aide 29 17
Instructional Aide 32 5
Instructional Aide 36 2
Instructional Aide 40 12
Instructional Aide (TK) 29 8
Instructional Aide (TK) 32 18
Instructional Aide (TK) 36 3
Instructional Aide (TK) 40 2
Interp for the Deaf 56 5
Job Developer, Employment Svcs 46 2
Lead Campus Supervisor 45 20
Lead Payroll Tech 51 2
Lead Print Shop Technician 58 1
Library Media Tech Asst 41 5
Library Service App Specialist 55 3
Linked Learning/CTP Pgm Tech 48 1
Materials Lab and Mail Tech 52 1
Matric & Orient Cntr Spec 50 2
Medi-Cal Rmbrsmnt Prog Spclst 69 1
Mgmt Information Tech 47 2
Morning Duty 29 12
NUTRI SERV PROGRAM SPECIALIST 56 2
Network Spec III 74 1
Network Specialist I 60 1
Noon Duty 29 177
Noon Duty 30 1
Noon Duty 33 1
Noon Duty NA 3
Nut Svc Inv Con Fac 45 2
Nutr Serv Purch and Wrhse Spec 54 2
Nutri Services Program Tech II 50 1
Occupational Therapist 88 14
Office Tchncn I 39 1
Office Tchncn II 41 18
Office Tchncn III 42 33
Office Technician IV 43 8
Ombudsperson 51 2
Parent Advisor 46 11
Pers Tech II 49 6
Personnel Tech I 42 3
Pest Control Specialist 59 2
Pgm Records Tech, CAMS 45 4
Pgm Records Tech-P&C 45 2
Print Shop Tech II 45 1
Professional Development Spec 73 1
Program Rec Tech SpEd 45 1
Prsnl Tech, Substitute Srvs 51 2
Pupil Personnel Records Tech 34 1
Registered Behavior Technician 47 7
Registrar 41 1
Registrar 53 12
Risk Management Specialist 51 1
School Community Liaison 34 2
School Community Liaison 38 1
School Intervention Staff Asst 42 1
School Office Manager I 44 48
School Office Manager II 44 11
School Office Manager III 45 10
Security Officer 46 5
Site Cmptr Suprt Tech I 45 2
Site Cmptr Suprt Tech II 53 3
Spec Progr & Advanced Learning 51 1
Special Ed Applications Spclst 55 4
Speech-Lang Pathology Asst 55 3
Student and Family Support 65 2
Swimming Pool Custodian 35 4
Teacher Assistant, Bilingual 37 25
Teacher Assistant, Bilingual 39 9
Teacher Asst Bil I - Spanish 39 1
Teacher Asst Bil II - Spanish 37 1
Tech Support Spec I 53 1
Tech Support Spec II 59 7
Tech Support Spec III 67 1
Trans Over-Enrollment Tech 45 1
Trans Parts-Inv Cntrl Wrkr 45 1
Transition Asst SpEd 45 2
Transportation Lead Mechanic 55 2
Transportation Scheduler/Disp 46 4
Transportation Svcs Tech 42 1
Transportation Trip Scheduler 42 1
Van Driver 36 5
Walking Attendant 29 4
Warehouse Records Clerk 41 1
Warehouse Worker 48 14
Webmaster/Comm Spec 72 1
Youth Services Pgm Associate 51 5
Youth Services Specialist 65 3
Youth/Family Mntl Hlth Adv 42 6
Show the code
# 
# roster_analyzed_1 %>%
#   count(`Job Class Title`, Range, SalarySchedule) %>%
#   kable(format = "html", escape = FALSE, align = c("l", "r", "r"), caption = "Count of Job Class Titles by Range")

3.0.2 Ranges by Job Class Title (NEW)

Show the code
# I want a list of all roster_analyzed_1$`Job Class Titles` by Range. I want it displayed as a kable.
roster_analyzed_1 %>%
  count(Range, `Job Class Title`) %>%
  kable(format = "html", escape = FALSE, align = c("r", "l", "r"), caption = "Count of Ranges by Job Class Titles") %>%
  scroll_box(width = "100%", height = "500px")
Count of Ranges by Job Class Titles
Range Job Class Title n
29 Bus Attendant 11
29 Child Care Attendant, Chld Dev 32
29 Clerk I 10
29 IEP Desig Inst Para-Sp Ed 4
29 Inst Aid, Spec Ed 86
29 Inst Aide Child Dev 2
29 Instructional Aide 17
29 Instructional Aide (TK) 8
29 Morning Duty 12
29 Noon Duty 177
29 Walking Attendant 4
30 Noon Duty 1
32 Instructional Aide 5
32 Instructional Aide (TK) 18
33 Attendance Tech I 1
33 Clerk II 58
33 IEP Desig Inst Para-Sp Ed 3
33 Inst Aid, Spec Ed 70
33 Inst Aide Child Dev 5
33 Noon Duty 1
34 Campus Monitor 53
34 Custodian 100
34 Inst Aid, Spec Ed 1
34 Pupil Personnel Records Tech 1
34 School Community Liaison 2
35 Adult Ed Customer Rel Clk 1
35 Food Service Assistant 235
35 Health Aide 6
35 Health Aide, Spec Ed 1
35 Inst Aide/Computer Lab Asst 1
35 Swimming Pool Custodian 4
36 Food Prod Asst, Cent Kit 18
36 Instructional Aide 2
36 Instructional Aide (TK) 3
36 Van Driver 5
37 Automotive Service Attendant 2
37 Campus Supervisor I 1
37 Food Service Lead, School Site 74
37 IEP Desig Inst Para-Sp Ed 3
37 Inst Aid, Spec Ed 30
37 Inst Aide Child Dev 7
37 Teacher Assistant, Bilingual 25
37 Teacher Asst Bil II - Spanish 1
38 Attendance Tech I 2
38 Clerk III 6
38 Customer Service Specialist 4
38 Health Services Clerk 4
38 School Community Liaison 1
39 Career Information Technician 6
39 Educational Assistant 2
39 Food Service Lead, Comp HS 5
39 Inst Aid, Comp Lab 3
39 Office Tchncn I 1
39 Teacher Assistant, Bilingual 9
39 Teacher Asst Bil I - Spanish 1
40 Food Prod Lead Cent Kitchen 4
40 Instructional Aide 12
40 Instructional Aide (TK) 2
41 Adult Edctn Testing Proctor 3
41 Attendance Tech II 15
41 Buyer I 1
41 Health Aide 1
41 Health Aide, Spec Ed 1
41 IEP Desig Inst Para-Sp Ed 7
41 Inst Aid, Spec Ed 65
41 Inst Aide Child Dev 15
41 Library Media Tech Asst 5
41 Office Tchncn II 18
41 Registrar 1
41 Warehouse Records Clerk 1
42 Adm & Family Svcs Tech 5
42 Child Dev Spec I 9
42 Clerk III 1
42 Health Services Technician 3
42 Office Tchncn III 33
42 Personnel Tech I 3
42 School Intervention Staff Asst 1
42 Transportation Svcs Tech 1
42 Transportation Trip Scheduler 1
42 Youth/Family Mntl Hlth Adv 6
43 Educational Assistant 2
43 Office Technician IV 8
44 Fiscal Services Tech I 5
44 School Office Manager I 48
44 School Office Manager II 11
45 Employee Benefit Tech 2
45 Employment Coach SpEd 4
45 Lead Campus Supervisor 20
45 Nut Svc Inv Con Fac 2
45 Pgm Records Tech, CAMS 4
45 Pgm Records Tech-P&C 2
45 Print Shop Tech II 1
45 Program Rec Tech SpEd 1
45 School Office Manager III 10
45 Site Cmptr Suprt Tech I 2
45 Trans Over-Enrollment Tech 1
45 Trans Parts-Inv Cntrl Wrkr 1
45 Transition Asst SpEd 2
46 Assessment Technician 2
46 Child Welfare & Att Spec 2
46 Child Welfare & Attnd Liaison 4
46 Job Developer, Employment Svcs 2
46 Parent Advisor 11
46 Security Officer 5
46 Transportation Scheduler/Disp 4
47 Buyer II 1
47 Health Aide 1
47 Health Aide, Spec Ed 3
47 Mgmt Information Tech 2
47 Registered Behavior Technician 7
48 Assessor-Translator MOC 10
48 Child Develop Prgms Tech 1
48 Controller-Bookkeeper HS 6
48 FACE Technician 1
48 Linked Learning/CTP Pgm Tech 1
48 Warehouse Worker 14
49 Accounting Specialist 3
49 Controller/Bkkpr Adult Ed. 1
49 Pers Tech II 6
50 Adult Ed Specialist 1
50 Child Dev Data Info Tech 1
50 Matric & Orient Cntr Spec 2
50 Nutri Services Program Tech II 1
51 Accts Payable Lead Technician 1
51 Family Partnership Facilitator 2
51 Foster Youth Srvs Prog Assct 4
51 Lead Payroll Tech 2
51 Ombudsperson 2
51 Prsnl Tech, Substitute Srvs 2
51 Risk Management Specialist 1
51 Spec Progr & Advanced Learning 1
51 Youth Services Pgm Associate 5
52 Fund Spec 6
52 Materials Lab and Mail Tech 1
53 Bus Vehicle Mechanic 6
53 Registrar 12
53 Site Cmptr Suprt Tech II 3
53 Tech Support Spec I 1
54 Nutr Serv Purch and Wrhse Spec 2
55 Certified Occup Therapy Asst 3
55 Library Service App Specialist 3
55 Special Ed Applications Spclst 4
55 Speech-Lang Pathology Asst 3
55 Transportation Lead Mechanic 2
56 Interp for the Deaf 5
56 NUTRI SERV PROGRAM SPECIALIST 2
57 Applications Spec I 2
58 Lead Print Shop Technician 1
59 Pest Control Specialist 2
59 Tech Support Spec II 7
60 Network Specialist I 1
65 Applications Spec II 2
65 Buyer III 1
65 Student and Family Support 2
65 Youth Services Specialist 3
66 Education Entrepreneur 4
67 Tech Support Spec III 1
68 Facilities Project Tech 1
69 Construction/Bond Accntng Spec 1
69 Medi-Cal Rmbrsmnt Prog Spclst 1
70 Gang Violence Prev/Intrvntn Sp 1
72 Applications Spec III 5
72 Webmaster/Comm Spec 1
73 Professional Development Spec 1
74 Network Spec III 1
78 HAZMAT Risk Comp Lead Worker 1
88 Occupational Therapist 14
100 Gang Violence Prev/Intrvntn Sp 1
NA Custodian 2
NA Food Service Assistant 1
NA Inst Aid, Spec Ed 2
NA Inst Aide Child Dev 1
NA Noon Duty 3

4 Costing Analysis

Below is a costing analysis of:

  • SEIU 1021’s Proposal of 2024-06-13
  • SCUSD’s Supposal Tables of 2024-07-25

4.1 SEIU 1021’s Proposal of 2024-06-13

Proposal from SEIU Local 1021 To Sacramento City Unified School District

ARTICLE 6 Salaries

  • 6.1 The District shall square the salary schedule for the 2023-24 school year to reflect an increase of no less than 2.5% between salary ranges and no less than 5% between salary steps within each range, with the lowest hourly rate on the salary schedule at $18.19 per hour. The District shall maintain the same increments for the 2024-25 salary schedule, with the lowest hourly rate on the salary schedule at $20 per hour.

  • The parties agree to a four percent (4%) across-the-board salary increase retroactive to July 1, 2023, for all represented SEIU 1021 members.

  • The parties agree to a two percent (2%) across-the-board salary increase effective July 1, 2024, for all represented SEIU 1021 members.

4.1.1 Costing Methodology

  1. Using SCUSD roster data for the 1021 bargaining unit, as of 2024-07-26
  2. Calculating the cost for every employee, using their current hourly wage, annual hours, FTE, and the proposed wage increases.
  3. Costing each sub-proposal separate, in the following order:
    1. 4% across-the-board salary increase retroactive to July 1, 2023 (applied to base pay rate)
    2. “Square the Salary Schedule” after 4% raises. (more below)
    3. 2% across-the-board salary increase effective July 1, 2024 (applied to base pay rate after above raises)
  4. Summing the total cost for all sub-proposals for all employees, for each year.
  5. Presenting data in raw and with Total Payroll Factor (TPF) of 1.27 (benefits, taxes, etc.). Figure comes from SCUSD management as of 2024-08-07. I calculated the TPF by taking the median percent paid in taxes, retirement, and “additional benefits” and combining. I did not include health benefits, as those are flat rate (i.e. don’t go up as wages go up). I also didn’t include union dues since those come out of the employee’s paycheck, not employer’s.

4.1.1.1 The Base Pay Rate

  1. The District was unable to provide 100% clean base pay rate data, i.e. the listed base pay for every EMP ID did not 100% match the salary schedule. Instead of trying to do so, we agree for me to just match the roster to the main salary schedule (based on Salary Schedule ID provided by management) to get the actual base rate, and for every EMP ID not on the main salary schedule, just use the base rate from the roster. This is a minor difference, but it’s worth noting.

4.1.1.2 Squaring the Salary Schedule Methodology

  1. For 1021’s proposed salary schedule, I simply started at Range 29, Step 1, and multiplied every subsequent range by 1.025. Then I multiplied every subsequent step by 1.05.
  2. For SCUSD’s proposed salary schedule, I simply loaded their proposed salary schedules.
  3. Then I match the roster data to the salary schedule data. To match:
    1. Filter out employee IDs with appropriate Salary Schedule IDs (as provided by management)
    2. For TEMP employees, match their RANGE and STEP data to a separate TEMP roster (provided by management) that includes their “actual” RANGE and STEP. The main roster shows all TEMP employees as RANGE 1, STEP 1, but the TEMP roster shows their actual RANGE and STEP.
    3. Based on Range and Step, match the employee’s new proposed base wage to the roster.
    4. Calculate the difference between the new proposal base wage and after the 4 percent raise (as agreed to by both sides).
    5. Sum the differences.

4.1.2 Squaring the Salary Schedule - 1021’s Proposed Salary Schedules

Below is 1021’s proposed salary schedule for 2023-24, which maintains a 5% differential between steps and a 2.5% differential between ranges.

Show the code
# Create 1021's proposed salary schedule
salary_schedule_1021_2023_24 <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  mutate(
    min_range = min(Range),
    min_salary = min(c(Step1, Step2, Step3, Step4, Step5)),
    Step1 = min_salary * (1.025 ^ (Range - min_range)),
    Step2 = Step1 * 1.05,
    Step3 = Step2 * 1.05,
    Step4 = Step3 * 1.05,
    Step5 = Step4 * 1.05) |> 
  select(-min_range, -min_salary)  # Remove helper columns

# Round to 2 decimal places for cols 2:6
salary_schedule_1021_2023_24[, 2:6] <- round(salary_schedule_1021_2023_24[, 2:6], 2)


# Round to 2 decimal places for cols 2:6
salary_schedule_1021_2023_24[, 2:6] <- round(salary_schedule_1021_2023_24[, 2:6], 2)
Show the code
roster_with_SS_pay <- roster_with_SS_pay %>%
  # First raise (4%)
  mutate(
    New_Hourly_Wage_4p = (`SS Base Wage` * 1.02),
    New_Annual_Salary_4p = (New_Hourly_Wage_4p * `Annual Hours Paid` * FTE),
    Raise4p = New_Annual_Salary_4p - Annual_Salary,
    Raise4pperc = (New_Annual_Salary_4p / Annual_Salary)-1)

# Calculate the total cost of the first raise (4%)
cost_raise_4perc_all_2023 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise4p, na.rm = TRUE)) %>%
  pull(total_cost)
Show the code
# First, reshape the salary_schedule to long format
salary_schedule_long <- salary_schedule_1021_2023_24 %>%
  pivot_longer(
    cols = starts_with("Step"),
    names_to = "Step",
    values_to = "New_Hourly_Wage_SSFix"
  ) %>%
  mutate(Step = as.numeric(gsub("Step", "", Step)))

# Define the appropriate SalarySchedule IDs
appropriate_schedules <- c("C-H", "C-M", "C-M2", "IAC-H", "IAC-M", "TEMP20H", "TEMP20M", "SPECIAL3")

# Add column to roster_with_SS_pay appropriate_schedules, with checks SalarySchedule IDs and does YES or NO
roster_with_SS_pay <- roster_with_SS_pay %>%
  mutate(`Main Salary Schedule` = SalarySchedule %in% appropriate_schedules)

# Join and calculate new salaries
roster_with_SS_pay <- roster_with_SS_pay %>%
  left_join(salary_schedule_long, by = c("Range", "Step")) %>%
  mutate(
    New_Hourly_Wage_SSFix = case_when(
      SalarySchedule %in% appropriate_schedules ~ New_Hourly_Wage_SSFix,
      TRUE ~ New_Hourly_Wage_4p
    ),
    New_Annual_Salary_SSFix = New_Hourly_Wage_SSFix * `Annual Hours Paid` * FTE,
    WageSSFix_Increase = New_Hourly_Wage_SSFix - New_Hourly_Wage_4p,
    RaiseSSFix = New_Annual_Salary_SSFix - New_Annual_Salary_4p,
    RaiseSSFixperc = round(((New_Annual_Salary_SSFix / New_Annual_Salary_4p) - 1) * 100, 1)
  ) %>%
  rename(
    Initial_Hourly_Wage = `SS Base Wage`,
    Initial_Annual_Salary = Annual_Salary
  )%>%
  # Second raise (2%)
  mutate(
    New_Hourly_Wage_2p = (New_Hourly_Wage_SSFix * 1.04),
    New_Annual_Salary_2p = (New_Hourly_Wage_2p * `Annual Hours Paid` * FTE),
    Raise2p = New_Annual_Salary_2p - New_Annual_Salary_SSFix,
    Raise2pperc = (New_Annual_Salary_2p / New_Annual_Salary_SSFix)-1)

total_annual_salary_increase <- roster_with_SS_pay %>%
  summarise(total_cost = sum(RaiseSSFix, na.rm = TRUE)) %>%
  pull(total_cost)


# Calculate the total cost of annual salary difference between 3 and 2, but only for those with an increase. I.e. ignore any row with a decrease in salary.
total_annual_salary_increase_raises_only <- roster_with_SS_pay %>%
  filter(RaiseSSFix > 0) %>%
  summarise(total_cost = sum(RaiseSSFix, na.rm = TRUE)) %>%
  pull(total_cost)

# Calculate the total cost of the second raise (2%)
cost_raise_2perc_all_2024 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise2p, na.rm = TRUE)) %>%
  pull(total_cost)
Show the code
## SCUSD's Supposal Tables of 2024-07-25
# First, let's modify the analyze_salary_schedule function to ensure numeric input
analyze_salary_schedule <- function(df) {
  df %>%
    # Ensure all columns except Range are numeric
    mutate(across(-Range, as.numeric)) %>%
    # Calculate % difference between steps, rounded to 1 decimal
    mutate(
      `S2%` = round((Step2 - Step1) / Step1 * 100, 1),
      `S3%` = round((Step3 - Step2) / Step2 * 100, 1),
      `S4%` = round((Step4 - Step3) / Step3 * 100, 1),
      `S5%` = round((Step5 - Step4) / Step4 * 100, 1)
    ) %>%
    # Calculate % difference between ranges for each step, rounded to 1 decimal
    mutate(
      `R1%` = round((Step1 - lag(Step1)) / lag(Step1) * 100, 1),
      `R2%` = round((Step2 - lag(Step2)) / lag(Step2) * 100, 1),
      `R3%` = round((Step3 - lag(Step3)) / lag(Step3) * 100, 1),
      `R4%` = round((Step4 - lag(Step4)) / lag(Step4) * 100, 1),
      `R5%` = round((Step5 - lag(Step5)) / lag(Step5) * 100, 1)
    )
}

# Now apply the function to each salary schedule
salary_schedule_mgmt_2022_23_current_analyzed <- analyze_salary_schedule(salary_schedule_mgmt_2022_23_current)
salary_schedule_mgmt_2023_24_increase_4_percent_analyzed <- analyze_salary_schedule(salary_schedule_mgmt_2023_24_increase_4_percent)
salary_schedule_mgmt_2024_25_correction_analyzed <- analyze_salary_schedule(salary_schedule_mgmt_2024_25_correction)
salary_schedule_mgmt_2024_25_increase_2_percent_analyzed <- analyze_salary_schedule(salary_schedule_mgmt_2024_25_increase_2_percent)
salary_schedule_1021_analyzed_2023_24 <- analyze_salary_schedule(salary_schedule_1021_2023_24)
Show the code
library(dplyr)
library(kableExtra)

display_salary_schedule <- function(salary_schedule) {
  salary_schedule %>%
    mutate(across(7:15, ~ as.numeric(as.character(.)))) %>%
    mutate(across(7:10, ~ cell_spec(
      .,
      format = "html",
      color = case_when(
        is.na(.) ~ "black",
        . < 5 ~ "red",
        TRUE ~ "black"
      )
    ))) %>%
    mutate(across(11:15, ~ cell_spec(
      .,
      format = "html",
      color = case_when(
        is.na(.) ~ "black",
        . < 2.5 ~ "red",
        TRUE ~ "black"
      )
    ))) %>%
    kable(format = "html", escape = FALSE, align = rep("r", ncol(salary_schedule))) %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive")) %>%
    column_spec(1, border_right = TRUE) %>%
    column_spec(6, border_right = TRUE) %>%
    column_spec(10, border_right = TRUE) %>%
    scroll_box(width = "100%", height = "500px")
}

# Usage:
salary_schedule_mgmt_2022_23_current_display <- display_salary_schedule(salary_schedule_mgmt_2022_23_current_analyzed)
salary_schedule_mgmt_2023_24_increase_4_percent_display <- display_salary_schedule(salary_schedule_mgmt_2023_24_increase_4_percent_analyzed)
salary_schedule_mgmt_2024_25_correction_display<- display_salary_schedule(salary_schedule_mgmt_2024_25_correction_analyzed)
salary_schedule_mgmt_2024_25_increase_2_percent_display <- display_salary_schedule(salary_schedule_mgmt_2024_25_increase_2_percent_analyzed)
salary_schedule_1021_analyzed_2023_24_display <- display_salary_schedule(salary_schedule_1021_analyzed_2023_24)
Show the code
# Total Salary Status Quote
roster_analysis <- roster_with_SS_pay %>%
  summarize(
    Total_Employees = n(),
    Total_Annual_Salary = sum(Initial_Annual_Salary),
    Avg_Annual_Salary = mean(Initial_Annual_Salary),
    Median_Annual_Salary = median(Initial_Annual_Salary),
    Min_Annual_Salary = min(Initial_Annual_Salary),
    Max_Annual_Salary = max(Initial_Annual_Salary)
  )
Show the code
salary_schedule_1021_analyzed_2023_24_display
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 19.87 20.86 21.90 23.00 5 5 5 5 NA NA NA NA NA
30 19.39 20.36 21.38 22.45 23.57 5 5 5 5 2.5 2.5 2.5 2.5 2.5
31 19.88 20.87 21.92 23.01 24.16 5 5 5 5 2.5 2.5 2.5 2.5 2.5
32 20.37 21.39 22.46 23.59 24.77 5 5 5 5 2.5 2.5 2.5 2.5 2.5
33 20.88 21.93 23.02 24.18 25.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
34 21.41 22.48 23.60 24.78 26.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
35 21.94 23.04 24.19 25.40 26.67 5 5 5 5 2.5 2.5 2.5 2.5 2.5
36 22.49 23.61 24.80 26.03 27.34 5 5 5 5 2.5 2.5 2.5 2.5 2.5
37 23.05 24.20 25.42 26.69 28.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
38 23.63 24.81 26.05 27.35 28.72 5 5 5 5 2.5 2.5 2.5 2.5 2.5
39 24.22 25.43 26.70 28.04 29.44 5 5 5 5 2.5 2.5 2.5 2.5 2.5
40 24.82 26.07 27.37 28.74 30.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
41 25.45 26.72 28.05 29.46 30.93 5 5 5 5 2.5 2.5 2.5 2.5 2.5
42 26.08 27.39 28.75 30.19 31.70 5 5 5 5 2.5 2.5 2.5 2.5 2.5
43 26.73 28.07 29.47 30.95 32.49 5 5 5 5 2.5 2.5 2.5 2.5 2.5
44 27.40 28.77 30.21 31.72 33.31 5 5 5 5 2.5 2.5 2.5 2.5 2.5
45 28.09 29.49 30.97 32.51 34.14 5 5 5 5 2.5 2.5 2.5 2.5 2.5
46 28.79 30.23 31.74 33.33 34.99 5 5 5 5 2.5 2.5 2.5 2.5 2.5
47 29.51 30.98 32.53 34.16 35.87 5 5 5 5 2.5 2.5 2.5 2.5 2.5
48 30.25 31.76 33.35 35.01 36.76 5 5 5 5 2.5 2.5 2.5 2.5 2.5
49 31.00 32.55 34.18 35.89 37.68 5 5 5 5 2.5 2.5 2.5 2.5 2.5
50 31.78 33.37 35.03 36.79 38.63 5 5 5 5 2.5 2.5 2.5 2.5 2.5
51 32.57 34.20 35.91 37.71 39.59 5 5 5 5 2.5 2.5 2.5 2.5 2.5
52 33.39 35.06 36.81 38.65 40.58 5 5 5 5 2.5 2.5 2.5 2.5 2.5
53 34.22 35.93 37.73 39.62 41.60 5 5 5 5 2.5 2.5 2.5 2.5 2.5
54 35.08 36.83 38.67 40.61 42.64 5 5 5 5 2.5 2.5 2.5 2.5 2.5
55 35.95 37.75 39.64 41.62 43.70 5 5 5 5 2.5 2.5 2.5 2.5 2.5
56 36.85 38.69 40.63 42.66 44.79 5 5 5 5 2.5 2.5 2.5 2.5 2.5
57 37.77 39.66 41.65 43.73 45.91 5 5 5 5 2.5 2.5 2.5 2.5 2.5
58 38.72 40.65 42.69 44.82 47.06 5 5 5 5 2.5 2.5 2.5 2.5 2.5
59 39.69 41.67 43.75 45.94 48.24 5 5 5 5 2.5 2.5 2.5 2.5 2.5
60 40.68 42.71 44.85 47.09 49.44 5 5 5 5 2.5 2.5 2.5 2.5 2.5
61 41.70 43.78 45.97 48.27 50.68 5 5 5 5 2.5 2.5 2.5 2.5 2.5
62 42.74 44.87 47.12 49.47 51.95 5 5 5 5 2.5 2.5 2.5 2.5 2.5
63 43.81 46.00 48.30 50.71 53.25 5 5 5 5 2.5 2.5 2.5 2.5 2.5
64 44.90 47.15 49.50 51.98 54.58 5 5 5 5 2.5 2.5 2.5 2.5 2.5
65 46.02 48.32 50.74 53.28 55.94 5 5 5 5 2.5 2.5 2.5 2.5 2.5
66 47.17 49.53 52.01 54.61 57.34 5 5 5 5 2.5 2.5 2.5 2.5 2.5
67 48.35 50.77 53.31 55.98 58.77 5 5 5 5 2.5 2.5 2.5 2.5 2.5
68 49.56 52.04 54.64 57.37 60.24 5 5 5 5 2.5 2.5 2.5 2.5 2.5
69 50.80 53.34 56.01 58.81 61.75 5 5 5 5 2.5 2.5 2.5 2.5 2.5
70 52.07 54.68 57.41 60.28 63.29 5 5 5 5 2.5 2.5 2.5 2.5 2.5
71 53.37 56.04 58.84 61.79 64.88 5 5 5 5 2.5 2.5 2.5 2.5 2.5
72 54.71 57.44 60.32 63.33 66.50 5 5 5 5 2.5 2.5 2.5 2.5 2.5
73 56.08 58.88 61.82 64.91 68.16 5 5 5 5 2.5 2.5 2.5 2.5 2.5
74 57.48 60.35 63.37 66.54 69.86 5 5 5 5 2.5 2.5 2.5 2.5 2.5
75 58.91 61.86 64.95 68.20 71.61 5 5 5 5 2.5 2.5 2.5 2.5 2.5
76 60.39 63.41 66.58 69.91 73.40 5 5 5 5 2.5 2.5 2.5 2.5 2.5
77 61.90 64.99 68.24 71.65 75.24 5 5 5 5 2.5 2.5 2.5 2.5 2.5
78 63.44 66.62 69.95 73.44 77.12 5 5 5 5 2.5 2.5 2.5 2.5 2.5
79 65.03 68.28 71.70 75.28 79.04 5 5 5 5 2.5 2.5 2.5 2.5 2.5
80 66.66 69.99 73.49 77.16 81.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
81 68.32 71.74 75.33 79.09 83.05 5 5 5 5 2.5 2.5 2.5 2.5 2.5
82 70.03 73.53 77.21 81.07 85.12 5 5 5 5 2.5 2.5 2.5 2.5 2.5
83 71.78 75.37 79.14 83.10 87.25 5 5 5 5 2.5 2.5 2.5 2.5 2.5
84 73.58 77.25 81.12 85.17 89.43 5 5 5 5 2.5 2.5 2.5 2.5 2.5
85 75.41 79.19 83.15 87.30 91.67 5 5 5 5 2.5 2.5 2.5 2.5 2.5
86 77.30 81.17 85.22 89.48 93.96 5 5 5 5 2.5 2.5 2.5 2.5 2.5
87 79.23 83.19 87.35 91.72 96.31 5 5 5 5 2.5 2.5 2.5 2.5 2.5
88 81.21 85.27 89.54 94.01 98.72 5 5 5 5 2.5 2.5 2.5 2.5 2.5

4.1.3 Distribution of Raises from Fixing the Salary Schedule (1021 Proposal)

Below looks at the spread of raises for all employees in the roster after fixing the salary schedule. Reminder, not all members are in the salary schedule that is getting fixed, so that explains why 176 members are getting no raise from fixing the salary schedule.

Show the code
mean_median_mode_RaiseSSFixperc <- roster_with_SS_pay %>%
  summarise(
    mean_RaiseSSFixperc = round(mean(RaiseSSFixperc, na.rm = TRUE), 1),
    median_RaiseSSFixperc = round(median(RaiseSSFixperc, na.rm = TRUE), 1),
    mode_RaiseSSFixperc = round(as.numeric(names(sort(table(RaiseSSFixperc), decreasing = TRUE)[1])), 1),
    lowest_RaiseSSFixperc = round(min(RaiseSSFixperc, na.rm = TRUE), 1),
    highest_RaiseSSFixperc = round(max(RaiseSSFixperc, na.rm = TRUE), 1)
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Statistic",
    values_to = "Value"
  )

# Create histogram of RaiseSSFixperc
RaiseSSFixperc_hist <- roster_with_SS_pay %>%
  ggplot(aes(x = RaiseSSFixperc)) +
  geom_histogram(binwidth = 1, fill = "purple", color = "black") +
  labs(
    title = "Distribution of Raises from Fixing the Salary Schedule (1021 Proposal)",
    x = "Raise (%)",
    y = "Number of Employees"
  ) +
  My_Theme_WithY()

RaiseSSFixperc_hist

Show the code
# Display the mean, median, mode, lowest, and highest raise as a kable table
mean_median_mode_RaiseSSFixperc %>%
  kable(format = "html", escape = FALSE, align = c("l", "r")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
Statistic Value
mean_RaiseSSFixperc 20.0
median_RaiseSSFixperc 19.9
mode_RaiseSSFixperc 19.0
lowest_RaiseSSFixperc 0.0
highest_RaiseSSFixperc 39.1
Show the code
# Create new column (Min_Wage) in roster_with_SS_pay for any row where New_Hourly_Wage_2p is less than $20, add $20 to new column, if $20 or above, keep the same value as in New_Hourly_Wage_2p
roster_with_SS_pay <- roster_with_SS_pay %>%
  mutate(Min_Wage = ifelse(New_Hourly_Wage_2p < 20, 20, New_Hourly_Wage_2p),
         Annual_Salary_Min_Wage = Min_Wage * `Annual Hours Paid` * FTE,
         Raise_Min_Wage = round(Annual_Salary_Min_Wage - New_Annual_Salary_2p, digits=2))

# Calculate the total cost of the second raise (2%)
cost_raise_min_wage_all_2024 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise_Min_Wage, na.rm = TRUE)) %>%
  pull(total_cost)

4.1.4 Summary Table

Show the code
library(dplyr)
library(knitr)
library(scales)

# Create a data frame for the table
# Create a data frame for the table
cost_table <- data.frame(
  Description = c("4% Raise for All Employees, Retro 2023-07-01", 
                  "2% Raise for All Employees, Retro 2024-07-01",
                  "Squaring the Salary Schedule",
                  "Minimum Wage Increase to $20/hr, Retro 2024-07-01",
                  "Total Annual Costs, No Cuts"),
  Cost_Raw = c(cost_raise_4perc_all_2023, 
               cost_raise_2perc_all_2024,
               total_annual_salary_increase,
               cost_raise_min_wage_all_2024,
               cost_raise_4perc_all_2023 + cost_raise_2perc_all_2024 + total_annual_salary_increase),
  Cost_With_Factor = c(cost_raise_4perc_all_2023 * tpf_median, 
                       cost_raise_2perc_all_2024 * tpf_median,
                       total_annual_salary_increase * tpf_median,
                       cost_raise_min_wage_all_2024 * tpf_median,
                       (cost_raise_4perc_all_2023 + cost_raise_2perc_all_2024 + total_annual_salary_increase) * tpf_median),
  Notes = c("Annual cost. Management's proposal, agreed to by SEIU",
            "Annual cost. Management's proposal, agreed to by SEIU. Applied 1021's proposed salary schedule fix.",
            "Annual cost. 1021's proposal",
            "Annual cost. 1021's proposal. Actually a few thousand, only affects 11 emp id.",
            "Annual cost. Total of all 1021 proposals, no cuts."))

# Format the costs as currency in millions with commas, rounded to 1 decimal place
cost_table$Cost_Raw <- dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(cost_table$Cost_Raw)
cost_table$Cost_With_Factor <- dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(cost_table$Cost_With_Factor)

# Create the kable table
kable(cost_table, 
  col.names = c("Proposal", "Cost (Raw)", "Cost with TPF of 1.27", "Notes"),
  align = c("l", "r", "r", "l"),
  caption = "Salary Raise Proposals and Costs (in Millions of Dollars)") %>%
  row_spec(5, bold = TRUE)
Salary Raise Proposals and Costs (in Millions of Dollars)
Proposal Cost (Raw) Cost with TPF of 1.27 Notes
4% Raise for All Employees, Retro 2023-07-01 $1.3M $1.6M Annual cost. Management's proposal, agreed to by SEIU
2% Raise for All Employees, Retro 2024-07-01 $3.1M $3.9M Annual cost. Management's proposal, agreed to by SEIU. Applied 1021's proposed salary schedule fix.
Squaring the Salary Schedule $13.1M $16.7M Annual cost. 1021's proposal
Minimum Wage Increase to $20/hr, Retro 2024-07-01 $0.0M $0.0M Annual cost. 1021's proposal. Actually a few thousand, only affects 11 emp id.
Total Annual Costs, No Cuts $17.5M $22.2M Annual cost. Total of all 1021 proposals, no cuts.

4.2 SCUSD’s Salary Schedule Supposals

4.2.1 Salary Schedule 2022-23 Current

Show the code
# Loaded the salary schedules in chunks above above

salary_schedule_mgmt_2022_23_current_display
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.19 18.19 18.19 18.26 18.95 0 0 0.4 3.8 NA NA NA NA NA
30 18.19 18.19 18.19 18.70 19.45 0 0 2.8 4 0 0 0 2.4 2.6
31 18.19 18.19 18.26 18.95 19.88 0 0.4 3.8 4.9 0 0 0.4 1.3 2.2
32 18.19 18.19 18.70 19.45 20.35 0 2.8 4 4.6 0 0 2.4 2.6 2.4
33 18.19 18.26 18.95 19.88 20.75 0.4 3.8 4.9 4.4 0 0.4 1.3 2.2 2
34 18.19 18.70 19.45 20.35 21.26 2.8 4 4.6 4.5 0 2.4 2.6 2.4 2.5
35 18.26 18.95 19.88 20.75 21.80 3.8 4.9 4.4 5.1 0.4 1.3 2.2 2 2.5
36 18.70 19.45 20.35 21.26 22.20 4 4.6 4.5 4.4 2.4 2.6 2.4 2.5 1.8
37 18.95 19.88 20.75 21.80 22.68 4.9 4.4 5.1 4 1.3 2.2 2 2.5 2.2
38 19.45 20.35 21.26 22.20 23.23 4.6 4.5 4.4 4.6 2.6 2.4 2.5 1.8 2.4
39 19.88 20.75 21.80 22.68 23.77 4.4 5.1 4 4.8 2.2 2 2.5 2.2 2.3
40 20.35 21.26 22.20 23.23 24.33 4.5 4.4 4.6 4.7 2.4 2.5 1.8 2.4 2.4
41 20.75 21.80 22.68 23.77 24.84 5.1 4 4.8 4.5 2 2.5 2.2 2.3 2.1
42 20.05 20.94 21.91 22.96 24.06 4.4 4.6 4.8 4.8 -3.4 -3.9 -3.4 -3.4 -3.1
43 20.57 21.40 22.43 23.43 24.52 4 4.8 4.5 4.7 2.6 2.2 2.4 2 1.9
44 20.94 21.91 22.96 24.06 25.10 4.6 4.8 4.8 4.3 1.8 2.4 2.4 2.7 2.4
45 21.40 22.43 23.43 24.52 25.70 4.8 4.5 4.7 4.8 2.2 2.4 2 1.9 2.4
46 21.91 22.96 24.06 25.10 26.32 4.8 4.8 4.3 4.9 2.4 2.4 2.7 2.4 2.4
47 22.43 23.43 24.52 25.70 26.93 4.5 4.7 4.8 4.8 2.4 2 1.9 2.4 2.3
48 22.96 24.06 25.10 26.32 27.48 4.8 4.3 4.9 4.4 2.4 2.7 2.4 2.4 2
49 23.43 24.52 25.70 26.93 28.18 4.7 4.8 4.8 4.6 2 1.9 2.4 2.3 2.5
50 24.06 25.10 26.32 27.48 28.93 4.3 4.9 4.4 5.3 2.7 2.4 2.4 2 2.7
51 24.52 25.70 26.93 28.18 29.50 4.8 4.8 4.6 4.7 1.9 2.4 2.3 2.5 2
52 25.10 26.32 27.48 28.93 30.32 4.9 4.4 5.3 4.8 2.4 2.4 2 2.7 2.8
53 25.70 26.93 28.18 29.50 31.01 4.8 4.6 4.7 5.1 2.4 2.3 2.5 2 2.3
54 26.32 27.48 28.93 30.32 31.75 4.4 5.3 4.8 4.7 2.4 2 2.7 2.8 2.4
55 26.93 28.18 29.50 31.01 32.54 4.6 4.7 5.1 4.9 2.3 2.5 2 2.3 2.5
56 27.48 28.93 30.32 31.75 33.35 5.3 4.8 4.7 5 2 2.7 2.8 2.4 2.5
57 28.18 29.50 31.01 32.54 34.09 4.7 5.1 4.9 4.8 2.5 2 2.3 2.5 2.2
58 28.93 30.32 31.75 33.35 34.93 4.8 4.7 5 4.7 2.7 2.8 2.4 2.5 2.5
59 29.50 31.01 32.54 34.09 35.74 5.1 4.9 4.8 4.8 2 2.3 2.5 2.2 2.3
60 30.32 31.75 33.35 34.93 36.64 4.7 5 4.7 4.9 2.8 2.4 2.5 2.5 2.5
61 31.01 32.54 34.09 35.74 37.48 4.9 4.8 4.8 4.9 2.3 2.5 2.2 2.3 2.3
62 31.75 33.35 34.93 36.64 38.41 5 4.7 4.9 4.8 2.4 2.5 2.5 2.5 2.5
63 32.54 34.09 35.74 37.48 39.31 4.8 4.8 4.9 4.9 2.5 2.2 2.3 2.3 2.3
64 33.35 34.93 36.64 38.41 40.26 4.7 4.9 4.8 4.8 2.5 2.5 2.5 2.5 2.4
65 34.09 35.74 37.48 39.31 41.27 4.8 4.9 4.9 5 2.2 2.3 2.3 2.3 2.5
66 34.93 36.64 38.41 40.26 42.28 4.9 4.8 4.8 5 2.5 2.5 2.5 2.4 2.4
67 35.74 37.48 39.31 41.27 43.30 4.9 4.9 5 4.9 2.3 2.3 2.3 2.5 2.4
68 36.64 38.41 40.26 42.28 44.33 4.8 4.8 5 4.8 2.5 2.5 2.4 2.4 2.4
69 37.48 39.31 41.27 43.30 45.41 4.9 5 4.9 4.9 2.3 2.3 2.5 2.4 2.4
70 38.41 40.26 42.28 44.33 46.60 4.8 5 4.8 5.1 2.5 2.4 2.4 2.4 2.6
71 39.31 41.27 43.30 45.41 47.70 5 4.9 4.9 5 2.3 2.5 2.4 2.4 2.4
72 40.26 42.28 44.33 46.60 48.87 5 4.8 5.1 4.9 2.4 2.4 2.4 2.6 2.5
73 41.27 43.30 45.41 47.70 50.06 4.9 4.9 5 4.9 2.5 2.4 2.4 2.4 2.4
74 42.28 44.33 46.60 48.87 51.30 4.8 5.1 4.9 5 2.4 2.4 2.6 2.5 2.5
75 43.30 45.41 47.70 50.06 52.57 4.9 5 4.9 5 2.4 2.4 2.4 2.4 2.5
76 44.33 46.60 48.87 51.30 53.85 5.1 4.9 5 5 2.4 2.6 2.5 2.5 2.4
77 45.41 47.70 50.06 52.57 55.09 5 4.9 5 4.8 2.4 2.4 2.4 2.5 2.3
78 46.60 48.87 51.30 53.85 56.53 4.9 5 5 5 2.6 2.5 2.5 2.4 2.6
79 47.70 50.06 52.57 55.09 57.86 4.9 5 4.8 5 2.4 2.4 2.5 2.3 2.4
80 48.87 51.30 53.85 56.53 59.31 5 5 5 4.9 2.5 2.5 2.4 2.6 2.5
81 49.84 52.34 54.97 57.71 60.59 5 5 5 5 2 2 2.1 2.1 2.2
82 50.83 53.39 56.06 58.87 61.81 5 5 5 5 2 2 2 2 2
83 51.87 54.45 57.18 60.04 63.06 5 5 5 5 2 2 2 2 2
84 52.91 55.54 58.31 61.24 64.33 5 5 5 5 2 2 2 2 2
85 53.97 56.65 59.49 62.46 65.62 5 5 5 5.1 2 2 2 2 2
86 55.04 57.78 60.68 63.70 66.92 5 5 5 5.1 2 2 2 2 2
87 56.14 58.94 61.89 64.99 68.28 5 5 5 5.1 2 2 2 2 2
88 57.27 60.12 63.13 66.29 69.64 5 5 5 5.1 2 2 2 2 2

4.2.2 Salary Schedule 2023-24 Increase 4%

Show the code
salary_schedule_mgmt_2023_24_increase_4_percent_display
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 18.92 18.92 18.99 19.71 0 0 0.4 3.8 NA NA NA NA NA
30 18.92 18.92 18.92 19.45 20.23 0 0 2.8 4 0 0 0 2.4 2.6
31 18.92 18.92 18.99 19.71 20.68 0 0.4 3.8 4.9 0 0 0.4 1.3 2.2
32 18.92 18.92 19.45 20.23 21.16 0 2.8 4 4.6 0 0 2.4 2.6 2.3
33 18.92 18.99 19.71 20.68 21.58 0.4 3.8 4.9 4.4 0 0.4 1.3 2.2 2
34 18.92 19.45 20.23 21.16 22.11 2.8 4 4.6 4.5 0 2.4 2.6 2.3 2.5
35 18.99 19.71 20.68 21.58 22.68 3.8 4.9 4.4 5.1 0.4 1.3 2.2 2 2.6
36 19.45 20.23 21.16 22.11 23.09 4 4.6 4.5 4.4 2.4 2.6 2.3 2.5 1.8
37 19.71 20.68 21.58 22.68 23.59 4.9 4.4 5.1 4 1.3 2.2 2 2.6 2.2
38 20.23 21.16 22.11 23.09 24.16 4.6 4.5 4.4 4.6 2.6 2.3 2.5 1.8 2.4
39 20.68 21.58 22.68 23.59 24.73 4.4 5.1 4 4.8 2.2 2 2.6 2.2 2.4
40 21.16 22.11 23.09 24.16 25.31 4.5 4.4 4.6 4.8 2.3 2.5 1.8 2.4 2.3
41 21.58 22.68 23.59 24.73 25.83 5.1 4 4.8 4.4 2 2.6 2.2 2.4 2.1
42 20.86 21.78 22.79 23.88 25.02 4.4 4.6 4.8 4.8 -3.3 -4 -3.4 -3.4 -3.1
43 21.39 22.25 23.33 24.37 25.50 4 4.9 4.5 4.6 2.5 2.2 2.4 2.1 1.9
44 21.78 22.79 23.88 25.02 26.11 4.6 4.8 4.8 4.4 1.8 2.4 2.4 2.7 2.4
45 22.25 23.33 24.37 25.50 26.72 4.9 4.5 4.6 4.8 2.2 2.4 2.1 1.9 2.3
46 22.79 23.88 25.02 26.11 27.38 4.8 4.8 4.4 4.9 2.4 2.4 2.7 2.4 2.5
47 23.33 24.37 25.50 26.72 28.01 4.5 4.6 4.8 4.8 2.4 2.1 1.9 2.3 2.3
48 23.88 25.02 26.11 27.38 28.58 4.8 4.4 4.9 4.4 2.4 2.7 2.4 2.5 2
49 24.37 25.50 26.72 28.01 29.31 4.6 4.8 4.8 4.6 2.1 1.9 2.3 2.3 2.6
50 25.02 26.11 27.38 28.58 30.09 4.4 4.9 4.4 5.3 2.7 2.4 2.5 2 2.7
51 25.50 26.72 28.01 29.31 30.68 4.8 4.8 4.6 4.7 1.9 2.3 2.3 2.6 2
52 26.11 27.38 28.58 30.09 31.53 4.9 4.4 5.3 4.8 2.4 2.5 2 2.7 2.8
53 26.72 28.01 29.31 30.68 32.25 4.8 4.6 4.7 5.1 2.3 2.3 2.6 2 2.3
54 27.38 28.58 30.09 31.53 33.02 4.4 5.3 4.8 4.7 2.5 2 2.7 2.8 2.4
55 28.01 29.31 30.68 32.25 33.84 4.6 4.7 5.1 4.9 2.3 2.6 2 2.3 2.5
56 28.58 30.09 31.53 33.02 34.69 5.3 4.8 4.7 5.1 2 2.7 2.8 2.4 2.5
57 29.31 30.68 32.25 33.84 35.45 4.7 5.1 4.9 4.8 2.6 2 2.3 2.5 2.2
58 30.09 31.53 33.02 34.69 36.32 4.8 4.7 5.1 4.7 2.7 2.8 2.4 2.5 2.5
59 30.68 32.25 33.84 35.45 37.17 5.1 4.9 4.8 4.9 2 2.3 2.5 2.2 2.3
60 31.53 33.02 34.69 36.32 38.11 4.7 5.1 4.7 4.9 2.8 2.4 2.5 2.5 2.5
61 32.25 33.84 35.45 37.17 38.98 4.9 4.8 4.9 4.9 2.3 2.5 2.2 2.3 2.3
62 33.02 34.69 36.32 38.11 39.95 5.1 4.7 4.9 4.8 2.4 2.5 2.5 2.5 2.5
63 33.84 35.45 37.17 38.98 40.89 4.8 4.9 4.9 4.9 2.5 2.2 2.3 2.3 2.4
64 34.69 36.32 38.11 39.95 41.87 4.7 4.9 4.8 4.8 2.5 2.5 2.5 2.5 2.4
65 35.45 37.17 38.98 40.89 42.92 4.9 4.9 4.9 5 2.2 2.3 2.3 2.4 2.5
66 36.32 38.11 39.95 41.87 43.98 4.9 4.8 4.8 5 2.5 2.5 2.5 2.4 2.5
67 37.17 38.98 40.89 42.92 45.03 4.9 4.9 5 4.9 2.3 2.3 2.4 2.5 2.4
68 38.11 39.95 41.87 43.98 46.10 4.8 4.8 5 4.8 2.5 2.5 2.4 2.5 2.4
69 38.98 40.89 42.92 45.03 47.22 4.9 5 4.9 4.9 2.3 2.4 2.5 2.4 2.4
70 39.95 41.87 43.98 46.10 48.46 4.8 5 4.8 5.1 2.5 2.4 2.5 2.4 2.6
71 40.89 42.92 45.03 47.22 49.60 5 4.9 4.9 5 2.4 2.5 2.4 2.4 2.4
72 41.87 43.98 46.10 48.46 50.83 5 4.8 5.1 4.9 2.4 2.5 2.4 2.6 2.5
73 42.92 45.03 47.22 49.60 52.06 4.9 4.9 5 5 2.5 2.4 2.4 2.4 2.4
74 43.98 46.10 48.46 50.83 53.36 4.8 5.1 4.9 5 2.5 2.4 2.6 2.5 2.5
75 45.03 47.22 49.60 52.06 54.67 4.9 5 5 5 2.4 2.4 2.4 2.4 2.5
76 46.10 48.46 50.83 53.36 56.00 5.1 4.9 5 4.9 2.4 2.6 2.5 2.5 2.4
77 47.22 49.60 52.06 54.67 57.29 5 5 5 4.8 2.4 2.4 2.4 2.5 2.3
78 48.46 50.83 53.36 56.00 58.79 4.9 5 4.9 5 2.6 2.5 2.5 2.4 2.6
79 49.60 52.06 54.67 57.29 60.17 5 5 4.8 5 2.4 2.4 2.5 2.3 2.3
80 50.83 53.36 56.00 58.79 61.68 5 4.9 5 4.9 2.5 2.5 2.4 2.6 2.5
81 51.83 54.43 57.17 60.01 63.01 5 5 5 5 2 2 2.1 2.1 2.2
82 52.86 55.53 58.30 61.23 64.28 5.1 5 5 5 2 2 2 2 2
83 53.94 56.63 59.47 62.44 65.59 5 5 5 5 2 2 2 2 2
84 55.03 57.76 60.64 63.69 66.90 5 5 5 5 2 2 2 2 2
85 56.12 58.92 61.87 64.96 68.24 5 5 5 5 2 2 2 2 2
86 57.25 60.09 63.10 66.25 69.60 5 5 5 5.1 2 2 2 2 2
87 58.39 61.30 64.36 67.59 71.01 5 5 5 5.1 2 2 2 2 2
88 59.56 62.52 65.65 68.94 72.43 5 5 5 5.1 2 2 2 2 2

4.2.3 Salary Schedule 2024-25 Correction

Show the code
salary_schedule_mgmt_2024_25_correction_display
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 19.77 20.66 21.59 22.56 4.5 4.5 4.5 4.5 NA NA NA NA NA
30 19.30 20.16 21.07 22.02 23.01 4.5 4.5 4.5 4.5 2 2 2 2 2
31 19.68 20.57 21.49 22.46 23.47 4.5 4.5 4.5 4.5 2 2 2 2 2
32 20.08 20.98 21.92 22.91 23.94 4.5 4.5 4.5 4.5 2 2 2 2 2
33 20.48 21.40 22.36 23.37 24.42 4.5 4.5 4.5 4.5 2 2 2 2 2
34 20.89 21.83 22.81 23.84 24.91 4.5 4.5 4.5 4.5 2 2 2 2 2
35 21.30 22.26 23.26 24.31 25.41 4.5 4.5 4.5 4.5 2 2 2 2 2
36 21.73 22.71 23.73 24.80 25.91 4.5 4.5 4.5 4.5 2 2 2 2 2
37 22.16 23.16 24.20 25.29 26.43 4.5 4.5 4.5 4.5 2 2 2 2 2
38 22.61 23.63 24.69 25.80 26.96 4.5 4.5 4.5 4.5 2 2 2 2 2
39 23.06 24.10 25.18 26.32 27.50 4.5 4.5 4.5 4.5 2 2 2 2 2
40 23.52 24.58 25.69 26.84 28.05 4.5 4.5 4.5 4.5 2 2 2 2 2
41 23.99 25.07 26.20 27.38 28.61 4.5 4.5 4.5 4.5 2 2 2 2 2
42 24.47 25.57 26.72 27.93 29.18 4.5 4.5 4.5 4.5 2 2 2 2 2
43 24.96 26.08 27.26 28.49 29.77 4.5 4.5 4.5 4.5 2 2 2 2 2
44 25.46 26.61 27.80 29.05 30.36 4.5 4.5 4.5 4.5 2 2 2 2 2
45 25.97 27.14 28.36 29.64 30.97 4.5 4.5 4.5 4.5 2 2 2 2 2
46 26.49 27.68 28.93 30.23 31.59 4.5 4.5 4.5 4.5 2 2 2 2 2
47 27.02 28.23 29.51 30.83 32.22 4.5 4.5 4.5 4.5 2 2 2 2 2
48 23.88 25.02 26.11 27.38 28.58 4.8 4.4 4.9 4.4 -11.6 -11.4 -11.5 -11.2 -11.3
49 24.37 25.50 26.72 28.01 29.31 4.6 4.8 4.8 4.6 2.1 1.9 2.3 2.3 2.6
50 25.02 26.11 27.38 28.58 30.09 4.4 4.9 4.4 5.3 2.7 2.4 2.5 2 2.7
51 25.50 26.72 28.01 29.31 30.68 4.8 4.8 4.6 4.7 1.9 2.3 2.3 2.6 2
52 26.11 27.38 28.58 30.09 31.53 4.9 4.4 5.3 4.8 2.4 2.5 2 2.7 2.8
53 26.72 28.01 29.31 30.68 32.25 4.8 4.6 4.7 5.1 2.3 2.3 2.6 2 2.3
54 27.38 28.58 30.09 31.53 33.02 4.4 5.3 4.8 4.7 2.5 2 2.7 2.8 2.4
55 28.01 29.31 30.68 32.25 33.84 4.6 4.7 5.1 4.9 2.3 2.6 2 2.3 2.5
56 28.58 30.09 31.53 33.02 34.69 5.3 4.8 4.7 5.1 2 2.7 2.8 2.4 2.5
57 29.31 30.68 32.25 33.84 35.45 4.7 5.1 4.9 4.8 2.6 2 2.3 2.5 2.2
58 30.09 31.53 33.02 34.69 36.32 4.8 4.7 5.1 4.7 2.7 2.8 2.4 2.5 2.5
59 30.68 32.25 33.84 35.45 37.17 5.1 4.9 4.8 4.9 2 2.3 2.5 2.2 2.3
60 31.53 33.02 34.69 36.32 38.11 4.7 5.1 4.7 4.9 2.8 2.4 2.5 2.5 2.5
61 32.25 33.84 35.45 37.17 38.98 4.9 4.8 4.9 4.9 2.3 2.5 2.2 2.3 2.3
62 33.02 34.69 36.32 38.11 39.95 5.1 4.7 4.9 4.8 2.4 2.5 2.5 2.5 2.5
63 33.84 35.45 37.17 38.98 40.89 4.8 4.9 4.9 4.9 2.5 2.2 2.3 2.3 2.4
64 34.69 36.32 38.11 39.95 41.87 4.7 4.9 4.8 4.8 2.5 2.5 2.5 2.5 2.4
65 35.45 37.17 38.98 40.89 42.92 4.9 4.9 4.9 5 2.2 2.3 2.3 2.4 2.5
66 36.32 38.11 39.95 41.87 43.98 4.9 4.8 4.8 5 2.5 2.5 2.5 2.4 2.5
67 37.17 38.98 40.89 42.92 45.03 4.9 4.9 5 4.9 2.3 2.3 2.4 2.5 2.4
68 38.11 39.95 41.87 43.98 46.10 4.8 4.8 5 4.8 2.5 2.5 2.4 2.5 2.4
69 38.98 40.89 42.92 45.03 47.22 4.9 5 4.9 4.9 2.3 2.4 2.5 2.4 2.4
70 39.95 41.87 43.98 46.10 48.46 4.8 5 4.8 5.1 2.5 2.4 2.5 2.4 2.6
71 40.89 42.92 45.03 47.22 49.60 5 4.9 4.9 5 2.4 2.5 2.4 2.4 2.4
72 41.87 43.98 46.10 48.46 50.83 5 4.8 5.1 4.9 2.4 2.5 2.4 2.6 2.5
73 42.92 45.03 47.22 49.60 52.06 4.9 4.9 5 5 2.5 2.4 2.4 2.4 2.4
74 43.98 46.10 48.46 50.83 53.36 4.8 5.1 4.9 5 2.5 2.4 2.6 2.5 2.5
75 45.03 47.22 49.60 52.06 54.67 4.9 5 5 5 2.4 2.4 2.4 2.4 2.5
76 46.10 48.46 50.83 53.36 56.00 5.1 4.9 5 4.9 2.4 2.6 2.5 2.5 2.4
77 47.22 49.60 52.06 54.67 57.29 5 5 5 4.8 2.4 2.4 2.4 2.5 2.3
78 48.46 50.83 53.36 56.00 58.79 4.9 5 4.9 5 2.6 2.5 2.5 2.4 2.6
79 49.60 52.06 54.67 57.29 60.17 5 5 4.8 5 2.4 2.4 2.5 2.3 2.3
80 50.83 53.36 56.00 58.79 61.68 5 4.9 5 4.9 2.5 2.5 2.4 2.6 2.5
81 51.83 54.43 57.17 60.01 63.01 5 5 5 5 2 2 2.1 2.1 2.2
82 52.86 55.53 58.30 61.23 64.28 5.1 5 5 5 2 2 2 2 2
83 53.94 56.63 59.47 62.44 65.59 5 5 5 5 2 2 2 2 2
84 55.03 57.76 60.64 63.69 66.90 5 5 5 5 2 2 2 2 2
85 56.12 58.92 61.87 64.96 68.24 5 5 5 5 2 2 2 2 2
86 57.25 60.09 63.10 66.25 69.60 5 5 5 5.1 2 2 2 2 2
87 58.39 61.30 64.36 67.59 71.01 5 5 5 5.1 2 2 2 2 2
88 59.56 62.52 65.65 68.94 72.43 5 5 5 5.1 2 2 2 2 2

4.2.4 Salary Schedule 2024-25 Increase 2%

Show the code
salary_schedule_mgmt_2024_25_increase_2_percent_display
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.30 20.16 21.07 22.02 23.01 4.5 4.5 4.5 4.5 NA NA NA NA NA
30 19.68 20.57 21.49 22.46 23.47 4.5 4.5 4.5 4.5 2 2 2 2 2
31 20.08 20.98 21.92 22.91 23.94 4.5 4.5 4.5 4.5 2 2 2 2 2
32 20.48 21.40 22.36 23.37 24.42 4.5 4.5 4.5 4.5 2 2 2 2 2
33 20.89 21.83 22.81 23.84 24.91 4.5 4.5 4.5 4.5 2 2 2 2 2
34 21.30 22.26 23.26 24.31 25.41 4.5 4.5 4.5 4.5 2 2 2 2 2
35 21.73 22.71 23.73 24.80 25.91 4.5 4.5 4.5 4.5 2 2 2 2 2
36 22.16 23.16 24.20 25.29 26.43 4.5 4.5 4.5 4.5 2 2 2 2 2
37 22.61 23.63 24.69 25.80 26.96 4.5 4.5 4.5 4.5 2 2 2 2 2
38 23.06 24.10 25.18 26.32 27.50 4.5 4.5 4.5 4.5 2 2 2 2 2
39 23.52 24.58 25.69 26.84 28.05 4.5 4.5 4.5 4.5 2 2 2 2 2
40 23.99 25.07 26.20 27.38 28.61 4.5 4.5 4.5 4.5 2 2 2 2 2
41 24.47 25.57 26.72 27.93 29.18 4.5 4.5 4.5 4.5 2 2 2 2 2
42 24.96 26.08 27.26 28.49 29.77 4.5 4.5 4.5 4.5 2 2 2 2 2
43 25.46 26.61 27.80 29.05 30.36 4.5 4.5 4.5 4.5 2 2 2 2 2
44 25.97 27.14 28.36 29.64 30.97 4.5 4.5 4.5 4.5 2 2 2 2 2
45 26.49 27.68 28.93 30.23 31.59 4.5 4.5 4.5 4.5 2 2 2 2 2
46 27.02 28.23 29.51 30.83 32.22 4.5 4.5 4.5 4.5 2 2 2 2 2
47 27.56 28.80 30.10 31.45 32.87 4.5 4.5 4.5 4.5 2 2 2 2 2
48 24.35 25.52 26.63 27.92 29.15 4.8 4.3 4.8 4.4 -11.6 -11.4 -11.5 -11.2 -11.3
49 24.85 26.01 27.26 28.57 29.90 4.7 4.8 4.8 4.7 2.1 1.9 2.4 2.3 2.6
50 25.52 26.63 27.92 29.15 30.69 4.3 4.8 4.4 5.3 2.7 2.4 2.4 2 2.6
51 26.01 27.26 28.57 29.90 31.30 4.8 4.8 4.7 4.7 1.9 2.4 2.3 2.6 2
52 26.63 27.92 29.15 30.69 32.16 4.8 4.4 5.3 4.8 2.4 2.4 2 2.6 2.7
53 27.26 28.57 29.90 31.30 32.89 4.8 4.7 4.7 5.1 2.4 2.3 2.6 2 2.3
54 27.92 29.15 30.69 32.16 33.68 4.4 5.3 4.8 4.7 2.4 2 2.6 2.7 2.4
55 28.57 29.90 31.30 32.89 34.52 4.7 4.7 5.1 5 2.3 2.6 2 2.3 2.5
56 29.15 30.69 32.16 33.68 35.38 5.3 4.8 4.7 5 2 2.6 2.7 2.4 2.5
57 29.90 31.30 32.89 34.52 36.16 4.7 5.1 5 4.8 2.6 2 2.3 2.5 2.2
58 30.69 32.16 33.68 35.38 37.05 4.8 4.7 5 4.7 2.6 2.7 2.4 2.5 2.5
59 31.30 32.89 34.52 36.16 37.91 5.1 5 4.8 4.8 2 2.3 2.5 2.2 2.3
60 32.16 33.68 35.38 37.05 38.87 4.7 5 4.7 4.9 2.7 2.4 2.5 2.5 2.5
61 32.89 34.52 36.16 37.91 39.76 5 4.8 4.8 4.9 2.3 2.5 2.2 2.3 2.3
62 33.68 35.38 37.05 38.87 40.75 5 4.7 4.9 4.8 2.4 2.5 2.5 2.5 2.5
63 34.52 36.16 37.91 39.76 41.70 4.8 4.8 4.9 4.9 2.5 2.2 2.3 2.3 2.3
64 35.38 37.05 38.87 40.75 42.71 4.7 4.9 4.8 4.8 2.5 2.5 2.5 2.5 2.4
65 36.16 37.91 39.76 41.70 43.78 4.8 4.9 4.9 5 2.2 2.3 2.3 2.3 2.5
66 37.05 38.87 40.75 42.71 44.85 4.9 4.8 4.8 5 2.5 2.5 2.5 2.4 2.4
67 37.91 39.76 41.70 43.78 45.93 4.9 4.9 5 4.9 2.3 2.3 2.3 2.5 2.4
68 38.87 40.75 42.71 44.85 47.03 4.8 4.8 5 4.9 2.5 2.5 2.4 2.4 2.4
69 39.76 41.70 43.78 45.93 48.17 4.9 5 4.9 4.9 2.3 2.3 2.5 2.4 2.4
70 40.75 42.71 44.85 47.03 49.43 4.8 5 4.9 5.1 2.5 2.4 2.4 2.4 2.6
71 41.70 43.78 45.93 48.17 50.60 5 4.9 4.9 5 2.3 2.5 2.4 2.4 2.4
72 42.71 44.85 47.03 49.43 51.84 5 4.9 5.1 4.9 2.4 2.4 2.4 2.6 2.5
73 43.78 45.93 48.17 50.60 53.10 4.9 4.9 5 4.9 2.5 2.4 2.4 2.4 2.4
74 44.85 47.03 49.43 51.84 54.42 4.9 5.1 4.9 5 2.4 2.4 2.6 2.5 2.5
75 45.93 48.17 50.60 53.10 55.77 4.9 5 4.9 5 2.4 2.4 2.4 2.4 2.5
76 47.03 49.43 51.84 54.42 57.12 5.1 4.9 5 5 2.4 2.6 2.5 2.5 2.4
77 48.17 50.60 53.10 55.77 58.44 5 4.9 5 4.8 2.4 2.4 2.4 2.5 2.3
78 49.43 51.84 54.42 57.12 59.97 4.9 5 5 5 2.6 2.5 2.5 2.4 2.6
79 50.60 53.10 55.77 58.44 61.38 4.9 5 4.8 5 2.4 2.4 2.5 2.3 2.4
80 51.84 54.42 57.12 59.97 62.92 5 5 5 4.9 2.5 2.5 2.4 2.6 2.5
81 52.87 55.52 58.31 61.21 64.27 5 5 5 5 2 2 2.1 2.1 2.1
82 53.92 56.64 59.46 62.45 65.57 5 5 5 5 2 2 2 2 2
83 55.02 57.76 60.65 63.69 66.90 5 5 5 5 2 2 2 2 2
84 56.13 58.92 61.86 64.96 68.24 5 5 5 5 2 2 2 2 2
85 57.25 60.09 63.10 66.26 69.60 5 5 5 5 2 2 2 2 2
86 58.39 61.30 64.37 67.57 70.99 5 5 5 5.1 2 2 2 2 2
87 59.56 62.52 65.65 68.94 72.43 5 5 5 5.1 2 2 2 2 2
88 60.75 63.77 66.97 70.32 73.88 5 5 5 5.1 2 2 2 2 2
Show the code
# First, let's reshape the salary_schedule to long format
salary_schedule_long <- salary_schedule_mgmt_2024_25_correction %>%
  pivot_longer(
    cols = starts_with("Step"),
    names_to = "Step",
    values_to = "New_Hourly_Wage_SSFix_SCUSD"
  ) %>%
  mutate(Step = as.numeric(gsub("Step", "", Step)))

# Join and calculate new salaries
roster_with_SS_pay <- roster_with_SS_pay %>%
  left_join(salary_schedule_long, by = c("Range", "Step")) %>%
  mutate(
    New_Hourly_Wage_SSFix_SCUSD = case_when(
      SalarySchedule %in% appropriate_schedules ~ New_Hourly_Wage_SSFix_SCUSD,
      TRUE ~ New_Hourly_Wage_4p
    ),
    New_Annual_Salary_SSFix_SCUSD = New_Hourly_Wage_SSFix_SCUSD * `Annual Hours Paid` * FTE,
    WageSSFix_SCUSD_Increase = New_Hourly_Wage_SSFix_SCUSD - New_Hourly_Wage_4p,
    RaiseSSFix_SCUSD = New_Annual_Salary_SSFix_SCUSD - New_Annual_Salary_4p,
    RaiseSSFix_SCUSDperc = round(((New_Annual_Salary_SSFix_SCUSD / New_Annual_Salary_4p) - 1) * 100, 1)
  ) |> # cumulative $ and % increase from Annual_Salary_Min_Wage from Initial_Annual_Salary
  mutate(
    Cumulative_Raise_1021 = (Annual_Salary_Min_Wage - Initial_Annual_Salary),
    Cumulative_Raise_1021_perc = round(((Annual_Salary_Min_Wage / Initial_Annual_Salary) - 1) * 100, 1)
  )

# Save as csv
write_csv(roster_with_SS_pay, here("Districts/Sacramento/output_data/roster_with_SS_pay.csv"))

# Summarize and pull value for RaiseSSFix
total_annual_salary_increase_scusd <- roster_with_SS_pay %>%
  summarise(total_cost = sum(RaiseSSFix_SCUSD, na.rm = TRUE)) %>%
  pull(total_cost)

# Calculate the total cost of annual salary difference between 3 and 2, but only for those with an increase. I.e. ignore any row with a decrease in salary.
total_annual_salary_increase_scusd_raises_only <- roster_with_SS_pay %>%
  filter(RaiseSSFix_SCUSD > 0) %>%
  summarise(total_cost = sum(RaiseSSFix_SCUSD, na.rm = TRUE)) %>%
  pull(total_cost)

4.2.5 Distribution of Raises from Fixing the Salary Schedule (SCUSD Supposal)

Below looks at the spread of raises for all employees in the roster after fixing the salary schedule. Reminder, this is not all members, just those with the applicable salary schedule.

Show the code
mean_median_mode_RaiseSSFix_SCUSDperc <- roster_with_SS_pay %>%
  summarise(
    mean_RaiseSSFix_SCUSDperc = round(mean(RaiseSSFix_SCUSDperc, na.rm = TRUE), 1),
    median_RaiseSSFix_SCUSDperc = round(median(RaiseSSFix_SCUSDperc, na.rm = TRUE), 1),
    mode_RaiseSSFix_SCUSDperc = round(as.numeric(names(sort(table(RaiseSSFix_SCUSDperc), decreasing = TRUE)[1])), 1),
    lowest_RaiseSSFix_SCUSDperc = round(min(RaiseSSFix_SCUSDperc, na.rm = TRUE), 1),
    highest_RaiseSSFix_SCUSDperc = round(max(RaiseSSFix_SCUSDperc, na.rm = TRUE), 1)
  ) %>%
  pivot_longer(
    cols = everything(),
    names_to = "Statistic",
    values_to = "Value"
  )

# Create histogram of RaiseSSFix_SCUSDperc
RaiseSSFix_SCUSDperc_hist <- roster_with_SS_pay %>%
  ggplot(aes(x = RaiseSSFix_SCUSDperc)) +
  geom_histogram(binwidth = 1, fill = "purple", color = "black") +
  labs(
    title = "Distribution of Raises from Fixing the Salary Schedule (SCUSD Supposal)",
    x = "Raise (%)",
    y = "Number of Employees"
  ) +
  My_Theme_WithY()

RaiseSSFix_SCUSDperc_hist

Show the code
# Display the mean, median, mode, lowest, and highest raise as a kable table
mean_median_mode_RaiseSSFix_SCUSDperc %>%
  kable(format = "html", escape = FALSE, align = c("l", "r")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
Statistic Value
mean_RaiseSSFix_SCUSDperc 12.6
median_RaiseSSFix_SCUSDperc 14.7
mode_RaiseSSFix_SCUSDperc 16.7
lowest_RaiseSSFix_SCUSDperc 0.0
highest_RaiseSSFix_SCUSDperc 19.7

4.2.6 Summary Table with SCUSD’s Proposed Squaring of the Salary Schedule

Below compares 1021’s and SCUSD’s proposals for squaring the salary schedule.

Show the code
library(dplyr)
library(knitr)
library(scales)

# Create a data frame for the table
cost_table <- data.frame(
  Description = c("Squaring the Salary Schedule (1021)",
                  "Squaring the Salary Schedule (SCUSD)",
                  "Difference"),
  Cost_Raw = c(total_annual_salary_increase,
               total_annual_salary_increase_scusd,
               total_annual_salary_increase_scusd - total_annual_salary_increase),
  Notes = c("Annual cost. 1021's proposal",
            "Annual cost. SCUSD's proposal",
            "Difference in annual cost"))

# Calculate Cost_With_Factor using vectorized operation
cost_table$Cost_With_Factor <- cost_table$Cost_Raw * tpf_median

# Format the costs as currency in millions with commas, rounded to 1 decimal place
cost_table$Cost_Raw <- dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(cost_table$Cost_Raw)
cost_table$Cost_With_Factor <- dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(cost_table$Cost_With_Factor)

# Create the kable table
kable(cost_table, 
  col.names = c("Proposal", "Cost (Raw)", "Cost with TPF of 1.27", "Notes"),
  align = c("l", "r", "r", "l"),
  caption = "Salary Raise Proposals and Costs (in Millions of Dollars)")
Salary Raise Proposals and Costs (in Millions of Dollars)
Proposal Cost (Raw) Cost with TPF of 1.27 Notes
Squaring the Salary Schedule (1021) $13.1M Annual cost. 1021’s proposal $16.7M
Squaring the Salary Schedule (SCUSD) $6.6M Annual cost. SCUSD’s proposal $8.4M
Difference -$6.5M Difference in annual cost -$8.3M

4.3 2024-10-15 Update: Four New Alternative Salary Schedules

  1. Squaring the entire salary schedule at 4.5% between steps and 2% between ranges
  2. Squaring the entire salary schedule at 4.25% between steps and 2% between ranges
  3. Tapering the squaring from 5%/2.5% up to range 47, 5%/2% from range 48 up
  4. Tapering the squaring from 5%/2.5% up to range 47, 5%/2% from range 48 to 79, 5%/1.5% from range 80 up
Show the code
# 1. Squaring the entire salary schedule at 4.5% between steps and 2% between ranges
salary_schedule_1021_alt1 <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  mutate(
    min_range = min(Range),
    min_salary = min(c(Step1, Step2, Step3, Step4, Step5)),
    Step1 = min_salary * (1.02 ^ (Range - min_range)),
    Step2 = Step1 * 1.045,
    Step3 = Step2 * 1.045,
    Step4 = Step3 * 1.045,
    Step5 = Step4 * 1.045
  ) %>%
  select(-min_range, -min_salary)

# 2. Squaring the entire salary schedule at 4.25% between steps and 2% between ranges
salary_schedule_1021_alt2 <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  mutate(
    min_range = min(Range),
    min_salary = min(c(Step1, Step2, Step3, Step4, Step5)),
    Step1 = min_salary * (1.02 ^ (Range - min_range)),
    Step2 = Step1 * 1.0425,
    Step3 = Step2 * 1.0425,
    Step4 = Step3 * 1.0425,
    Step5 = Step4 * 1.0425
  ) %>%
  select(-min_range, -min_salary)

# 2.1. Squaring the entire salary schedule at 4% between steps and 2% between ranges
salary_schedule_1021_alt2p1 <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  mutate(
    min_range = min(Range),
    min_salary = min(c(Step1, Step2, Step3, Step4, Step5)),
    Step1 = min_salary * (1.02 ^ (Range - min_range)),
    Step2 = Step1 * 1.04,
    Step3 = Step2 * 1.04,
    Step4 = Step3 * 1.04,
    Step5 = Step4 * 1.04
  ) %>%
  select(-min_range, -min_salary)

# 3. Tapering the squaring from 5%/2.5% up to range 47, then 5%/2% from range 48 up
salary_schedule_1021_alt3 <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  mutate(
    min_range = min(Range),
    min_salary = min(c(Step1, Step2, Step3, Step4, Step5)),
    Step1 = case_when(
      Range <= 47 ~ min_salary * (1.025 ^ (Range - min_range)),
      Range > 47 ~ (min_salary * (1.025 ^ (47 - min_range))) * (1.02 ^ (Range - 47))
    ),
    Step2 = Step1 * 1.05,
    Step3 = Step2 * 1.05,
    Step4 = Step3 * 1.05,
    Step5 = Step4 * 1.05
  ) %>%
  select(-min_range, -min_salary)

# 4. Tapering the squaring from 5%/2.5% up to range 47, 5%/2% from range 48 to 79, 5%/1.5% from range 80 up
salary_schedule_1021_alt4 <- salary_schedule_mgmt_2023_24_increase_4_percent %>%
  mutate(
    min_range = min(Range),
    min_salary = min(c(Step1, Step2, Step3, Step4, Step5)),
    Step1 = case_when(
      Range <= 47 ~ min_salary * (1.025 ^ (Range - min_range)),
      Range > 47 & Range <= 79 ~ (min_salary * (1.025 ^ (47 - min_range))) * (1.02 ^ (Range - 47)),
      Range > 79 ~ (min_salary * (1.025 ^ (47 - min_range))) * (1.02 ^ 32) * (1.015 ^ (Range - 79))
    ),
    Step2 = Step1 * 1.05,
    Step3 = Step2 * 1.05,
    Step4 = Step3 * 1.05,
    Step5 = Step4 * 1.05
  ) %>%
  select(-min_range, -min_salary)

# Round to 2 decimal places for cols 2:6 in all schedules
salary_schedule_1021_alt1[, 2:6] <- round(salary_schedule_1021_alt1[, 2:6], 2)
salary_schedule_1021_alt2[, 2:6] <- round(salary_schedule_1021_alt2[, 2:6], 2)
salary_schedule_1021_alt3[, 2:6] <- round(salary_schedule_1021_alt3[, 2:6], 2)
salary_schedule_1021_alt4[, 2:6] <- round(salary_schedule_1021_alt4[, 2:6], 2)
Show the code
# Analyze salary schedules

# Apply to new alternative schedules
salary_schedule_1021_alt1_analyzed <- analyze_salary_schedule(salary_schedule_1021_alt1)
salary_schedule_1021_alt2_analyzed <- analyze_salary_schedule(salary_schedule_1021_alt2)
salary_schedule_1021_alt2p1_analyzed <- analyze_salary_schedule(salary_schedule_1021_alt2p1)
salary_schedule_1021_alt3_analyzed <- analyze_salary_schedule(salary_schedule_1021_alt3)
salary_schedule_1021_alt4_analyzed <- analyze_salary_schedule(salary_schedule_1021_alt4)

4.3.1 Alt #1: Uniform Squaring of Salary Schedule at Slightly Smaller Rates

All Ranges (29-88):

  • 4.5% between steps
  • 2% between ranges
Show the code
# Display salary schedules
display_salary_schedule(salary_schedule_1021_alt1_analyzed)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 19.77 20.66 21.59 22.56 4.5 4.5 4.5 4.5 NA NA NA NA NA
30 19.30 20.17 21.07 22.02 23.01 4.5 4.5 4.5 4.5 2 2 2 2 2
31 19.68 20.57 21.50 22.46 23.47 4.5 4.5 4.5 4.5 2 2 2 2 2
32 20.08 20.98 21.93 22.91 23.94 4.5 4.5 4.5 4.5 2 2 2 2 2
33 20.48 21.40 22.36 23.37 24.42 4.5 4.5 4.5 4.5 2 2 2 2 2
34 20.89 21.83 22.81 23.84 24.91 4.5 4.5 4.5 4.5 2 2 2 2 2
35 21.31 22.27 23.27 24.31 25.41 4.5 4.5 4.5 4.5 2 2 2 2 2
36 21.73 22.71 23.73 24.80 25.92 4.5 4.5 4.5 4.5 2 2 2 2 2
37 22.17 23.17 24.21 25.30 26.44 4.5 4.5 4.5 4.5 2 2 2 2 2
38 22.61 23.63 24.69 25.80 26.96 4.5 4.5 4.5 4.5 2 2 2 2 2
39 23.06 24.10 25.19 26.32 27.50 4.5 4.5 4.5 4.5 2 2 2 2 2
40 23.52 24.58 25.69 26.85 28.05 4.5 4.5 4.5 4.5 2 2 2 2 2
41 24.00 25.07 26.20 27.38 28.61 4.5 4.5 4.5 4.5 2 2 2 2 2
42 24.48 25.58 26.73 27.93 29.19 4.5 4.5 4.5 4.5 2 2 2 2 2
43 24.96 26.09 27.26 28.49 29.77 4.5 4.5 4.5 4.5 2 2 2 2 2
44 25.46 26.61 27.81 29.06 30.37 4.5 4.5 4.5 4.5 2 2 2 2 2
45 25.97 27.14 28.36 29.64 30.97 4.5 4.5 4.5 4.5 2 2 2 2 2
46 26.49 27.68 28.93 30.23 31.59 4.5 4.5 4.5 4.5 2 2 2 2 2
47 27.02 28.24 29.51 30.84 32.22 4.5 4.5 4.5 4.5 2 2 2 2 2
48 27.56 28.80 30.10 31.45 32.87 4.5 4.5 4.5 4.5 2 2 2 2 2
49 28.11 29.38 30.70 32.08 33.53 4.5 4.5 4.5 4.5 2 2 2 2 2
50 28.68 29.97 31.32 32.72 34.20 4.5 4.5 4.5 4.5 2 2 2 2 2
51 29.25 30.57 31.94 33.38 34.88 4.5 4.5 4.5 4.5 2 2 2 2 2
52 29.83 31.18 32.58 34.05 35.58 4.5 4.5 4.5 4.5 2 2 2 2 2
53 30.43 31.80 33.23 34.73 36.29 4.5 4.5 4.5 4.5 2 2 2 2 2
54 31.04 32.44 33.90 35.42 37.02 4.5 4.5 4.5 4.5 2 2 2 2 2
55 31.66 33.09 34.57 36.13 37.76 4.5 4.5 4.5 4.5 2 2 2 2 2
56 32.29 33.75 35.27 36.85 38.51 4.5 4.5 4.5 4.5 2 2 2 2 2
57 32.94 34.42 35.97 37.59 39.28 4.5 4.5 4.5 4.5 2 2 2 2 2
58 33.60 35.11 36.69 38.34 40.07 4.5 4.5 4.5 4.5 2 2 2 2 2
59 34.27 35.81 37.42 39.11 40.87 4.5 4.5 4.5 4.5 2 2 2 2 2
60 34.96 36.53 38.17 39.89 41.69 4.5 4.5 4.5 4.5 2 2 2 2 2
61 35.66 37.26 38.94 40.69 42.52 4.5 4.5 4.5 4.5 2 2 2 2 2
62 36.37 38.01 39.72 41.50 43.37 4.5 4.5 4.5 4.5 2 2 2 2 2
63 37.10 38.77 40.51 42.33 44.24 4.5 4.5 4.5 4.5 2 2 2 2 2
64 37.84 39.54 41.32 43.18 45.12 4.5 4.5 4.5 4.5 2 2 2 2 2
65 38.59 40.33 42.15 44.04 46.02 4.5 4.5 4.5 4.5 2 2 2 2 2
66 39.37 41.14 42.99 44.92 46.95 4.5 4.5 4.5 4.5 2 2 2 2 2
67 40.15 41.96 43.85 45.82 47.88 4.5 4.5 4.5 4.5 2 2 2 2 2
68 40.96 42.80 44.73 46.74 48.84 4.5 4.5 4.5 4.5 2 2 2 2 2
69 41.78 43.66 45.62 47.67 49.82 4.5 4.5 4.5 4.5 2 2 2 2 2
70 42.61 44.53 46.53 48.63 50.82 4.5 4.5 4.5 4.5 2 2 2 2 2
71 43.46 45.42 47.46 49.60 51.83 4.5 4.5 4.5 4.5 2 2 2 2 2
72 44.33 46.33 48.41 50.59 52.87 4.5 4.5 4.5 4.5 2 2 2 2 2
73 45.22 47.25 49.38 51.60 53.93 4.5 4.5 4.5 4.5 2 2 2 2 2
74 46.12 48.20 50.37 52.64 55.00 4.5 4.5 4.5 4.5 2 2 2 2 2
75 47.05 49.16 51.38 53.69 56.10 4.5 4.5 4.5 4.5 2 2 2 2 2
76 47.99 50.15 52.40 54.76 57.23 4.5 4.5 4.5 4.5 2 2 2 2 2
77 48.95 51.15 53.45 55.86 58.37 4.5 4.5 4.5 4.5 2 2 2 2 2
78 49.93 52.17 54.52 56.97 59.54 4.5 4.5 4.5 4.5 2 2 2 2 2
79 50.92 53.22 55.61 58.11 60.73 4.5 4.5 4.5 4.5 2 2 2 2 2
80 51.94 54.28 56.72 59.28 61.94 4.5 4.5 4.5 4.5 2 2 2 2 2
81 52.98 55.37 57.86 60.46 63.18 4.5 4.5 4.5 4.5 2 2 2 2 2
82 54.04 56.47 59.02 61.67 64.45 4.5 4.5 4.5 4.5 2 2 2 2 2
83 55.12 57.60 60.20 62.90 65.73 4.5 4.5 4.5 4.5 2 2 2 2 2
84 56.23 58.76 61.40 64.16 67.05 4.5 4.5 4.5 4.5 2 2 2 2 2
85 57.35 59.93 62.63 65.45 68.39 4.5 4.5 4.5 4.5 2 2 2 2 2
86 58.50 61.13 63.88 66.75 69.76 4.5 4.5 4.5 4.5 2 2 2 2 2
87 59.67 62.35 65.16 68.09 71.15 4.5 4.5 4.5 4.5 2 2 2 2 2
88 60.86 63.60 66.46 69.45 72.58 4.5 4.5 4.5 4.5 2 2 2 2 2

4.3.2 Alt #2: Uniform Squaring of Salary Schedule at Even Slightly Smaller Rates

All Ranges (29-88):

  • 4.25% between steps
  • 2% between ranges
Show the code
# Display salary schedules
display_salary_schedule(salary_schedule_1021_alt2_analyzed)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 19.72 20.56 21.44 22.35 4.2 4.3 4.3 4.2 NA NA NA NA NA
30 19.30 20.12 20.97 21.87 22.79 4.2 4.2 4.3 4.2 2 2 2 2 2
31 19.68 20.52 21.39 22.30 23.25 4.3 4.2 4.3 4.3 2 2 2 2 2
32 20.08 20.93 21.82 22.75 23.72 4.2 4.3 4.3 4.3 2 2 2 2 2
33 20.48 21.35 22.26 23.20 24.19 4.2 4.3 4.2 4.3 2 2 2 2 2
34 20.89 21.78 22.70 23.67 24.67 4.3 4.2 4.3 4.2 2 2 2 2 2
35 21.31 22.21 23.16 24.14 25.17 4.2 4.3 4.2 4.3 2 2 2 2 2
36 21.73 22.66 23.62 24.62 25.67 4.3 4.2 4.2 4.3 2 2 2 2 2
37 22.17 23.11 24.09 25.12 26.18 4.2 4.2 4.3 4.2 2 2 2 2 2
38 22.61 23.57 24.57 25.62 26.71 4.2 4.2 4.3 4.3 2 2 2 2 2
39 23.06 24.04 25.07 26.13 27.24 4.2 4.3 4.2 4.2 2 2 2 2 2
40 23.52 24.52 25.57 26.65 27.79 4.3 4.3 4.2 4.3 2 2 2 2 2
41 24.00 25.01 26.08 27.19 28.34 4.2 4.3 4.3 4.2 2 2 2 2 2
42 24.48 25.52 26.60 27.73 28.91 4.2 4.2 4.2 4.3 2 2 2 2 2
43 24.96 26.03 27.13 28.28 29.49 4.3 4.2 4.2 4.3 2 2 2 2 2
44 25.46 26.55 27.67 28.85 30.08 4.3 4.2 4.3 4.3 2 2 2 2 2
45 25.97 27.08 28.23 29.43 30.68 4.3 4.2 4.3 4.2 2 2 2 2 2
46 26.49 27.62 28.79 30.02 31.29 4.3 4.2 4.3 4.2 2 2 2 2 2
47 27.02 28.17 29.37 30.62 31.92 4.3 4.3 4.3 4.2 2 2 2 2 2
48 27.56 28.73 29.96 31.23 32.56 4.2 4.3 4.2 4.3 2 2 2 2 2
49 28.11 29.31 30.55 31.85 33.21 4.3 4.2 4.3 4.3 2 2 2 2 2
50 28.68 29.90 31.17 32.49 33.87 4.3 4.2 4.2 4.2 2 2 2 2 2
51 29.25 30.49 31.79 33.14 34.55 4.2 4.3 4.2 4.3 2 2 2 2 2
52 29.83 31.10 32.42 33.80 35.24 4.3 4.2 4.3 4.3 2 2 2 2 2
53 30.43 31.72 33.07 34.48 35.94 4.2 4.3 4.3 4.2 2 2 2 2 2
54 31.04 32.36 33.73 35.17 36.66 4.3 4.2 4.3 4.2 2 2 2 2 2
55 31.66 33.01 34.41 35.87 37.40 4.3 4.2 4.2 4.3 2 2 2 2 2
56 32.29 33.67 35.10 36.59 38.14 4.3 4.2 4.2 4.2 2 2 2 2 2
57 32.94 34.34 35.80 37.32 38.91 4.3 4.3 4.2 4.3 2 2 2 2 2
58 33.60 35.03 36.52 38.07 39.69 4.3 4.3 4.2 4.3 2 2 2 2 2
59 34.27 35.73 37.25 38.83 40.48 4.3 4.3 4.2 4.2 2 2 2 2 2
60 34.96 36.44 37.99 39.61 41.29 4.2 4.3 4.3 4.2 2 2 2 2 2
61 35.66 37.17 38.75 40.40 42.11 4.2 4.3 4.3 4.2 2 2 2 2 2
62 36.37 37.91 39.53 41.21 42.96 4.2 4.3 4.2 4.2 2 2 2 2 2
63 37.10 38.67 40.32 42.03 43.82 4.2 4.3 4.2 4.3 2 2 2 2 2
64 37.84 39.45 41.12 42.87 44.69 4.3 4.2 4.3 4.2 2 2 2 2 2
65 38.59 40.23 41.94 43.73 45.59 4.2 4.3 4.3 4.3 2 2 2 2 2
66 39.37 41.04 42.78 44.60 46.50 4.2 4.2 4.3 4.3 2 2 2 2 2
67 40.15 41.86 43.64 45.49 47.43 4.3 4.3 4.2 4.3 2 2 2 2 2
68 40.96 42.70 44.51 46.40 48.38 4.2 4.2 4.2 4.3 2 2 2 2 2
69 41.78 43.55 45.40 47.33 49.34 4.2 4.2 4.3 4.2 2 2 2 2 2
70 42.61 44.42 46.31 48.28 50.33 4.2 4.3 4.3 4.2 2 2 2 2 2
71 43.46 45.31 47.24 49.24 51.34 4.3 4.3 4.2 4.3 2 2 2 2 2
72 44.33 46.22 48.18 50.23 52.36 4.3 4.2 4.3 4.2 2 2 2 2 2
73 45.22 47.14 49.15 51.23 53.41 4.2 4.3 4.2 4.3 2 2 2 2 2
74 46.12 48.08 50.13 52.26 54.48 4.2 4.3 4.2 4.2 2 2 2 2 2
75 47.05 49.05 51.13 53.30 55.57 4.3 4.2 4.2 4.3 2 2 2 2 2
76 47.99 50.03 52.15 54.37 56.68 4.3 4.2 4.3 4.2 2 2 2 2 2
77 48.95 51.03 53.20 55.46 57.81 4.2 4.3 4.2 4.2 2 2 2 2 2
78 49.93 52.05 54.26 56.57 58.97 4.2 4.2 4.3 4.2 2 2 2 2 2
79 50.92 53.09 55.35 57.70 60.15 4.3 4.3 4.2 4.2 2 2 2 2 2
80 51.94 54.15 56.45 58.85 61.35 4.3 4.2 4.3 4.2 2 2 2 2 2
81 52.98 55.23 57.58 60.03 62.58 4.2 4.3 4.3 4.2 2 2 2 2 2
82 54.04 56.34 58.73 61.23 63.83 4.3 4.2 4.3 4.2 2 2 2 2 2
83 55.12 57.47 59.91 62.45 65.11 4.3 4.2 4.2 4.3 2 2 2 2 2
84 56.23 58.61 61.11 63.70 66.41 4.2 4.3 4.2 4.3 2 2 2 2 2
85 57.35 59.79 62.33 64.98 67.74 4.3 4.2 4.3 4.2 2 2 2 2 2
86 58.50 60.98 63.57 66.28 69.09 4.2 4.2 4.3 4.2 2 2 2 2 2
87 59.67 62.20 64.85 67.60 70.48 4.2 4.3 4.2 4.3 2 2 2 2 2
88 60.86 63.45 66.14 68.95 71.88 4.3 4.2 4.2 4.2 2 2 2 2 2

4.3.3 Alt #2.1: Uniform Squaring of Salary Schedule at Even Slightly Smaller Rates

All Ranges (29-88):

  • 4.0% between steps
  • 2% between ranges
Show the code
# Display salary schedules
display_salary_schedule(salary_schedule_1021_alt2p1_analyzed)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92000 19.67680 20.46387 21.28243 22.13372 4 4 4 4 NA NA NA NA NA
30 19.29840 20.07034 20.87315 21.70808 22.57640 4 4 4 4 2 2 2 2 2
31 19.68437 20.47174 21.29061 22.14224 23.02793 4 4 4 4 2 2 2 2 2
32 20.07806 20.88118 21.71642 22.58508 23.48848 4 4 4 4 2 2 2 2 2
33 20.47962 21.29880 22.15075 23.03678 23.95825 4 4 4 4 2 2 2 2 2
34 20.88921 21.72478 22.59377 23.49752 24.43742 4 4 4 4 2 2 2 2 2
35 21.30699 22.15927 23.04564 23.96747 24.92617 4 4 4 4 2 2 2 2 2
36 21.73313 22.60246 23.50656 24.44682 25.42469 4 4 4 4 2 2 2 2 2
37 22.16780 23.05451 23.97669 24.93576 25.93319 4 4 4 4 2 2 2 2 2
38 22.61115 23.51560 24.45622 25.43447 26.45185 4 4 4 4 2 2 2 2 2
39 23.06337 23.98591 24.94535 25.94316 26.98089 4 4 4 4 2 2 2 2 2
40 23.52464 24.46563 25.44425 26.46202 27.52050 4 4 4 4 2 2 2 2 2
41 23.99513 24.95494 25.95314 26.99126 28.07091 4 4 4 4 2 2 2 2 2
42 24.47504 25.45404 26.47220 27.53109 28.63233 4 4 4 4 2 2 2 2 2
43 24.96454 25.96312 27.00164 28.08171 29.20498 4 4 4 4 2 2 2 2 2
44 25.46383 26.48238 27.54168 28.64334 29.78908 4 4 4 4 2 2 2 2 2
45 25.97311 27.01203 28.09251 29.21621 30.38486 4 4 4 4 2 2 2 2 2
46 26.49257 27.55227 28.65436 29.80054 30.99256 4 4 4 4 2 2 2 2 2
47 27.02242 28.10332 29.22745 30.39655 31.61241 4 4 4 4 2 2 2 2 2
48 27.56287 28.66538 29.81200 31.00448 32.24466 4 4 4 4 2 2 2 2 2
49 28.11412 29.23869 30.40824 31.62457 32.88955 4 4 4 4 2 2 2 2 2
50 28.67641 29.82346 31.01640 32.25706 33.54734 4 4 4 4 2 2 2 2 2
51 29.24994 30.41993 31.63673 32.90220 34.21829 4 4 4 4 2 2 2 2 2
52 29.83493 31.02833 32.26946 33.56024 34.90265 4 4 4 4 2 2 2 2 2
53 30.43163 31.64890 32.91485 34.23145 35.60071 4 4 4 4 2 2 2 2 2
54 31.04027 32.28188 33.57315 34.91608 36.31272 4 4 4 4 2 2 2 2 2
55 31.66107 32.92751 34.24461 35.61440 37.03897 4 4 4 4 2 2 2 2 2
56 32.29429 33.58606 34.92951 36.32669 37.77975 4 4 4 4 2 2 2 2 2
57 32.94018 34.25779 35.62810 37.05322 38.53535 4 4 4 4 2 2 2 2 2
58 33.59898 34.94294 36.34066 37.79428 39.30606 4 4 4 4 2 2 2 2 2
59 34.27096 35.64180 37.06747 38.55017 40.09218 4 4 4 4 2 2 2 2 2
60 34.95638 36.35464 37.80882 39.32117 40.89402 4 4 4 4 2 2 2 2 2
61 35.65551 37.08173 38.56500 40.10760 41.71190 4 4 4 4 2 2 2 2 2
62 36.36862 37.82336 39.33630 40.90975 42.54614 4 4 4 4 2 2 2 2 2
63 37.09599 38.57983 40.12302 41.72794 43.39706 4 4 4 4 2 2 2 2 2
64 37.83791 39.35143 40.92548 42.56250 44.26500 4 4 4 4 2 2 2 2 2
65 38.59467 40.13846 41.74399 43.41375 45.15030 4 4 4 4 2 2 2 2 2
66 39.36656 40.94122 42.57887 44.28203 46.05331 4 4 4 4 2 2 2 2 2
67 40.15389 41.76005 43.43045 45.16767 46.97438 4 4 4 4 2 2 2 2 2
68 40.95697 42.59525 44.29906 46.07102 47.91386 4 4 4 4 2 2 2 2 2
69 41.77611 43.44715 45.18504 46.99244 48.87214 4 4 4 4 2 2 2 2 2
70 42.61163 44.31610 46.08874 47.93229 49.84958 4 4 4 4 2 2 2 2 2
71 43.46387 45.20242 47.01052 48.89094 50.84657 4 4 4 4 2 2 2 2 2
72 44.33314 46.10647 47.95073 49.86876 51.86351 4 4 4 4 2 2 2 2 2
73 45.21981 47.02860 48.90974 50.86613 52.90078 4 4 4 4 2 2 2 2 2
74 46.12420 47.96917 49.88794 51.88345 53.95879 4 4 4 4 2 2 2 2 2
75 47.04669 48.92855 50.88570 52.92112 55.03797 4 4 4 4 2 2 2 2 2
76 47.98762 49.90712 51.90341 53.97955 56.13873 4 4 4 4 2 2 2 2 2
77 48.94737 50.90527 52.94148 55.05914 57.26150 4 4 4 4 2 2 2 2 2
78 49.92632 51.92337 54.00031 56.16032 58.40673 4 4 4 4 2 2 2 2 2
79 50.92485 52.96184 55.08031 57.28353 59.57487 4 4 4 4 2 2 2 2 2
80 51.94334 54.02108 56.18192 58.42920 60.76636 4 4 4 4 2 2 2 2 2
81 52.98221 55.10150 57.30556 59.59778 61.98169 4 4 4 4 2 2 2 2 2
82 54.04185 56.20353 58.45167 60.78974 63.22132 4 4 4 4 2 2 2 2 2
83 55.12269 57.32760 59.62070 62.00553 64.48575 4 4 4 4 2 2 2 2 2
84 56.22514 58.47415 60.81312 63.24564 65.77547 4 4 4 4 2 2 2 2 2
85 57.34965 59.64363 62.02938 64.51055 67.09098 4 4 4 4 2 2 2 2 2
86 58.49664 60.83651 63.26997 65.80076 68.43280 4 4 4 4 2 2 2 2 2
87 59.66657 62.05324 64.53537 67.11678 69.80145 4 4 4 4 2 2 2 2 2
88 60.85990 63.29430 65.82607 68.45912 71.19748 4 4 4 4 2 2 2 2 2

4.3.4 Alt #3: Dual-Tier Tapering

Ranges 29-47:

  • 5% between steps
  • 2.5% between ranges

Range 47-88:

  • 5% steps
  • 2% ranges
Show the code
# Display salary schedules
display_salary_schedule(salary_schedule_1021_alt3_analyzed)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 19.87 20.86 21.90 23.00 5 5 5 5 NA NA NA NA NA
30 19.39 20.36 21.38 22.45 23.57 5 5 5 5 2.5 2.5 2.5 2.5 2.5
31 19.88 20.87 21.92 23.01 24.16 5 5 5 5 2.5 2.5 2.5 2.5 2.5
32 20.37 21.39 22.46 23.59 24.77 5 5 5 5 2.5 2.5 2.5 2.5 2.5
33 20.88 21.93 23.02 24.18 25.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
34 21.41 22.48 23.60 24.78 26.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
35 21.94 23.04 24.19 25.40 26.67 5 5 5 5 2.5 2.5 2.5 2.5 2.5
36 22.49 23.61 24.80 26.03 27.34 5 5 5 5 2.5 2.5 2.5 2.5 2.5
37 23.05 24.20 25.42 26.69 28.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
38 23.63 24.81 26.05 27.35 28.72 5 5 5 5 2.5 2.5 2.5 2.5 2.5
39 24.22 25.43 26.70 28.04 29.44 5 5 5 5 2.5 2.5 2.5 2.5 2.5
40 24.82 26.07 27.37 28.74 30.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
41 25.45 26.72 28.05 29.46 30.93 5 5 5 5 2.5 2.5 2.5 2.5 2.5
42 26.08 27.39 28.75 30.19 31.70 5 5 5 5 2.5 2.5 2.5 2.5 2.5
43 26.73 28.07 29.47 30.95 32.49 5 5 5 5 2.5 2.5 2.5 2.5 2.5
44 27.40 28.77 30.21 31.72 33.31 5 5 5 5 2.5 2.5 2.5 2.5 2.5
45 28.09 29.49 30.97 32.51 34.14 5 5 5 5 2.5 2.5 2.5 2.5 2.5
46 28.79 30.23 31.74 33.33 34.99 5 5 5 5 2.5 2.5 2.5 2.5 2.5
47 29.51 30.98 32.53 34.16 35.87 5 5 5 5 2.5 2.5 2.5 2.5 2.5
48 30.10 31.60 33.18 34.84 36.59 5 5 5 5 2 2 2 2 2
49 30.70 32.24 33.85 35.54 37.32 5 5 5 5 2 2 2 2 2
50 31.31 32.88 34.52 36.25 38.06 5 5 5 5 2 2 2 2 2
51 31.94 33.54 35.22 36.98 38.82 5 5 5 5 2 2 2 2 2
52 32.58 34.21 35.92 37.72 39.60 5 5 5 5 2 2 2 2 2
53 33.23 34.89 36.64 38.47 40.39 5 5 5 5 2 2 2 2 2
54 33.90 35.59 37.37 39.24 41.20 5 5 5 5 2 2 2 2 2
55 34.57 36.30 38.12 40.02 42.03 5 5 5 5 2 2 2 2 2
56 35.27 37.03 38.88 40.82 42.87 5 5 5 5 2 2 2 2 2
57 35.97 37.77 39.66 41.64 43.72 5 5 5 5 2 2 2 2 2
58 36.69 38.52 40.45 42.47 44.60 5 5 5 5 2 2 2 2 2
59 37.42 39.30 41.26 43.32 45.49 5 5 5 5 2 2 2 2 2
60 38.17 40.08 42.09 44.19 46.40 5 5 5 5 2 2 2 2 2
61 38.94 40.88 42.93 45.07 47.33 5 5 5 5 2 2 2 2 2
62 39.71 41.70 43.79 45.97 48.27 5 5 5 5 2 2 2 2 2
63 40.51 42.53 44.66 46.89 49.24 5 5 5 5 2 2 2 2 2
64 41.32 43.39 45.55 47.83 50.22 5 5 5 5 2 2 2 2 2
65 42.15 44.25 46.47 48.79 51.23 5 5 5 5 2 2 2 2 2
66 42.99 45.14 47.40 49.76 52.25 5 5 5 5 2 2 2 2 2
67 43.85 46.04 48.34 50.76 53.30 5 5 5 5 2 2 2 2 2
68 44.73 46.96 49.31 51.78 54.36 5 5 5 5 2 2 2 2 2
69 45.62 47.90 50.30 52.81 55.45 5 5 5 5 2 2 2 2 2
70 46.53 48.86 51.30 53.87 56.56 5 5 5 5 2 2 2 2 2
71 47.46 49.84 52.33 54.94 57.69 5 5 5 5 2 2 2 2 2
72 48.41 50.83 53.37 56.04 58.85 5 5 5 5 2 2 2 2 2
73 49.38 51.85 54.44 57.16 60.02 5 5 5 5 2 2 2 2 2
74 50.37 52.89 55.53 58.31 61.22 5 5 5 5 2 2 2 2 2
75 51.38 53.94 56.64 59.47 62.45 5 5 5 5 2 2 2 2 2
76 52.40 55.02 57.77 60.66 63.70 5 5 5 5 2 2 2 2 2
77 53.45 56.12 58.93 61.88 64.97 5 5 5 5 2 2 2 2 2
78 54.52 57.25 60.11 63.11 66.27 5 5 5 5 2 2 2 2 2
79 55.61 58.39 61.31 64.38 67.59 5 5 5 5 2 2 2 2 2
80 56.72 59.56 62.54 65.66 68.95 5 5 5 5 2 2 2 2 2
81 57.86 60.75 63.79 66.98 70.33 5 5 5 5 2 2 2 2 2
82 59.01 61.96 65.06 68.32 71.73 5 5 5 5 2 2 2 2 2
83 60.19 63.20 66.36 69.68 73.17 5 5 5 5 2 2 2 2 2
84 61.40 64.47 67.69 71.08 74.63 5 5 5 5 2 2 2 2 2
85 62.63 65.76 69.05 72.50 76.12 5 5 5 5 2 2 2 2 2
86 63.88 67.07 70.43 73.95 77.65 5 5 5 5 2 2 2 2 2
87 65.16 68.41 71.84 75.43 79.20 5 5 5 5 2 2 2 2 2
88 66.46 69.78 73.27 76.94 80.78 5 5 5 5 2 2 2 2 2

4.3.5 Alt #4: Triple-Tier Tapering

Ranges 29-47:

  • 5% between steps
  • 2.5% between ranges

Ranges 47-79:

  • 5% steps
  • 2% ranges

Ranges 80-88

  • 5% steps
  • 1.5% ranges
Show the code
# Display salary schedules
display_salary_schedule(salary_schedule_1021_alt4_analyzed)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 18.92 19.87 20.86 21.90 23.00 5 5 5 5 NA NA NA NA NA
30 19.39 20.36 21.38 22.45 23.57 5 5 5 5 2.5 2.5 2.5 2.5 2.5
31 19.88 20.87 21.92 23.01 24.16 5 5 5 5 2.5 2.5 2.5 2.5 2.5
32 20.37 21.39 22.46 23.59 24.77 5 5 5 5 2.5 2.5 2.5 2.5 2.5
33 20.88 21.93 23.02 24.18 25.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
34 21.41 22.48 23.60 24.78 26.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
35 21.94 23.04 24.19 25.40 26.67 5 5 5 5 2.5 2.5 2.5 2.5 2.5
36 22.49 23.61 24.80 26.03 27.34 5 5 5 5 2.5 2.5 2.5 2.5 2.5
37 23.05 24.20 25.42 26.69 28.02 5 5 5 5 2.5 2.5 2.5 2.5 2.5
38 23.63 24.81 26.05 27.35 28.72 5 5 5 5 2.5 2.5 2.5 2.5 2.5
39 24.22 25.43 26.70 28.04 29.44 5 5 5 5 2.5 2.5 2.5 2.5 2.5
40 24.82 26.07 27.37 28.74 30.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
41 25.45 26.72 28.05 29.46 30.93 5 5 5 5 2.5 2.5 2.5 2.5 2.5
42 26.08 27.39 28.75 30.19 31.70 5 5 5 5 2.5 2.5 2.5 2.5 2.5
43 26.73 28.07 29.47 30.95 32.49 5 5 5 5 2.5 2.5 2.5 2.5 2.5
44 27.40 28.77 30.21 31.72 33.31 5 5 5 5 2.5 2.5 2.5 2.5 2.5
45 28.09 29.49 30.97 32.51 34.14 5 5 5 5 2.5 2.5 2.5 2.5 2.5
46 28.79 30.23 31.74 33.33 34.99 5 5 5 5 2.5 2.5 2.5 2.5 2.5
47 29.51 30.98 32.53 34.16 35.87 5 5 5 5 2.5 2.5 2.5 2.5 2.5
48 30.10 31.60 33.18 34.84 36.59 5 5 5 5 2 2 2 2 2
49 30.70 32.24 33.85 35.54 37.32 5 5 5 5 2 2 2 2 2
50 31.31 32.88 34.52 36.25 38.06 5 5 5 5 2 2 2 2 2
51 31.94 33.54 35.22 36.98 38.82 5 5 5 5 2 2 2 2 2
52 32.58 34.21 35.92 37.72 39.60 5 5 5 5 2 2 2 2 2
53 33.23 34.89 36.64 38.47 40.39 5 5 5 5 2 2 2 2 2
54 33.90 35.59 37.37 39.24 41.20 5 5 5 5 2 2 2 2 2
55 34.57 36.30 38.12 40.02 42.03 5 5 5 5 2 2 2 2 2
56 35.27 37.03 38.88 40.82 42.87 5 5 5 5 2 2 2 2 2
57 35.97 37.77 39.66 41.64 43.72 5 5 5 5 2 2 2 2 2
58 36.69 38.52 40.45 42.47 44.60 5 5 5 5 2 2 2 2 2
59 37.42 39.30 41.26 43.32 45.49 5 5 5 5 2 2 2 2 2
60 38.17 40.08 42.09 44.19 46.40 5 5 5 5 2 2 2 2 2
61 38.94 40.88 42.93 45.07 47.33 5 5 5 5 2 2 2 2 2
62 39.71 41.70 43.79 45.97 48.27 5 5 5 5 2 2 2 2 2
63 40.51 42.53 44.66 46.89 49.24 5 5 5 5 2 2 2 2 2
64 41.32 43.39 45.55 47.83 50.22 5 5 5 5 2 2 2 2 2
65 42.15 44.25 46.47 48.79 51.23 5 5 5 5 2 2 2 2 2
66 42.99 45.14 47.40 49.76 52.25 5 5 5 5 2 2 2 2 2
67 43.85 46.04 48.34 50.76 53.30 5 5 5 5 2 2 2 2 2
68 44.73 46.96 49.31 51.78 54.36 5 5 5 5 2 2 2 2 2
69 45.62 47.90 50.30 52.81 55.45 5 5 5 5 2 2 2 2 2
70 46.53 48.86 51.30 53.87 56.56 5 5 5 5 2 2 2 2 2
71 47.46 49.84 52.33 54.94 57.69 5 5 5 5 2 2 2 2 2
72 48.41 50.83 53.37 56.04 58.85 5 5 5 5 2 2 2 2 2
73 49.38 51.85 54.44 57.16 60.02 5 5 5 5 2 2 2 2 2
74 50.37 52.89 55.53 58.31 61.22 5 5 5 5 2 2 2 2 2
75 51.38 53.94 56.64 59.47 62.45 5 5 5 5 2 2 2 2 2
76 52.40 55.02 57.77 60.66 63.70 5 5 5 5 2 2 2 2 2
77 53.45 56.12 58.93 61.88 64.97 5 5 5 5 2 2 2 2 2
78 54.52 57.25 60.11 63.11 66.27 5 5 5 5 2 2 2 2 2
79 55.61 58.39 61.31 64.38 67.59 5 5 5 5 2 2 2 2 2
80 56.44 59.27 62.23 65.34 68.61 5 5 5 5 1.5 1.5 1.5 1.5 1.5
81 57.29 60.16 63.16 66.32 69.64 5 5 5 5 1.5 1.5 1.5 1.5 1.5
82 58.15 61.06 64.11 67.32 70.68 5 5 5 5 1.5 1.5 1.5 1.5 1.5
83 59.02 61.97 65.07 68.33 71.74 5 5 5 5 1.5 1.5 1.5 1.5 1.5
84 59.91 62.90 66.05 69.35 72.82 5 5 5 5 1.5 1.5 1.5 1.5 1.5
85 60.81 63.85 67.04 70.39 73.91 5 5 5 5 1.5 1.5 1.5 1.5 1.5
86 61.72 64.80 68.05 71.45 75.02 5 5 5 5 1.5 1.5 1.5 1.5 1.5
87 62.64 65.78 69.07 72.52 76.15 5 5 5 5 1.5 1.5 1.5 1.5 1.5
88 63.58 66.76 70.10 73.61 77.29 5 5 5 5 1.5 1.5 1.5 1.5 1.5
Show the code
# Create function to match salary schedules to roster and calculate raises

process_alt_salary_schedule <- function(roster_data, salary_schedule, alt_number, appropriate_schedules) {
  # Reshape the salary_schedule to long format
  salary_schedule_long <- salary_schedule %>%
    pivot_longer(
      cols = starts_with("Step"),
      names_to = "Step",
      values_to = paste0("New_Hourly_Wage_Alt", alt_number)
    ) %>%
    mutate(Step = as.numeric(gsub("Step", "", Step)))

  # Join and calculate new salaries
  roster_data <- roster_data %>%
    left_join(salary_schedule_long, by = c("Range", "Step")) %>%
    mutate(
      !!sym(paste0("New_Hourly_Wage_Alt", alt_number)) := case_when(
        SalarySchedule %in% appropriate_schedules ~ !!sym(paste0("New_Hourly_Wage_Alt", alt_number)),
        TRUE ~ New_Hourly_Wage_4p
      ),
      !!sym(paste0("New_Annual_Salary_Alt", alt_number)) := !!sym(paste0("New_Hourly_Wage_Alt", alt_number)) * `Annual Hours Paid` * FTE,
      !!sym(paste0("Wage_Alt", alt_number, "_Increase")) := !!sym(paste0("New_Hourly_Wage_Alt", alt_number)) - New_Hourly_Wage_4p,
      !!sym(paste0("Raise_Alt", alt_number)) := !!sym(paste0("New_Annual_Salary_Alt", alt_number)) - New_Annual_Salary_4p,
      !!sym(paste0("Raise_Alt", alt_number, "_perc")) := round(((!!sym(paste0("New_Annual_Salary_Alt", alt_number)) / New_Annual_Salary_4p) - 1) * 100, 1)
    )

  return(roster_data)
}

# Process all three alternative salary schedules
roster_with_SS_pay <- roster_with_SS_pay %>%
  process_alt_salary_schedule(salary_schedule_1021_alt1, 1, appropriate_schedules) %>%
  process_alt_salary_schedule(salary_schedule_1021_alt2, 2, appropriate_schedules) %>%
  process_alt_salary_schedule(salary_schedule_1021_alt2p1, 2.1, appropriate_schedules) %>%
  process_alt_salary_schedule(salary_schedule_1021_alt3, 3, appropriate_schedules) |> 
  process_alt_salary_schedule(salary_schedule_1021_alt4, 4, appropriate_schedules)
Show the code
# Summarize and pull value for RaiseSSFix
total_annual_salary_increase_al1 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise_Alt1, na.rm = TRUE)) %>%
  pull(total_cost)

total_annual_salary_increase_al2 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise_Alt2, na.rm = TRUE)) %>%
  pull(total_cost)

total_annual_salary_increase_al2p1 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(`Raise_Alt2.1`, na.rm = TRUE)) %>%
  pull(total_cost)

total_annual_salary_increase_al3 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise_Alt3, na.rm = TRUE)) %>%
  pull(total_cost)

total_annual_salary_increase_al4 <- roster_with_SS_pay %>%
  summarise(total_cost = sum(Raise_Alt4, na.rm = TRUE)) %>%
  pull(total_cost)

4.3.6 Summary Table and Plot

Show the code
# Display salary schedules
# Create a data frame for the table
cost_table <- data.frame(
  Description = c("Squaring the Salary Schedule (1021)",
                  "Squaring the Salary Schedule (SCUSD)",
                  "Alternative 1",
                  "Alternative 2",
                  "Alternative 2.1",
                  "Alternative 3",
                  "Alternative 4"),
  Cost_Raw = c(total_annual_salary_increase,
               total_annual_salary_increase_scusd,
               total_annual_salary_increase_al1,
               total_annual_salary_increase_al2,
               total_annual_salary_increase_al2p1,
               total_annual_salary_increase_al3,
               total_annual_salary_increase_al4))

# Calculate Cost_With_Factor using vectorized operation
cost_table$Cost_With_Factor <- cost_table$Cost_Raw * tpf_median

# Get 2024 Unrestricted Ending Balance from Sacramento_USD_filtered_net_rev_and_urf_tot_divided_by_mil$Type. Filtered to "UnrestrictedFund." $YearEnd == 2024
unrestricted_ending_balance_2024 <- Sacramento_USD_filtered_net_rev_and_urf_tot %>%
  filter(Type == "UnrestrictedFund", YearEnd == 2024) %>%
  pull(Value)

# Add the unrestricted ending balance to the cost_table
cost_table <- cost_table %>%
  add_row(Description = "Unrestricted Ending Balance 2024",
           Cost_Raw = unrestricted_ending_balance_2024,
           Cost_With_Factor = unrestricted_ending_balance_2024)

# Add column that is Cost_With_Factor as a percentage of unrestricted ending balance
cost_table <- cost_table %>%
  mutate(Cost_Percent_Unrestricted = round(Cost_With_Factor / unrestricted_ending_balance_2024 * 100, 1))

# Sort in descending order
cost_table_plot <- cost_table %>%
  arrange(desc(Cost_Raw)) |> # divide by million and round to 1 decimal
  mutate(Cost_Raw = round(Cost_Raw / 1e6, 1),
         Cost_With_Factor = round(Cost_With_Factor / 1e6, 1))

# Format the costs as currency in millions with commas, rounded to 1 decimal place, save as new df
cost_table_formatted <- cost_table %>%
  mutate(Cost_Raw = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(Cost_Raw),
         Cost_With_Factor = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(Cost_With_Factor))

# Create the kable table
kable(cost_table_formatted, 
  col.names = c("Proposal", "Cost (Raw)", "Cost (w/TPF of 1.27)", "Cost (w/TPF) as % of UR Fund"),
  align = c("l", "r", "r", "r"),
  caption = "Salary Raise Proposals and Costs (in Millions of Dollars)")
Salary Raise Proposals and Costs (in Millions of Dollars)
Proposal Cost (Raw) Cost (w/TPF of 1.27) Cost (w/TPF) as % of UR Fund
Squaring the Salary Schedule (1021) $13.1M $16.7M 9.7
Squaring the Salary Schedule (SCUSD) $6.6M $8.4M 4.9
Alternative 1 $7.8M $10.0M 5.8
Alternative 2 $7.4M $9.4M 5.4
Alternative 2.1 $6.9M $8.8M 5.1
Alternative 3 $12.1M $15.3M 8.9
Alternative 4 $12.0M $15.2M 8.9
Unrestricted Ending Balance 2024 $172.0M $172.0M 100.0
Show the code
# Create the lollipop plot of cost_table_plot
cost_table_plot %>%
  ggplot(aes(x = reorder(Description, Cost_With_Factor), y = Cost_With_Factor)) +
  geom_segment(aes(xend = Description, yend = 0), color = "grey") +
  geom_point(size = 12, color = "purple") +
  coord_flip() +
  geom_text(aes(label = `Cost_With_Factor`), vjust = .5, size = 4, color="white", fontface="bold", family="Avenir Next Condensed") +
  labs(title = "Total Annual Costs of Squaring the Salary Schedule",
       x = "Proposal",
       y = "Total Annual Cost (in Millions of Dollars)") +
  My_Theme_WithY() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

4.4 Summary Tables of All Proposals

Show the code
# Calculate 2% raise cost being applied to different salary schedules
# In roster_with_SS_pay, create new columns which are the following salary schedules * 1.02
# New_Annual_Salary_SSFix_SCUSD
# New_Annual_Salary_Alt1
# New_Annual_Salary_Alt2
# New_Annual_Salary_Alt3

roster_with_SS_pay <- roster_with_SS_pay %>%
  mutate(
    New_Annual_Salary_SSFix_SCUSD_2p = New_Annual_Salary_SSFix_SCUSD * 1.04,
    New_Annual_Salary_Alt1_2p = New_Annual_Salary_Alt1 * 1.04,
    New_Annual_Salary_Alt2_2p = New_Annual_Salary_Alt2 * 1.04,
    `New_Annual_Salary_Alt2.1_2p` = `New_Annual_Salary_Alt2.1` * 1.04,
    New_Annual_Salary_Alt3_2p = New_Annual_Salary_Alt3 * 1.04,
    New_Annual_Salary_Alt4_2p = New_Annual_Salary_Alt4 * 1.04
  ) |> # Create 4 new columns that are the difference between the new salary schedule and the original salary schedule
  mutate(
    WageSSFix_SCUSD_Increase_2p = New_Annual_Salary_SSFix_SCUSD_2p - New_Annual_Salary_SSFix_SCUSD,
    Wage_Alt1_Increase_2p = New_Annual_Salary_Alt1_2p - New_Annual_Salary_Alt1,
    Wage_Alt2_Increase_2p = New_Annual_Salary_Alt2_2p - New_Annual_Salary_Alt2,
    Wage_Alt2p1_Increase_2p = `New_Annual_Salary_Alt2.1_2p` - `New_Annual_Salary_Alt2.1`,
    Wage_Alt3_Increase_2p = New_Annual_Salary_Alt3_2p - New_Annual_Salary_Alt3,
    Wage_Alt4_Increase_2p = New_Annual_Salary_Alt4_2p - New_Annual_Salary_Alt4
  )
  
# Create new df that is the summary (total cost) of the 2% raise for each salary schedule. It should be 5 rows for each salary schedule. `Raise2p` is column for the first salary scheudle, `Raise2p_Alt1` is the column for the second salary schedule, etc.
cost_raise_2perc_all_2024 <- roster_with_SS_pay %>%
  summarise(
    Raise2p = sum(Raise2p, na.rm = TRUE),
    Raise2p_SCUSD = sum(WageSSFix_SCUSD_Increase_2p, na.rm = TRUE),
    Raise2p_Alt1 = sum(Wage_Alt1_Increase_2p, na.rm = TRUE),
    Raise2p_Alt2 = sum(Wage_Alt2_Increase_2p, na.rm = TRUE),
    Raise2p_Alt2p1 = sum(Wage_Alt2p1_Increase_2p, na.rm = TRUE),
    Raise2p_Alt3 = sum(Wage_Alt3_Increase_2p, na.rm = TRUE),
    Raise2p_Alt4 = sum(Wage_Alt4_Increase_2p, na.rm = TRUE)
  ) |> # make long
  pivot_longer(
    cols = everything(),
    names_to = "Salary_Schedule",
    values_to = "Total_Cost"
  )

# Rename columns so they match this
# Squaring the Salary Schedule (1021)
# Squaring the Salary Schedule (SCUSD)
# Alternative 1
# Alternative 2
# Alternative 3
cost_raise_2perc_all_2024 <- cost_raise_2perc_all_2024 %>%
  mutate(
    Salary_Schedule = case_when(
      Salary_Schedule == "Raise2p" ~ "Squaring the Salary Schedule (1021)",
      Salary_Schedule == "Raise2p_SCUSD" ~ "Squaring the Salary Schedule (SCUSD)",
      Salary_Schedule == "Raise2p_Alt1" ~ "Alternative 1",
      Salary_Schedule == "Raise2p_Alt2" ~ "Alternative 2",
      Salary_Schedule == "Raise2p_Alt2p1" ~ "Alternative 2.1",
      Salary_Schedule == "Raise2p_Alt3" ~ "Alternative 3",
      Salary_Schedule == "Raise2p_Alt4" ~ "Alternative 4"
    )
  )

4.4.1 Annual Costs

Below is the ongoing cost of all proposals. Specifically:

Add:

  • 2% raise
  • 2024-2025 Salary Schedule Fix
  • 2024-2025 4% Raise (reminder: 4% is applied to the new salary schedule, not the original salary schedule)

Equals:

  • Ongoing cost
Show the code
# Take cost_table, turn into new DF, remove final row
cost_table_1yr <- cost_table[-nrow(cost_table), ]
cost_table_1yr <- cost_table_1yr %>%
  select(-Cost_With_Factor, -Cost_Percent_Unrestricted) %>%
  rename(`SS Cost (Raw)` = Cost_Raw)

# Add new columns and calculate totals
cost_table_1yr <- cost_table_1yr %>%
  add_column(`4% Raise (2y)` = cost_raise_4perc_all_2023, .before = 1)

# Join cost_raise_2perc_all_2024 to cost_table_1yr and rename new column "2% Raise 2024-25"
cost_table_1yr <- cost_table_1yr %>%
  left_join(cost_raise_2perc_all_2024, by = c("Description" = "Salary_Schedule")) |> 
  rename(`2% Raise 2024-25` = Total_Cost) |>
  mutate(
    `Total 1-Year Cost (Raw)` = `4% Raise (2y)` + `SS Cost (Raw)` + `2% Raise 2024-25`,
    `Total 1-Year Cost (TPF)` = `Total 1-Year Cost (Raw)` * tpf_median,
    `Total 1-Year Cost (TPF) as % of UR Fund` = round(`Total 1-Year Cost (TPF)` / unrestricted_ending_balance_2024 * 100, 1)
  ) %>%
  arrange(desc(`Total 1-Year Cost (Raw)`))

# Turn into cost_table_1yr_formatted with the costs as currency in millions with commas, rounded to 1 decimal place
cost_table_1yr_formatted <- cost_table_1yr %>%
  mutate(
    `4% Raise (2y)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`4% Raise (2y)`),
    `SS Cost (Raw)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`SS Cost (Raw)`),
    `2% Raise 2024-25` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`2% Raise 2024-25`),
    `Total 1-Year Cost (Raw)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total 1-Year Cost (Raw)`),
    `Total 1-Year Cost (TPF)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total 1-Year Cost (TPF)`)
  )


# # Kable
kable(cost_table_1yr_formatted,
  col.names = c("2% Raise", "SS Description", "SS Cost (Raw)", "4% Raise", "Total 1-Year Cost (Raw)", "Total 1-Year Cost (TPF of 1.27)", "Total 1-Year Cost (TPF) as % of UR Fund"),
  align = c("r", "l", "r", "r", "r", "r", "r"),
  caption = "One-Year Costs of Salary Raise Proposals (in Millions of Dollars)")
One-Year Costs of Salary Raise Proposals (in Millions of Dollars)
2% Raise SS Description SS Cost (Raw) 4% Raise Total 1-Year Cost (Raw) Total 1-Year Cost (TPF of 1.27) Total 1-Year Cost (TPF) as % of UR Fund
$1.3M Squaring the Salary Schedule (1021) $13.1M $3.1M $17.5M $22.2M 12.9
$1.3M Alternative 3 $12.1M $3.1M $16.4M $20.8M 12.1
$1.3M Alternative 4 $12.0M $3.1M $16.3M $20.7M 12.0
$1.3M Alternative 1 $7.8M $2.9M $12.0M $15.2M 8.9
$1.3M Alternative 2 $7.4M $2.9M $11.5M $14.6M 8.5
$1.3M Alternative 2.1 $6.9M $2.9M $11.0M $14.0M 8.2
$1.3M Squaring the Salary Schedule (SCUSD) $6.6M $2.8M $10.7M $13.6M 7.9

4.4.2 Two Year Costs (2023-2025)

Exact same as above, except the 4% raise gets counted twice, since it’s being applied retroactively for a year.

Show the code
# Take cost_table, turn into new DF, remove final row
cost_table_2yr <- cost_table[-nrow(cost_table), ]
cost_table_2yr <- cost_table_2yr %>%
  select(-Cost_With_Factor, -Cost_Percent_Unrestricted) %>%
  rename(`SS Cost (Raw)` = Cost_Raw)

# Add new columns and calculate totals
cost_table_2yr <- cost_table_2yr %>%
  add_column(`4% Raise (2y)` = cost_raise_4perc_all_2023 * 2, .before = 1)

# Join cost_raise_2perc_all_2024 to cost_table_2yr and rename new column "2% Raise 2024-25"
cost_table_2yr <- cost_table_2yr %>%
  left_join(cost_raise_2perc_all_2024, by = c("Description" = "Salary_Schedule")) |> 
  rename(`2% Raise 2024-25` = Total_Cost) |>
  mutate(
    `Total 2-Year Cost (Raw)` = `4% Raise (2y)` + `SS Cost (Raw)` + `2% Raise 2024-25`,
    `Total 2-Year Cost (TPF)` = `Total 2-Year Cost (Raw)` * tpf_median,
    `Total 2-Year Cost (TPF) as % of UR Fund` = round(`Total 2-Year Cost (TPF)` / unrestricted_ending_balance_2024 * 100, 1)
  ) %>%
  arrange(desc(`Total 2-Year Cost (Raw)`))

# Turn into cost_table_2yr_formatted with the costs as currency in millions with commas, rounded to 1 decimal place
cost_table_2yr_formatted <- cost_table_2yr %>%
  mutate(
    `4% Raise (2y)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`4% Raise (2y)`),
    `SS Cost (Raw)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`SS Cost (Raw)`),
    `2% Raise 2024-25` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`2% Raise 2024-25`),
    `Total 2-Year Cost (Raw)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total 2-Year Cost (Raw)`),
    `Total 2-Year Cost (TPF)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total 2-Year Cost (TPF)`)
  )


# # Kable
kable(cost_table_2yr_formatted,
  col.names = c("2% Raise (2y)", "SS Description", "SS Cost (Raw)", "4% Raise 2024-25", "Total 2-Year Cost (Raw)", "Total 2-Year Cost (TPF of 1.27)", "Total 2-Year Cost (TPF) as % of UR Fund"),
  align = c("r", "l", "r", "r", "r", "r", "r"),
  caption = "Two-Year Costs of Salary Raise Proposals (in Millions of Dollars)")
Two-Year Costs of Salary Raise Proposals (in Millions of Dollars)
2% Raise (2y) SS Description SS Cost (Raw) 4% Raise 2024-25 Total 2-Year Cost (Raw) Total 2-Year Cost (TPF of 1.27) Total 2-Year Cost (TPF) as % of UR Fund
$2.5M Squaring the Salary Schedule (1021) $13.1M $3.1M $18.8M $23.8M 13.9
$2.5M Alternative 3 $12.1M $3.1M $17.7M $22.5M 13.1
$2.5M Alternative 4 $12.0M $3.1M $17.6M $22.3M 13.0
$2.5M Alternative 1 $7.8M $2.9M $13.3M $16.9M 9.8
$2.5M Alternative 2 $7.4M $2.9M $12.8M $16.2M 9.4
$2.5M Alternative 2.1 $6.9M $2.9M $12.3M $15.6M 9.1
$2.5M Squaring the Salary Schedule (SCUSD) $6.6M $2.8M $12.0M $15.2M 8.9
Show the code
# Take cost_table_2yrkeep only column 2 and 6 and add unrestricted ending balance
cost_table_plot_2yr_plot <- cost_table_2yr |> 
  select(Description, `Total 2-Year Cost (TPF)`) |> 
  add_row(Description = "Unrestricted Ending Balance 2024",
           `Total 2-Year Cost (TPF)` = unrestricted_ending_balance_2024) |> # sort in descending order
  arrange(desc(`Total 2-Year Cost (TPF)`)) |> # divide by million and round to 1 decimal
  mutate(`Total 2-Year Cost (TPF)` = round(`Total 2-Year Cost (TPF)` / 1e6, 1))
Show the code
# Create the lollipop plot of cost_table_plot
cost_table_plot_2yr_plot %>%
  ggplot(aes(x = reorder(Description, `Total 2-Year Cost (TPF)`), y = `Total 2-Year Cost (TPF)`)) +
  geom_segment(aes(xend = Description, yend = 0), color = "grey") +
  geom_point(size = 12, color = "purple") +
  coord_flip() +
  geom_text(aes(label = `Total 2-Year Cost (TPF)`), vjust = .5, size = 4, color="white", fontface="bold", family="Avenir Next Condensed") +
  labs(title = "Total Two-Year Costs of all Proposals (2023-2025)",
       x = "Proposal",
       y = "Total Two-Year Cost (in Millions of Dollars)") +
  My_Theme_WithY() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

4.4.3 Summary Table With Differrent Costing Assumptions

Below I estimated the two-year cost including two different assumptions:

  1. A Total Payroll Factor (TPF) of 1.4 instead of 1.27.

  2. A “Vacancy Charge” of 23% on top of the total cost. Employers typically budget and cost out a fully-staffed bargaining unit, which never happens in reality. The “Vacancy Charge” is my estimate to account for this budgeting assumption.

Show the code
tpf_high <- 1.4

# Take cost_table, turn into new DF, remove final row
cost_table_2yr_new_ass <- cost_table[-nrow(cost_table), ]
cost_table_2yr_new_ass <- cost_table_2yr_new_ass %>%
  select(-Cost_With_Factor, -Cost_Percent_Unrestricted) %>%
  rename(`SS Cost (Raw)` = Cost_Raw)

# Add new columns and calculate totals
cost_table_2yr_new_ass <- cost_table_2yr_new_ass %>%
  add_column(`4% Raise (2y)` = cost_raise_4perc_all_2023 * 2, .before = 1)

# Join cost_raise_2perc_all_2024 to cost_table_2yr_new_ass and rename new column "2% Raise 2024-25"
cost_table_2yr_new_ass <- cost_table_2yr_new_ass %>%
  left_join(cost_raise_2perc_all_2024, by = c("Description" = "Salary_Schedule")) |> 
  rename(`2% Raise 2024-25` = Total_Cost) |>
  mutate(
    `Total 2-Year Cost (Raw)` = `4% Raise (2y)` + `SS Cost (Raw)` + `2% Raise 2024-25`,
    `Total 2-Year Cost (TPF)` = `Total 2-Year Cost (Raw)` * tpf_high,
    `Total w/ Vacancy Charge (1.23)` = `Total 2-Year Cost (TPF)` * 1.23,
    `Total 2-Year Cost (TPF) as % of UR Fund` = round(`Total w/ Vacancy Charge (1.23)` / unrestricted_ending_balance_2024 * 100, 1)
  ) %>%
  arrange(desc(`Total 2-Year Cost (Raw)`))

# Turn into cost_table_2yr_new_ass_formatted with the costs as currency in millions with commas, rounded to 1 decimal place
cost_table_2yr_new_ass_formatted <- cost_table_2yr_new_ass %>%
  mutate(
    `4% Raise (2y)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`4% Raise (2y)`),
    `SS Cost (Raw)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`SS Cost (Raw)`),
    `2% Raise 2024-25` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`2% Raise 2024-25`),
    `Total 2-Year Cost (Raw)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total 2-Year Cost (Raw)`),
    `Total w/ Vacancy Charge (1.23)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total w/ Vacancy Charge (1.23)`),
    `Total 2-Year Cost (TPF)` = dollar_format(scale = 1e-6, prefix = "$", suffix = "M", accuracy = 0.1)(`Total 2-Year Cost (TPF)`)
  )

# Kable
kable(cost_table_2yr_new_ass_formatted,
  col.names = c("4% Raise (2y)", "SS Description", "SS Cost (Raw)", "2% Raise 2024-25", "Total 2-Year Cost (Raw)", "Total 2-Year Cost (TPF of 1.39)", "Total w/ Vacancy Charge (1.23)", "Total (all assumptions) % of UR Fund"),
  align = c("r", "l", "r", "r", "r", "r", "r", "r"),
  caption = "Two-Year Costs of Salary Raise Proposals (in Millions of Dollars)")
Two-Year Costs of Salary Raise Proposals (in Millions of Dollars)
4% Raise (2y) SS Description SS Cost (Raw) 2% Raise 2024-25 Total 2-Year Cost (Raw) Total 2-Year Cost (TPF of 1.39) Total w/ Vacancy Charge (1.23) Total (all assumptions) % of UR Fund
$2.5M Squaring the Salary Schedule (1021) $13.1M $3.1M $18.8M $26.3M $32.4M 18.8
$2.5M Alternative 3 $12.1M $3.1M $17.7M $24.8M $30.5M 17.7
$2.5M Alternative 4 $12.0M $3.1M $17.6M $24.6M $30.3M 17.6
$2.5M Alternative 1 $7.8M $2.9M $13.3M $18.6M $22.9M 13.3
$2.5M Alternative 2 $7.4M $2.9M $12.8M $17.9M $22.0M 12.8
$2.5M Alternative 2.1 $6.9M $2.9M $12.3M $17.2M $21.2M 12.3
$2.5M Squaring the Salary Schedule (SCUSD) $6.6M $2.8M $12.0M $16.8M $20.7M 12.0
Show the code
cost_table_plot_2yr_plot_new_ass <- cost_table_2yr_new_ass |> 
  select(Description, `Total w/ Vacancy Charge (1.23)`) |> 
  add_row(Description = "Unrestricted Ending Balance 2024",
           `Total w/ Vacancy Charge (1.23)` = unrestricted_ending_balance_2024) |> # sort in descending order
  arrange(desc(`Total w/ Vacancy Charge (1.23)`)) |> # divide by million and round to 1 decimal
  mutate(`Total w/ Vacancy Charge (1.23)` = round(`Total w/ Vacancy Charge (1.23)` / 1e6, 1))

# Create the lollipop plot of cost_table_plot
cost_table_plot_2yr_plot_new_ass %>%
  ggplot(aes(x = reorder(Description, `Total w/ Vacancy Charge (1.23)`), y = `Total w/ Vacancy Charge (1.23)`)) +
  geom_segment(aes(xend = Description, yend = 0), color = "grey") +
  geom_point(size = 12, color = "purple") +
  coord_flip() +
  geom_text(aes(label = `Total w/ Vacancy Charge (1.23)`), vjust = .5, size = 4, color="white", fontface="bold", family="Avenir Next Condensed") +
  labs(title = "Total Two-Year Costs of all Proposals (2023-2025)",
       x = "Proposal",
       y = "Total Two-Year Cost (in Millions of Dollars)") +
  My_Theme_WithY() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

4.5 Distributional Analysis of Proposals

The graph below shows the exact percentage raise for each 1,878 Employee IDs in the bargaining unit. On the X-axis (left to right), they are ordered by initial annual salary. By sorting by initial annual salary, and then showing the percentage raise, we can see how the proposed raises are being distributed–whether it’s “progressive” (more to lower-paid members) or “regressive” (more to higher-paid). This scatterplot is then displayed for all 6 different proposals, so we can easily compare across proposals.

Show the code
# Reshape the data
plot_data <- roster_with_SS_pay %>%
  select(Initial_Annual_Salary, 
         RaiseSSFixperc, 
         RaiseSSFix_SCUSDperc, 
         Raise_Alt1_perc, 
         Raise_Alt2_perc, 
         `Raise_Alt2.1_perc`,
         Raise_Alt3_perc, 
         Raise_Alt4_perc,
         `Main Salary Schedule`) %>%
  pivot_longer(cols = -c(Initial_Annual_Salary, `Main Salary Schedule`),
               names_to = "Schedule", 
               values_to = "Percentage_Increase") %>%
  mutate(Schedule = factor(Schedule, 
                           levels = c("RaiseSSFixperc", 
                                      "RaiseSSFix_SCUSDperc", 
                                      "Raise_Alt1_perc", 
                                      "Raise_Alt2_perc",
                                      "Raise_Alt2.1_perc",
                                      "Raise_Alt3_perc", 
                                      "Raise_Alt4_perc"),
                           labels = c("SSFix", 
                                      "SSFix SCUSD", 
                                      "Alt1", 
                                      "Alt2",
                                      "Alt2.1",
                                      "Alt3", 
                                      "Alt4")))

# Relabel the Schedule factor
plot_data$Schedule <- factor(plot_data$Schedule,
  levels = c("SSFix", "SSFix SCUSD", "Alt1", "Alt2", "Alt2.1", "Alt3", "Alt4"),
  labels = c(
    "Initial 1021 Fix Proposal (2.5 & 5%)",
    "Initial SCUSD Fix Proposal (2 & 4.5% to Range 48)",
    "Alternative 1 (2 & 4.5%)",
    "Alternative 2 (2 & 4.25%)",
    "Alternative 2.1 (2 & 4.0%)",
    "Alternative 3  (Two-Tiered)",
    "Alternative 4 (Three-Tiered)"
  )
)

# Then create   plot
ggplot(plot_data, aes(x = Initial_Annual_Salary, y = Percentage_Increase, colour = `Main Salary Schedule`)) +
  geom_point(alpha = 0.5) +
  facet_wrap(~ Schedule, nrow = 4, ncol = 2) +
  labs(x = "Initial Annual Salary",
       y = "Percentage Increase",
       title = "Wage Increases (%) by Initial Annual Salary, for each proposed Salary Schedule Fix") +
  My_Theme_WithY() +
  scale_color_manual(values = c("FALSE" = "purple", "TRUE" = "black")) +
  geom_smooth(
    data = subset(plot_data, `Main Salary Schedule` == TRUE),
    method = "gam",
    formula = y ~ s(x, bs = "cs", k = 5),
    method.args = list(family = gaussian(link = "log")),
    se = FALSE,
    size = 1.5,
    color = "red") +
  theme(
    legend.position = "top",
    axis.text.x = element_text(angle = 45, hjust = 1),
    strip.text = element_text(face = "bold")
  )

4.5.1 Cases of Negative Raises from Salary Schedule Fixes

Depending on your costing assumptions, Alternative Proposal #2 (2% ranges, 4% steps) is only $300K to $500K more costly than the District’s initial proposal, despite fully fixing the salary schedule with no cliffs and a smooth progression of range and step increases. Unfortunately, at the top of the salary schedule, starting at Range 78, Step 5, some cells end up below the status quo (that is after the 4% retro). This is because the combination of the 2% and 4% differentials, which are lower in many cases than the current 2.5% and 5% differentials, results in a lower salary schedule for a handful of employees at the top. The table below shows the Employee IDs and their negative raises for each proposal.

A fix is relatively simple: just include language that “for any salary schedule cell that ends up lower than the status quo, the employee will receive the status quo salary.” Such a fix would solve the issue and cost negligible amounts of money.

Show the code
library(tidyverse)
library(kableExtra)

# Function to identify negative raise percentages across specified columns
find_negative_raises <- function(df) {
  # Vector of columns to check with their display names
  raise_cols <- c(
    "RaiseSSFixperc",
    "RaiseSSFix_SCUSDperc",
    "Raise_Alt1_perc",
    "Raise_Alt2_perc",
    "Raise_Alt2.1_perc",
    "Raise_Alt3_perc",
    "Raise_Alt4_perc"
  )
  
  # Create named vector for renaming
  proposal_names <- c(
    "RaiseSSFixperc" = "Initial 1021 Fix Proposal (2.5 & 5%)",
    "RaiseSSFix_SCUSDperc" = "Initial SCUSD Fix Proposal (2 & 4.5% to Range 48)",
    "Raise_Alt1_perc" = "Alternative 1 (2 & 4.5%)",
    "Raise_Alt2_perc" = "Alternative 2 (2 & 4.25%)",
    "Raise_Alt2.1_perc" = "Alternative 2.1 (2 & 4.0%)",
    "Raise_Alt3_perc" = "Alternative 3 (Two-Tiered)",
    "Raise_Alt4_perc" = "Alternative 4 (Three-Tiered)"
  )
  
  # Process data and create table
  result <- df %>%
    # Select only necessary columns
    select(
      `Emp ID`,
      Range,
      Step,
      all_of(raise_cols)
    ) %>%
    # Convert wide to long format
    pivot_longer(
      cols = all_of(raise_cols),
      names_to = "Proposal",
      values_to = "Value"
    ) %>%
    # Filter for negative values
    filter(Value < 0) %>%
    # Replace proposal names with descriptive versions
    mutate(Proposal = proposal_names[Proposal]) %>%
    # Arrange by Emp ID and Proposal
    arrange(`Emp ID`, Proposal) %>%
    # Sort by Value first (this will sort the numeric values before formatting)
    arrange(Value, `Emp ID`)
  
  # Format the Value column as percentage with one decimal place
  result$Value <- sprintf("%.1f%%", result$Value)
  
  # Create formatted kable output
  kable_output <- result %>%
    kable(
      col.names = c("Employee ID", "Range", "Step", "Proposal", "Value"),
      caption = "Employees with Negative Raise Percentages",
      align = c('r', 'r', 'r', 'l', 'r')
    ) %>%
    kable_styling(
      bootstrap_options = c("striped", "hover"),
      full_width = FALSE,
      position = "left"
    )
  
  return(kable_output)
}

# Example usage:
negative_raises_table <- find_negative_raises(roster_with_SS_pay)
negative_raises_table
Employees with Negative Raise Percentages
Employee ID Range Step Proposal Value
NA NA NA NA NA
-----------: -----: ----: :-------- -----:
Show the code
# Save roster_with_SS_pay to a csv file to here() output_data
write_csv(roster_with_SS_pay, here("Districts/Sacramento/output_data/", "roster_with_SS_pay.csv"))
write_csv(roster_SS_diff, here("Districts/Sacramento/output_data/", "roster_SS_diff.csv"))

4.6 Final Salary Schedule Proposals (after 4% raise is applied to SS fix)

Show the code
library(tidyverse)

# Function to adjust salaries with rounding
adjust_salaries <- function(df) {
  df %>%
    mutate(across(2:6, ~round(.x * 1.04, 2)))
}

# Apply adjustment to each dataframe
salary_schedule_1021_2023_24_adj <- adjust_salaries(salary_schedule_1021_analyzed_2023_24)
salary_schedule_1021_alt1_adj <- adjust_salaries(salary_schedule_1021_alt1_analyzed)
salary_schedule_1021_alt2_adj <- adjust_salaries(salary_schedule_1021_alt2_analyzed)
salary_schedule_1021_alt2p1_adj <- adjust_salaries(salary_schedule_1021_alt2p1_analyzed)
salary_schedule_1021_alt3_adj <- adjust_salaries(salary_schedule_1021_alt3_analyzed)
salary_schedule_1021_alt4_adj <- adjust_salaries(salary_schedule_1021_alt4_analyzed)

# Display all adjusted dataframes with headers
cat("\n=== Initial 1021 Proposal (w/4% Increase) ===\n")

=== Initial 1021 Proposal (w/4% Increase) ===
Show the code
display_salary_schedule(salary_schedule_1021_2023_24_adj)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.68 20.66 21.69 22.78 23.92 5 5 5 5 NA NA NA NA NA
30 20.17 21.17 22.24 23.35 24.51 5 5 5 5 2.5 2.5 2.5 2.5 2.5
31 20.68 21.70 22.80 23.93 25.13 5 5 5 5 2.5 2.5 2.5 2.5 2.5
32 21.18 22.25 23.36 24.53 25.76 5 5 5 5 2.5 2.5 2.5 2.5 2.5
33 21.72 22.81 23.94 25.15 26.40 5 5 5 5 2.5 2.5 2.5 2.5 2.5
34 22.27 23.38 24.54 25.77 27.06 5 5 5 5 2.5 2.5 2.5 2.5 2.5
35 22.82 23.96 25.16 26.42 27.74 5 5 5 5 2.5 2.5 2.5 2.5 2.5
36 23.39 24.55 25.79 27.07 28.43 5 5 5 5 2.5 2.5 2.5 2.5 2.5
37 23.97 25.17 26.44 27.76 29.14 5 5 5 5 2.5 2.5 2.5 2.5 2.5
38 24.58 25.80 27.09 28.44 29.87 5 5 5 5 2.5 2.5 2.5 2.5 2.5
39 25.19 26.45 27.77 29.16 30.62 5 5 5 5 2.5 2.5 2.5 2.5 2.5
40 25.81 27.11 28.46 29.89 31.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
41 26.47 27.79 29.17 30.64 32.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
42 27.12 28.49 29.90 31.40 32.97 5 5 5 5 2.5 2.5 2.5 2.5 2.5
43 27.80 29.19 30.65 32.19 33.79 5 5 5 5 2.5 2.5 2.5 2.5 2.5
44 28.50 29.92 31.42 32.99 34.64 5 5 5 5 2.5 2.5 2.5 2.5 2.5
45 29.21 30.67 32.21 33.81 35.51 5 5 5 5 2.5 2.5 2.5 2.5 2.5
46 29.94 31.44 33.01 34.66 36.39 5 5 5 5 2.5 2.5 2.5 2.5 2.5
47 30.69 32.22 33.83 35.53 37.30 5 5 5 5 2.5 2.5 2.5 2.5 2.5
48 31.46 33.03 34.68 36.41 38.23 5 5 5 5 2.5 2.5 2.5 2.5 2.5
49 32.24 33.85 35.55 37.33 39.19 5 5 5 5 2.5 2.5 2.5 2.5 2.5
50 33.05 34.70 36.43 38.26 40.18 5 5 5 5 2.5 2.5 2.5 2.5 2.5
51 33.87 35.57 37.35 39.22 41.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
52 34.73 36.46 38.28 40.20 42.20 5 5 5 5 2.5 2.5 2.5 2.5 2.5
53 35.59 37.37 39.24 41.20 43.26 5 5 5 5 2.5 2.5 2.5 2.5 2.5
54 36.48 38.30 40.22 42.23 44.35 5 5 5 5 2.5 2.5 2.5 2.5 2.5
55 37.39 39.26 41.23 43.28 45.45 5 5 5 5 2.5 2.5 2.5 2.5 2.5
56 38.32 40.24 42.26 44.37 46.58 5 5 5 5 2.5 2.5 2.5 2.5 2.5
57 39.28 41.25 43.32 45.48 47.75 5 5 5 5 2.5 2.5 2.5 2.5 2.5
58 40.27 42.28 44.40 46.61 48.94 5 5 5 5 2.5 2.5 2.5 2.5 2.5
59 41.28 43.34 45.50 47.78 50.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
60 42.31 44.42 46.64 48.97 51.42 5 5 5 5 2.5 2.5 2.5 2.5 2.5
61 43.37 45.53 47.81 50.20 52.71 5 5 5 5 2.5 2.5 2.5 2.5 2.5
62 44.45 46.66 49.00 51.45 54.03 5 5 5 5 2.5 2.5 2.5 2.5 2.5
63 45.56 47.84 50.23 52.74 55.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
64 46.70 49.04 51.48 54.06 56.76 5 5 5 5 2.5 2.5 2.5 2.5 2.5
65 47.86 50.25 52.77 55.41 58.18 5 5 5 5 2.5 2.5 2.5 2.5 2.5
66 49.06 51.51 54.09 56.79 59.63 5 5 5 5 2.5 2.5 2.5 2.5 2.5
67 50.28 52.80 55.44 58.22 61.12 5 5 5 5 2.5 2.5 2.5 2.5 2.5
68 51.54 54.12 56.83 59.66 62.65 5 5 5 5 2.5 2.5 2.5 2.5 2.5
69 52.83 55.47 58.25 61.16 64.22 5 5 5 5 2.5 2.5 2.5 2.5 2.5
70 54.15 56.87 59.71 62.69 65.82 5 5 5 5 2.5 2.5 2.5 2.5 2.5
71 55.50 58.28 61.19 64.26 67.48 5 5 5 5 2.5 2.5 2.5 2.5 2.5
72 56.90 59.74 62.73 65.86 69.16 5 5 5 5 2.5 2.5 2.5 2.5 2.5
73 58.32 61.24 64.29 67.51 70.89 5 5 5 5 2.5 2.5 2.5 2.5 2.5
74 59.78 62.76 65.90 69.20 72.65 5 5 5 5 2.5 2.5 2.5 2.5 2.5
75 61.27 64.33 67.55 70.93 74.47 5 5 5 5 2.5 2.5 2.5 2.5 2.5
76 62.81 65.95 69.24 72.71 76.34 5 5 5 5 2.5 2.5 2.5 2.5 2.5
77 64.38 67.59 70.97 74.52 78.25 5 5 5 5 2.5 2.5 2.5 2.5 2.5
78 65.98 69.28 72.75 76.38 80.20 5 5 5 5 2.5 2.5 2.5 2.5 2.5
79 67.63 71.01 74.57 78.29 82.20 5 5 5 5 2.5 2.5 2.5 2.5 2.5
80 69.33 72.79 76.43 80.25 84.26 5 5 5 5 2.5 2.5 2.5 2.5 2.5
81 71.05 74.61 78.34 82.25 86.37 5 5 5 5 2.5 2.5 2.5 2.5 2.5
82 72.83 76.47 80.30 84.31 88.52 5 5 5 5 2.5 2.5 2.5 2.5 2.5
83 74.65 78.38 82.31 86.42 90.74 5 5 5 5 2.5 2.5 2.5 2.5 2.5
84 76.52 80.34 84.36 88.58 93.01 5 5 5 5 2.5 2.5 2.5 2.5 2.5
85 78.43 82.36 86.48 90.79 95.34 5 5 5 5 2.5 2.5 2.5 2.5 2.5
86 80.39 84.42 88.63 93.06 97.72 5 5 5 5 2.5 2.5 2.5 2.5 2.5
87 82.40 86.52 90.84 95.39 100.16 5 5 5 5 2.5 2.5 2.5 2.5 2.5
88 84.46 88.68 93.12 97.77 102.67 5 5 5 5 2.5 2.5 2.5 2.5 2.5
Show the code
cat("\n=== Alternative 1 (w/4% Increase) ===\n")

=== Alternative 1 (w/4% Increase) ===
Show the code
display_salary_schedule(salary_schedule_1021_alt1_adj)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.68 20.56 21.49 22.45 23.46 4.5 4.5 4.5 4.5 NA NA NA NA NA
30 20.07 20.98 21.91 22.90 23.93 4.5 4.5 4.5 4.5 2 2 2 2 2
31 20.47 21.39 22.36 23.36 24.41 4.5 4.5 4.5 4.5 2 2 2 2 2
32 20.88 21.82 22.81 23.83 24.90 4.5 4.5 4.5 4.5 2 2 2 2 2
33 21.30 22.26 23.25 24.30 25.40 4.5 4.5 4.5 4.5 2 2 2 2 2
34 21.73 22.70 23.72 24.79 25.91 4.5 4.5 4.5 4.5 2 2 2 2 2
35 22.16 23.16 24.20 25.28 26.43 4.5 4.5 4.5 4.5 2 2 2 2 2
36 22.60 23.62 24.68 25.79 26.96 4.5 4.5 4.5 4.5 2 2 2 2 2
37 23.06 24.10 25.18 26.31 27.50 4.5 4.5 4.5 4.5 2 2 2 2 2
38 23.51 24.58 25.68 26.83 28.04 4.5 4.5 4.5 4.5 2 2 2 2 2
39 23.98 25.06 26.20 27.37 28.60 4.5 4.5 4.5 4.5 2 2 2 2 2
40 24.46 25.56 26.72 27.92 29.17 4.5 4.5 4.5 4.5 2 2 2 2 2
41 24.96 26.07 27.25 28.48 29.75 4.5 4.5 4.5 4.5 2 2 2 2 2
42 25.46 26.60 27.80 29.05 30.36 4.5 4.5 4.5 4.5 2 2 2 2 2
43 25.96 27.13 28.35 29.63 30.96 4.5 4.5 4.5 4.5 2 2 2 2 2
44 26.48 27.67 28.92 30.22 31.58 4.5 4.5 4.5 4.5 2 2 2 2 2
45 27.01 28.23 29.49 30.83 32.21 4.5 4.5 4.5 4.5 2 2 2 2 2
46 27.55 28.79 30.09 31.44 32.85 4.5 4.5 4.5 4.5 2 2 2 2 2
47 28.10 29.37 30.69 32.07 33.51 4.5 4.5 4.5 4.5 2 2 2 2 2
48 28.66 29.95 31.30 32.71 34.18 4.5 4.5 4.5 4.5 2 2 2 2 2
49 29.23 30.56 31.93 33.36 34.87 4.5 4.5 4.5 4.5 2 2 2 2 2
50 29.83 31.17 32.57 34.03 35.57 4.5 4.5 4.5 4.5 2 2 2 2 2
51 30.42 31.79 33.22 34.72 36.28 4.5 4.5 4.5 4.5 2 2 2 2 2
52 31.02 32.43 33.88 35.41 37.00 4.5 4.5 4.5 4.5 2 2 2 2 2
53 31.65 33.07 34.56 36.12 37.74 4.5 4.5 4.5 4.5 2 2 2 2 2
54 32.28 33.74 35.26 36.84 38.50 4.5 4.5 4.5 4.5 2 2 2 2 2
55 32.93 34.41 35.95 37.58 39.27 4.5 4.5 4.5 4.5 2 2 2 2 2
56 33.58 35.10 36.68 38.32 40.05 4.5 4.5 4.5 4.5 2 2 2 2 2
57 34.26 35.80 37.41 39.09 40.85 4.5 4.5 4.5 4.5 2 2 2 2 2
58 34.94 36.51 38.16 39.87 41.67 4.5 4.5 4.5 4.5 2 2 2 2 2
59 35.64 37.24 38.92 40.67 42.50 4.5 4.5 4.5 4.5 2 2 2 2 2
60 36.36 37.99 39.70 41.49 43.36 4.5 4.5 4.5 4.5 2 2 2 2 2
61 37.09 38.75 40.50 42.32 44.22 4.5 4.5 4.5 4.5 2 2 2 2 2
62 37.82 39.53 41.31 43.16 45.10 4.5 4.5 4.5 4.5 2 2 2 2 2
63 38.58 40.32 42.13 44.02 46.01 4.5 4.5 4.5 4.5 2 2 2 2 2
64 39.35 41.12 42.97 44.91 46.92 4.5 4.5 4.5 4.5 2 2 2 2 2
65 40.13 41.94 43.84 45.80 47.86 4.5 4.5 4.5 4.5 2 2 2 2 2
66 40.94 42.79 44.71 46.72 48.83 4.5 4.5 4.5 4.5 2 2 2 2 2
67 41.76 43.64 45.60 47.65 49.80 4.5 4.5 4.5 4.5 2 2 2 2 2
68 42.60 44.51 46.52 48.61 50.79 4.5 4.5 4.5 4.5 2 2 2 2 2
69 43.45 45.41 47.44 49.58 51.81 4.5 4.5 4.5 4.5 2 2 2 2 2
70 44.31 46.31 48.39 50.58 52.85 4.5 4.5 4.5 4.5 2 2 2 2 2
71 45.20 47.24 49.36 51.58 53.90 4.5 4.5 4.5 4.5 2 2 2 2 2
72 46.10 48.18 50.35 52.61 54.98 4.5 4.5 4.5 4.5 2 2 2 2 2
73 47.03 49.14 51.36 53.66 56.09 4.5 4.5 4.5 4.5 2 2 2 2 2
74 47.96 50.13 52.38 54.75 57.20 4.5 4.5 4.5 4.5 2 2 2 2 2
75 48.93 51.13 53.44 55.84 58.34 4.5 4.5 4.5 4.5 2 2 2 2 2
76 49.91 52.16 54.50 56.95 59.52 4.5 4.5 4.5 4.5 2 2 2 2 2
77 50.91 53.20 55.59 58.09 60.70 4.5 4.5 4.5 4.5 2 2 2 2 2
78 51.93 54.26 56.70 59.25 61.92 4.5 4.5 4.5 4.5 2 2 2 2 2
79 52.96 55.35 57.83 60.43 63.16 4.5 4.5 4.5 4.5 2 2 2 2 2
80 54.02 56.45 58.99 61.65 64.42 4.5 4.5 4.5 4.5 2 2 2 2 2
81 55.10 57.58 60.17 62.88 65.71 4.5 4.5 4.5 4.5 2 2 2 2 2
82 56.20 58.73 61.38 64.14 67.03 4.5 4.5 4.5 4.5 2 2 2 2 2
83 57.32 59.90 62.61 65.42 68.36 4.5 4.5 4.5 4.5 2 2 2 2 2
84 58.48 61.11 63.86 66.73 69.73 4.5 4.5 4.5 4.5 2 2 2 2 2
85 59.64 62.33 65.14 68.07 71.13 4.5 4.5 4.5 4.5 2 2 2 2 2
86 60.84 63.58 66.44 69.42 72.55 4.5 4.5 4.5 4.5 2 2 2 2 2
87 62.06 64.84 67.77 70.81 74.00 4.5 4.5 4.5 4.5 2 2 2 2 2
88 63.29 66.14 69.12 72.23 75.48 4.5 4.5 4.5 4.5 2 2 2 2 2
Show the code
cat("\n=== Alternative 2 (w/4% Increase) ===\n")

=== Alternative 2 (w/4% Increase) ===
Show the code
display_salary_schedule(salary_schedule_1021_alt2_adj)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.68 20.51 21.38 22.30 23.24 4.2 4.3 4.3 4.2 NA NA NA NA NA
30 20.07 20.92 21.81 22.74 23.70 4.2 4.2 4.3 4.2 2 2 2 2 2
31 20.47 21.34 22.25 23.19 24.18 4.3 4.2 4.3 4.3 2 2 2 2 2
32 20.88 21.77 22.69 23.66 24.67 4.2 4.3 4.3 4.3 2 2 2 2 2
33 21.30 22.20 23.15 24.13 25.16 4.2 4.3 4.2 4.3 2 2 2 2 2
34 21.73 22.65 23.61 24.62 25.66 4.3 4.2 4.3 4.2 2 2 2 2 2
35 22.16 23.10 24.09 25.11 26.18 4.2 4.3 4.2 4.3 2 2 2 2 2
36 22.60 23.57 24.56 25.60 26.70 4.3 4.2 4.2 4.3 2 2 2 2 2
37 23.06 24.03 25.05 26.12 27.23 4.2 4.2 4.3 4.2 2 2 2 2 2
38 23.51 24.51 25.55 26.64 27.78 4.2 4.2 4.3 4.3 2 2 2 2 2
39 23.98 25.00 26.07 27.18 28.33 4.2 4.3 4.2 4.2 2 2 2 2 2
40 24.46 25.50 26.59 27.72 28.90 4.3 4.3 4.2 4.3 2 2 2 2 2
41 24.96 26.01 27.12 28.28 29.47 4.2 4.3 4.3 4.2 2 2 2 2 2
42 25.46 26.54 27.66 28.84 30.07 4.2 4.2 4.2 4.3 2 2 2 2 2
43 25.96 27.07 28.22 29.41 30.67 4.3 4.2 4.2 4.3 2 2 2 2 2
44 26.48 27.61 28.78 30.00 31.28 4.3 4.2 4.3 4.3 2 2 2 2 2
45 27.01 28.16 29.36 30.61 31.91 4.3 4.2 4.3 4.2 2 2 2 2 2
46 27.55 28.72 29.94 31.22 32.54 4.3 4.2 4.3 4.2 2 2 2 2 2
47 28.10 29.30 30.54 31.84 33.20 4.3 4.3 4.3 4.2 2 2 2 2 2
48 28.66 29.88 31.16 32.48 33.86 4.2 4.3 4.2 4.3 2 2 2 2 2
49 29.23 30.48 31.77 33.12 34.54 4.3 4.2 4.3 4.3 2 2 2 2 2
50 29.83 31.10 32.42 33.79 35.22 4.3 4.2 4.2 4.2 2 2 2 2 2
51 30.42 31.71 33.06 34.47 35.93 4.2 4.3 4.2 4.3 2 2 2 2 2
52 31.02 32.34 33.72 35.15 36.65 4.3 4.2 4.3 4.3 2 2 2 2 2
53 31.65 32.99 34.39 35.86 37.38 4.2 4.3 4.3 4.2 2 2 2 2 2
54 32.28 33.65 35.08 36.58 38.13 4.3 4.2 4.3 4.2 2 2 2 2 2
55 32.93 34.33 35.79 37.30 38.90 4.3 4.2 4.2 4.3 2 2 2 2 2
56 33.58 35.02 36.50 38.05 39.67 4.3 4.2 4.2 4.2 2 2 2 2 2
57 34.26 35.71 37.23 38.81 40.47 4.3 4.3 4.2 4.3 2 2 2 2 2
58 34.94 36.43 37.98 39.59 41.28 4.3 4.3 4.2 4.3 2 2 2 2 2
59 35.64 37.16 38.74 40.38 42.10 4.3 4.3 4.2 4.2 2 2 2 2 2
60 36.36 37.90 39.51 41.19 42.94 4.2 4.3 4.3 4.2 2 2 2 2 2
61 37.09 38.66 40.30 42.02 43.79 4.2 4.3 4.3 4.2 2 2 2 2 2
62 37.82 39.43 41.11 42.86 44.68 4.2 4.3 4.2 4.2 2 2 2 2 2
63 38.58 40.22 41.93 43.71 45.57 4.2 4.3 4.2 4.3 2 2 2 2 2
64 39.35 41.03 42.76 44.58 46.48 4.3 4.2 4.3 4.2 2 2 2 2 2
65 40.13 41.84 43.62 45.48 47.41 4.2 4.3 4.3 4.3 2 2 2 2 2
66 40.94 42.68 44.49 46.38 48.36 4.2 4.2 4.3 4.3 2 2 2 2 2
67 41.76 43.53 45.39 47.31 49.33 4.3 4.3 4.2 4.3 2 2 2 2 2
68 42.60 44.41 46.29 48.26 50.32 4.2 4.2 4.2 4.3 2 2 2 2 2
69 43.45 45.29 47.22 49.22 51.31 4.2 4.2 4.3 4.2 2 2 2 2 2
70 44.31 46.20 48.16 50.21 52.34 4.2 4.3 4.3 4.2 2 2 2 2 2
71 45.20 47.12 49.13 51.21 53.39 4.3 4.3 4.2 4.3 2 2 2 2 2
72 46.10 48.07 50.11 52.24 54.45 4.3 4.2 4.3 4.2 2 2 2 2 2
73 47.03 49.03 51.12 53.28 55.55 4.2 4.3 4.2 4.3 2 2 2 2 2
74 47.96 50.00 52.14 54.35 56.66 4.2 4.3 4.2 4.2 2 2 2 2 2
75 48.93 51.01 53.18 55.43 57.79 4.3 4.2 4.2 4.3 2 2 2 2 2
76 49.91 52.03 54.24 56.54 58.95 4.3 4.2 4.3 4.2 2 2 2 2 2
77 50.91 53.07 55.33 57.68 60.12 4.2 4.3 4.2 4.2 2 2 2 2 2
78 51.93 54.13 56.43 58.83 61.33 4.2 4.2 4.3 4.2 2 2 2 2 2
79 52.96 55.21 57.56 60.01 62.56 4.3 4.3 4.2 4.2 2 2 2 2 2
80 54.02 56.32 58.71 61.20 63.80 4.3 4.2 4.3 4.2 2 2 2 2 2
81 55.10 57.44 59.88 62.43 65.08 4.2 4.3 4.3 4.2 2 2 2 2 2
82 56.20 58.59 61.08 63.68 66.38 4.3 4.2 4.3 4.2 2 2 2 2 2
83 57.32 59.77 62.31 64.95 67.71 4.3 4.2 4.2 4.3 2 2 2 2 2
84 58.48 60.95 63.55 66.25 69.07 4.2 4.3 4.2 4.3 2 2 2 2 2
85 59.64 62.18 64.82 67.58 70.45 4.3 4.2 4.3 4.2 2 2 2 2 2
86 60.84 63.42 66.11 68.93 71.85 4.2 4.2 4.3 4.2 2 2 2 2 2
87 62.06 64.69 67.44 70.30 73.30 4.2 4.3 4.2 4.3 2 2 2 2 2
88 63.29 65.99 68.79 71.71 74.76 4.3 4.2 4.2 4.2 2 2 2 2 2
Show the code
cat("\n=== Alternative 2.1 (w/4% Increase) ===\n")

=== Alternative 2.1 (w/4% Increase) ===
Show the code
display_salary_schedule(salary_schedule_1021_alt2p1_adj)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.68 20.46 21.28 22.13 23.02 4 4 4 4 NA NA NA NA NA
30 20.07 20.87 21.71 22.58 23.48 4 4 4 4 2 2 2 2 2
31 20.47 21.29 22.14 23.03 23.95 4 4 4 4 2 2 2 2 2
32 20.88 21.72 22.59 23.49 24.43 4 4 4 4 2 2 2 2 2
33 21.30 22.15 23.04 23.96 24.92 4 4 4 4 2 2 2 2 2
34 21.72 22.59 23.50 24.44 25.41 4 4 4 4 2 2 2 2 2
35 22.16 23.05 23.97 24.93 25.92 4 4 4 4 2 2 2 2 2
36 22.60 23.51 24.45 25.42 26.44 4 4 4 4 2 2 2 2 2
37 23.05 23.98 24.94 25.93 26.97 4 4 4 4 2 2 2 2 2
38 23.52 24.46 25.43 26.45 27.51 4 4 4 4 2 2 2 2 2
39 23.99 24.95 25.94 26.98 28.06 4 4 4 4 2 2 2 2 2
40 24.47 25.44 26.46 27.52 28.62 4 4 4 4 2 2 2 2 2
41 24.95 25.95 26.99 28.07 29.19 4 4 4 4 2 2 2 2 2
42 25.45 26.47 27.53 28.63 29.78 4 4 4 4 2 2 2 2 2
43 25.96 27.00 28.08 29.20 30.37 4 4 4 4 2 2 2 2 2
44 26.48 27.54 28.64 29.79 30.98 4 4 4 4 2 2 2 2 2
45 27.01 28.09 29.22 30.38 31.60 4 4 4 4 2 2 2 2 2
46 27.55 28.65 29.80 30.99 32.23 4 4 4 4 2 2 2 2 2
47 28.10 29.23 30.40 31.61 32.88 4 4 4 4 2 2 2 2 2
48 28.67 29.81 31.00 32.24 33.53 4 4 4 4 2 2 2 2 2
49 29.24 30.41 31.62 32.89 34.21 4 4 4 4 2 2 2 2 2
50 29.82 31.02 32.26 33.55 34.89 4 4 4 4 2 2 2 2 2
51 30.42 31.64 32.90 34.22 35.59 4 4 4 4 2 2 2 2 2
52 31.03 32.27 33.56 34.90 36.30 4 4 4 4 2 2 2 2 2
53 31.65 32.91 34.23 35.60 37.02 4 4 4 4 2 2 2 2 2
54 32.28 33.57 34.92 36.31 37.77 4 4 4 4 2 2 2 2 2
55 32.93 34.24 35.61 37.04 38.52 4 4 4 4 2 2 2 2 2
56 33.59 34.93 36.33 37.78 39.29 4 4 4 4 2 2 2 2 2
57 34.26 35.63 37.05 38.54 40.08 4 4 4 4 2 2 2 2 2
58 34.94 36.34 37.79 39.31 40.88 4 4 4 4 2 2 2 2 2
59 35.64 37.07 38.55 40.09 41.70 4 4 4 4 2 2 2 2 2
60 36.35 37.81 39.32 40.89 42.53 4 4 4 4 2 2 2 2 2
61 37.08 38.56 40.11 41.71 43.38 4 4 4 4 2 2 2 2 2
62 37.82 39.34 40.91 42.55 44.25 4 4 4 4 2 2 2 2 2
63 38.58 40.12 41.73 43.40 45.13 4 4 4 4 2 2 2 2 2
64 39.35 40.93 42.56 44.27 46.04 4 4 4 4 2 2 2 2 2
65 40.14 41.74 43.41 45.15 46.96 4 4 4 4 2 2 2 2 2
66 40.94 42.58 44.28 46.05 47.90 4 4 4 4 2 2 2 2 2
67 41.76 43.43 45.17 46.97 48.85 4 4 4 4 2 2 2 2 2
68 42.60 44.30 46.07 47.91 49.83 4 4 4 4 2 2 2 2 2
69 43.45 45.19 46.99 48.87 50.83 4 4 4 4 2 2 2 2 2
70 44.32 46.09 47.93 49.85 51.84 4 4 4 4 2 2 2 2 2
71 45.20 47.01 48.89 50.85 52.88 4 4 4 4 2 2 2 2 2
72 46.11 47.95 49.87 51.86 53.94 4 4 4 4 2 2 2 2 2
73 47.03 48.91 50.87 52.90 55.02 4 4 4 4 2 2 2 2 2
74 47.97 49.89 51.88 53.96 56.12 4 4 4 4 2 2 2 2 2
75 48.93 50.89 52.92 55.04 57.24 4 4 4 4 2 2 2 2 2
76 49.91 51.90 53.98 56.14 58.38 4 4 4 4 2 2 2 2 2
77 50.91 52.94 55.06 57.26 59.55 4 4 4 4 2 2 2 2 2
78 51.92 54.00 56.16 58.41 60.74 4 4 4 4 2 2 2 2 2
79 52.96 55.08 57.28 59.57 61.96 4 4 4 4 2 2 2 2 2
80 54.02 56.18 58.43 60.77 63.20 4 4 4 4 2 2 2 2 2
81 55.10 57.31 59.60 61.98 64.46 4 4 4 4 2 2 2 2 2
82 56.20 58.45 60.79 63.22 65.75 4 4 4 4 2 2 2 2 2
83 57.33 59.62 62.01 64.49 67.07 4 4 4 4 2 2 2 2 2
84 58.47 60.81 63.25 65.78 68.41 4 4 4 4 2 2 2 2 2
85 59.64 62.03 64.51 67.09 69.77 4 4 4 4 2 2 2 2 2
86 60.84 63.27 65.80 68.43 71.17 4 4 4 4 2 2 2 2 2
87 62.05 64.54 67.12 69.80 72.59 4 4 4 4 2 2 2 2 2
88 63.29 65.83 68.46 71.20 74.05 4 4 4 4 2 2 2 2 2
Show the code
cat("\n=== Alternative 3 (w/4% Increase) ===\n")

=== Alternative 3 (w/4% Increase) ===
Show the code
display_salary_schedule(salary_schedule_1021_alt3_adj)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.68 20.66 21.69 22.78 23.92 5 5 5 5 NA NA NA NA NA
30 20.17 21.17 22.24 23.35 24.51 5 5 5 5 2.5 2.5 2.5 2.5 2.5
31 20.68 21.70 22.80 23.93 25.13 5 5 5 5 2.5 2.5 2.5 2.5 2.5
32 21.18 22.25 23.36 24.53 25.76 5 5 5 5 2.5 2.5 2.5 2.5 2.5
33 21.72 22.81 23.94 25.15 26.40 5 5 5 5 2.5 2.5 2.5 2.5 2.5
34 22.27 23.38 24.54 25.77 27.06 5 5 5 5 2.5 2.5 2.5 2.5 2.5
35 22.82 23.96 25.16 26.42 27.74 5 5 5 5 2.5 2.5 2.5 2.5 2.5
36 23.39 24.55 25.79 27.07 28.43 5 5 5 5 2.5 2.5 2.5 2.5 2.5
37 23.97 25.17 26.44 27.76 29.14 5 5 5 5 2.5 2.5 2.5 2.5 2.5
38 24.58 25.80 27.09 28.44 29.87 5 5 5 5 2.5 2.5 2.5 2.5 2.5
39 25.19 26.45 27.77 29.16 30.62 5 5 5 5 2.5 2.5 2.5 2.5 2.5
40 25.81 27.11 28.46 29.89 31.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
41 26.47 27.79 29.17 30.64 32.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
42 27.12 28.49 29.90 31.40 32.97 5 5 5 5 2.5 2.5 2.5 2.5 2.5
43 27.80 29.19 30.65 32.19 33.79 5 5 5 5 2.5 2.5 2.5 2.5 2.5
44 28.50 29.92 31.42 32.99 34.64 5 5 5 5 2.5 2.5 2.5 2.5 2.5
45 29.21 30.67 32.21 33.81 35.51 5 5 5 5 2.5 2.5 2.5 2.5 2.5
46 29.94 31.44 33.01 34.66 36.39 5 5 5 5 2.5 2.5 2.5 2.5 2.5
47 30.69 32.22 33.83 35.53 37.30 5 5 5 5 2.5 2.5 2.5 2.5 2.5
48 31.30 32.86 34.51 36.23 38.05 5 5 5 5 2 2 2 2 2
49 31.93 33.53 35.20 36.96 38.81 5 5 5 5 2 2 2 2 2
50 32.56 34.20 35.90 37.70 39.58 5 5 5 5 2 2 2 2 2
51 33.22 34.88 36.63 38.46 40.37 5 5 5 5 2 2 2 2 2
52 33.88 35.58 37.36 39.23 41.18 5 5 5 5 2 2 2 2 2
53 34.56 36.29 38.11 40.01 42.01 5 5 5 5 2 2 2 2 2
54 35.26 37.01 38.86 40.81 42.85 5 5 5 5 2 2 2 2 2
55 35.95 37.75 39.64 41.62 43.71 5 5 5 5 2 2 2 2 2
56 36.68 38.51 40.44 42.45 44.58 5 5 5 5 2 2 2 2 2
57 37.41 39.28 41.25 43.31 45.47 5 5 5 5 2 2 2 2 2
58 38.16 40.06 42.07 44.17 46.38 5 5 5 5 2 2 2 2 2
59 38.92 40.87 42.91 45.05 47.31 5 5 5 5 2 2 2 2 2
60 39.70 41.68 43.77 45.96 48.26 5 5 5 5 2 2 2 2 2
61 40.50 42.52 44.65 46.87 49.22 5 5 5 5 2 2 2 2 2
62 41.30 43.37 45.54 47.81 50.20 5 5 5 5 2 2 2 2 2
63 42.13 44.23 46.45 48.77 51.21 5 5 5 5 2 2 2 2 2
64 42.97 45.13 47.37 49.74 52.23 5 5 5 5 2 2 2 2 2
65 43.84 46.02 48.33 50.74 53.28 5 5 5 5 2 2 2 2 2
66 44.71 46.95 49.30 51.75 54.34 5 5 5 5 2 2 2 2 2
67 45.60 47.88 50.27 52.79 55.43 5 5 5 5 2 2 2 2 2
68 46.52 48.84 51.28 53.85 56.53 5 5 5 5 2 2 2 2 2
69 47.44 49.82 52.31 54.92 57.67 5 5 5 5 2 2 2 2 2
70 48.39 50.81 53.35 56.02 58.82 5 5 5 5 2 2 2 2 2
71 49.36 51.83 54.42 57.14 60.00 5 5 5 5 2 2 2 2 2
72 50.35 52.86 55.50 58.28 61.20 5 5 5 5 2 2 2 2 2
73 51.36 53.92 56.62 59.45 62.42 5 5 5 5 2 2 2 2 2
74 52.38 55.01 57.75 60.64 63.67 5 5 5 5 2 2 2 2 2
75 53.44 56.10 58.91 61.85 64.95 5 5 5 5 2 2 2 2 2
76 54.50 57.22 60.08 63.09 66.25 5 5 5 5 2 2 2 2 2
77 55.59 58.36 61.29 64.36 67.57 5 5 5 5 2 2 2 2 2
78 56.70 59.54 62.51 65.63 68.92 5 5 5 5 2 2 2 2 2
79 57.83 60.73 63.76 66.96 70.29 5 5 5 5 2 2 2 2 2
80 58.99 61.94 65.04 68.29 71.71 5 5 5 5 2 2 2 2 2
81 60.17 63.18 66.34 69.66 73.14 5 5 5 5 2 2 2 2 2
82 61.37 64.44 67.66 71.05 74.60 5 5 5 5 2 2 2 2 2
83 62.60 65.73 69.01 72.47 76.10 5 5 5 5 2 2 2 2 2
84 63.86 67.05 70.40 73.92 77.62 5 5 5 5 2 2 2 2 2
85 65.14 68.39 71.81 75.40 79.16 5 5 5 5 2 2 2 2 2
86 66.44 69.75 73.25 76.91 80.76 5 5 5 5 2 2 2 2 2
87 67.77 71.15 74.71 78.45 82.37 5 5 5 5 2 2 2 2 2
88 69.12 72.57 76.20 80.02 84.01 5 5 5 5 2 2 2 2 2
Show the code
cat("\n=== Alternative 4 (w/4% Increase) ===\n")

=== Alternative 4 (w/4% Increase) ===
Show the code
display_salary_schedule(salary_schedule_1021_alt4_adj)
Range Step1 Step2 Step3 Step4 Step5 S2% S3% S4% S5% R1% R2% R3% R4% R5%
29 19.68 20.66 21.69 22.78 23.92 5 5 5 5 NA NA NA NA NA
30 20.17 21.17 22.24 23.35 24.51 5 5 5 5 2.5 2.5 2.5 2.5 2.5
31 20.68 21.70 22.80 23.93 25.13 5 5 5 5 2.5 2.5 2.5 2.5 2.5
32 21.18 22.25 23.36 24.53 25.76 5 5 5 5 2.5 2.5 2.5 2.5 2.5
33 21.72 22.81 23.94 25.15 26.40 5 5 5 5 2.5 2.5 2.5 2.5 2.5
34 22.27 23.38 24.54 25.77 27.06 5 5 5 5 2.5 2.5 2.5 2.5 2.5
35 22.82 23.96 25.16 26.42 27.74 5 5 5 5 2.5 2.5 2.5 2.5 2.5
36 23.39 24.55 25.79 27.07 28.43 5 5 5 5 2.5 2.5 2.5 2.5 2.5
37 23.97 25.17 26.44 27.76 29.14 5 5 5 5 2.5 2.5 2.5 2.5 2.5
38 24.58 25.80 27.09 28.44 29.87 5 5 5 5 2.5 2.5 2.5 2.5 2.5
39 25.19 26.45 27.77 29.16 30.62 5 5 5 5 2.5 2.5 2.5 2.5 2.5
40 25.81 27.11 28.46 29.89 31.38 5 5 5 5 2.5 2.5 2.5 2.5 2.5
41 26.47 27.79 29.17 30.64 32.17 5 5 5 5 2.5 2.5 2.5 2.5 2.5
42 27.12 28.49 29.90 31.40 32.97 5 5 5 5 2.5 2.5 2.5 2.5 2.5
43 27.80 29.19 30.65 32.19 33.79 5 5 5 5 2.5 2.5 2.5 2.5 2.5
44 28.50 29.92 31.42 32.99 34.64 5 5 5 5 2.5 2.5 2.5 2.5 2.5
45 29.21 30.67 32.21 33.81 35.51 5 5 5 5 2.5 2.5 2.5 2.5 2.5
46 29.94 31.44 33.01 34.66 36.39 5 5 5 5 2.5 2.5 2.5 2.5 2.5
47 30.69 32.22 33.83 35.53 37.30 5 5 5 5 2.5 2.5 2.5 2.5 2.5
48 31.30 32.86 34.51 36.23 38.05 5 5 5 5 2 2 2 2 2
49 31.93 33.53 35.20 36.96 38.81 5 5 5 5 2 2 2 2 2
50 32.56 34.20 35.90 37.70 39.58 5 5 5 5 2 2 2 2 2
51 33.22 34.88 36.63 38.46 40.37 5 5 5 5 2 2 2 2 2
52 33.88 35.58 37.36 39.23 41.18 5 5 5 5 2 2 2 2 2
53 34.56 36.29 38.11 40.01 42.01 5 5 5 5 2 2 2 2 2
54 35.26 37.01 38.86 40.81 42.85 5 5 5 5 2 2 2 2 2
55 35.95 37.75 39.64 41.62 43.71 5 5 5 5 2 2 2 2 2
56 36.68 38.51 40.44 42.45 44.58 5 5 5 5 2 2 2 2 2
57 37.41 39.28 41.25 43.31 45.47 5 5 5 5 2 2 2 2 2
58 38.16 40.06 42.07 44.17 46.38 5 5 5 5 2 2 2 2 2
59 38.92 40.87 42.91 45.05 47.31 5 5 5 5 2 2 2 2 2
60 39.70 41.68 43.77 45.96 48.26 5 5 5 5 2 2 2 2 2
61 40.50 42.52 44.65 46.87 49.22 5 5 5 5 2 2 2 2 2
62 41.30 43.37 45.54 47.81 50.20 5 5 5 5 2 2 2 2 2
63 42.13 44.23 46.45 48.77 51.21 5 5 5 5 2 2 2 2 2
64 42.97 45.13 47.37 49.74 52.23 5 5 5 5 2 2 2 2 2
65 43.84 46.02 48.33 50.74 53.28 5 5 5 5 2 2 2 2 2
66 44.71 46.95 49.30 51.75 54.34 5 5 5 5 2 2 2 2 2
67 45.60 47.88 50.27 52.79 55.43 5 5 5 5 2 2 2 2 2
68 46.52 48.84 51.28 53.85 56.53 5 5 5 5 2 2 2 2 2
69 47.44 49.82 52.31 54.92 57.67 5 5 5 5 2 2 2 2 2
70 48.39 50.81 53.35 56.02 58.82 5 5 5 5 2 2 2 2 2
71 49.36 51.83 54.42 57.14 60.00 5 5 5 5 2 2 2 2 2
72 50.35 52.86 55.50 58.28 61.20 5 5 5 5 2 2 2 2 2
73 51.36 53.92 56.62 59.45 62.42 5 5 5 5 2 2 2 2 2
74 52.38 55.01 57.75 60.64 63.67 5 5 5 5 2 2 2 2 2
75 53.44 56.10 58.91 61.85 64.95 5 5 5 5 2 2 2 2 2
76 54.50 57.22 60.08 63.09 66.25 5 5 5 5 2 2 2 2 2
77 55.59 58.36 61.29 64.36 67.57 5 5 5 5 2 2 2 2 2
78 56.70 59.54 62.51 65.63 68.92 5 5 5 5 2 2 2 2 2
79 57.83 60.73 63.76 66.96 70.29 5 5 5 5 2 2 2 2 2
80 58.70 61.64 64.72 67.95 71.35 5 5 5 5 1.5 1.5 1.5 1.5 1.5
81 59.58 62.57 65.69 68.97 72.43 5 5 5 5 1.5 1.5 1.5 1.5 1.5
82 60.48 63.50 66.67 70.01 73.51 5 5 5 5 1.5 1.5 1.5 1.5 1.5
83 61.38 64.45 67.67 71.06 74.61 5 5 5 5 1.5 1.5 1.5 1.5 1.5
84 62.31 65.42 68.69 72.12 75.73 5 5 5 5 1.5 1.5 1.5 1.5 1.5
85 63.24 66.40 69.72 73.21 76.87 5 5 5 5 1.5 1.5 1.5 1.5 1.5
86 64.19 67.39 70.77 74.31 78.02 5 5 5 5 1.5 1.5 1.5 1.5 1.5
87 65.15 68.41 71.83 75.42 79.20 5 5 5 5 1.5 1.5 1.5 1.5 1.5
88 66.12 69.43 72.90 76.55 80.38 5 5 5 5 1.5 1.5 1.5 1.5 1.5