1  Employment and average wages

1.1 NC employment by sector

In the state-level data for 2021 the CBP reported 3,903,814 workers in 20 NAICS categories, which are summarized in Section 1.6.

Show the code
data_for_plot <- d_emp_sector_total_state_nc |>
  filter(year == 2021) |>
  mutate(naics_abbr = fct_reorder(naics_abbr, emp)) 

nc_naics_abbr_levels = levels(data_for_plot$naics_abbr)

data_for_plot |>
  ggplot() +
  geom_col(aes(x = emp, y = naics_abbr),
           fill = carolina_blue, alpha = 0.6) +
  scale_x_continuous(labels = label_number(scale_cut = cut_short_scale())) +
  labs(
    title = "NC state employment by sector 2021",
    subtitle = "Includes all 100 counties and 'Statewide'",
    x = "Employees",
    y = "",
    color = NULL,
    caption = my_caption
  )

This bar plot lists employment sectors on the Y axis with counts of the number of employees in North Carolina in each in 2021. This information is available in table form in the last sction of this page.

Figure 1.1: NC state employment by sector 2021


The employment distribution across the sectors in NC and the USA overall is similar:

Show the code
data_for_plot <- bind_rows(
  d_emp_sector_total_state_nc |>
    filter(year == 2021) |>
    mutate(scope = "nc"),
  d_emp_sector_total_usa |>
    filter(year == 2021) |>
    mutate(scope = "usa")
) |>
  select(naics, naics_abbr, emp, pct_emp, scope) |>
  mutate(naics_abbr = factor(naics_abbr, levels = nc_naics_abbr_levels)) |>
  mutate(low_value = min(pct_emp),
         high_value = max(pct_emp),
         .by = naics_abbr) |>
  mutate(diff_pct = high_value - low_value,
         diff_pct = if_else(pct_emp == high_value, diff_pct, -1 * diff_pct)) 

diff_pct_cutoff <- 0.005

data_for_plot |>
  ggplot() +
  geom_segment(aes(x = low_value, xend = high_value, y = naics_abbr, yend = naics_abbr),
               alpha = 0.3) +
  geom_point(aes(x = pct_emp, y = naics_abbr, color = scope),
           alpha = 0.6) + 
  geom_point(aes(x = pct_emp, y = naics_abbr, color = scope),
           alpha = 0.6) + 
  geom_text(aes(x = high_value, y = naics_abbr,
                label = if_else(diff_pct > diff_pct_cutoff,
                                percent(pct_emp, accuracy = .1),
                                NA_character_)),
            na.rm = TRUE, size = 3,
            hjust = 0, nudge_x = 0.003) +
  geom_text(aes(x = low_value, y = naics_abbr,
                label = if_else(diff_pct < -1 * diff_pct_cutoff,
                                percent(pct_emp, accuracy = .1),
                                NA_character_)),
            na.rm = TRUE, size = 3,
            hjust = 1, nudge_x = -0.003) +
  scale_x_continuous(labels = label_percent()) +
  scale_color_manual(values = c(carolina_blue, "firebrick")) +
  theme(legend.position = c(0.8, 0.4),
        legend.box.background = element_rect(fill = "grey80")) +
  labs(
    title = "NC state employment by sector\ncompared to USA 2021",
    subtitle = glue("Includes all 100 counties and 'Statewide'", 
                    "; showing percentages where difference is > {percent(diff_pct_cutoff, accuracy = 0.1)}"),
    x = "Employees",
    y = "",
    color = NULL,
    caption = my_caption
  )

This plot lists employment sectors on the Y axis with points indicating the percent of the employment in North Carolina and all 50 states. The percentages are similar for both.

Figure 1.2: NC employment by sector compared to USA 2021


The CBP state data includes employee counts categorized by employee size class. The range is embedded in the name. For example, e1_4 includes a count of employees working in establishments with 1-4 employees. Let’s assume that the average number of workers in each employment size class is about the midpoint of the class, and for e1000 (“1000 or more employees) that the midpoint is 2000.

Then we can answer the question: from the perspective of workers, what are the most common employer size classes? Or asking another way: if one randomly selected a NC worker what is the probability the person would work in an establishment of a particular size class?

Show the code
data_for_plot <- d_emp_state_nc_total_size_classes |>
  filter(year == 2021) |>
  inner_join(n_employees_ref |>
               select(-est_size_class),
             by = "emp_size_class")

p1 <- data_for_plot |>
  mutate(emp_size_class = fct_reorder(emp_size_class, factor_order)) |>
  ggplot() +
  geom_col(aes(x = pct_emp, y = emp_size_class),
           fill = carolina_blue, alpha = 0.6) +
  scale_x_continuous(labels = label_percent()) +
  scale_y_discrete(limits=rev) +
  labs(
    x = "Percent of employees",
    y = "Employee size class",
    color = NULL,
  )

p2 <- data_for_plot |>
  mutate(emp_size_class = fct_reorder(emp_size_class, pct_emp)) |>
  arrange(desc(emp_size_class)) |>
  mutate(cum_pct_emp = cumsum(pct_emp),
         ybar_start = lag(cum_pct_emp, default = 0)) |>
  ggplot() +
  geom_segment(aes(x = emp_size_class, xend = emp_size_class, y = ybar_start, yend = cum_pct_emp),
           color = carolina_blue, linewidth = 8, alpha = 0.6) + 
  scale_y_continuous(labels = label_percent()) +
  scale_x_discrete(limits=rev) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    x = "Employee size class",
    y = "Percent of employees",
    color = NULL,
  )

p1 + p2 +
  plot_annotation(
    title = "Percent of NC employees working for establishments\nin each employee size class",
    subtitle = "2021; includes all sectors reported in CBP",
    caption = my_caption,
    #theme = theme(plot.title = element_text(size = 16))
  )

This bar chart lists employee size classes on the Y axis with percentage of employees in North Carolina in each in 2021. Size classes range from '1 to 4' up to '1000 or more'.

Figure 1.3: NC workers in each employee size class 2021


Further categorizing this data by industry sector reveals which industries have concentrations of workers in establishments of particular size classes. Employees in AccFood mostly work in establishments in the 10 to 100 employee range. In Retail there is a wider range: from very small to 499 employees and almost none larger. The industry sectors with the largest portion of employees working for the largest establishments are HeathSoc (hospital systems, I assume) and FinIns. Construction and ProfSciTech have the largest portion of employees in the sector working in 1-4 employee establishments.

Show the code
data_for_plot <- d_emp_state_nc_size_classes |>
  filter(year == 2021) |>
  inner_join(n_employees_ref |>
               select(-est_size_class),
             by = "emp_size_class") |>
  mutate(emp_size_class = factor(emp_size_class, levels = emp_size_class_levels),
         naics_abbr = fct_lump(naics_abbr, n = 9, w = emp)) 

p1 <- data_for_plot |>
  ggplot() +
  geom_col(aes(x = pct_emp, y = emp_size_class, fill = naics_abbr),
           alpha = 0.6, show.legend = FALSE) +
  scale_x_continuous(labels = label_percent(accuracy = 1)) +
  scale_y_discrete(limits=rev) +
  labs(
    x = "Percent of employees",
    y = "Employee size class",
    color = NULL
  )

p2 <- data_for_plot |>
  ggplot() +
  geom_col(aes(x = pct_emp, y = emp_size_class, fill = naics_abbr),
           alpha = 0.6, position = position_fill()) +
  scale_x_continuous(labels = label_percent(accuracy = 1)) +
  scale_y_discrete(limits=rev) +
  labs(
    x = "Distibution of size classes",
    y = NULL,
    color = NULL
  )

p3 <- data_for_plot |>
  mutate(naics_abbr = fct_reorder(naics_abbr, emp, sum)) |>
  ggplot() +
  geom_col(aes(x = pct_emp, y = naics_abbr, fill = emp_size_class),
           alpha = 0.6, show.legend = FALSE) +
  scale_x_continuous(labels = label_percent(accuracy = 1)) +
  scale_fill_viridis_d(end = 0.85) +
  labs(
    x = "Percent of employees",
    y = NULL,
    color = NULL
  )

p4 <- data_for_plot |>
  mutate(naics_abbr = fct_reorder(naics_abbr, emp, sum)) |> 
  ggplot() +
  geom_col(aes(x = pct_emp, y = naics_abbr, fill = emp_size_class),
           alpha = 0.6, position = position_fill()) +
  scale_x_continuous(labels = label_percent(accuracy = 1)) +
  scale_fill_viridis_d(end = 0.85) +
  labs(
    x = "Distribution of NAICS categories",
    y = NULL,
    color = NULL
  )

(p1 + p2) / (p3 + p4) +
  plot_annotation(
    title = "Percent of NC workers in each employee size class by sector",
    subtitle = "2021; includes all sectors reported in CBP",
    caption = my_caption
  )

This bar chart lists employee size classes on the Y axis with percentage of employees in North Carolina colored by industry sector. Data is for each in 2021. A second plot shows the same data spread out to show the distribution of industry sectors among the size classes. Two more plots provide similar information but with industry sectors on the Y axis.

Figure 1.4: Percent of NC workers in each employee size class by sector 2021


1.2 Top sectors in largest NC counties

Are there similarities in the top sectors and their proportions in the counties with the most workers? Yes. HealthSoc, Retail, and AccFood are among the top four sectors in each of the top nine counties and the “Statewide” category. There are some differences: Mecklenburg’s top sector is FinIns, Durham’s is ProfSciTec, and Catawba’s is Manuf.

Show the code
county_name_label <- d_emp_sector_total_county |> #d_sector_totals_county |>
  filter(year == 2021) |>
  select(year, fipscty, emp, county_name, naics) |>
  summarize(emp_sum = sum(emp),
            .by = county_name) |>
  slice_max(order_by = emp_sum, n = 10) |>
  mutate(county_name_label = glue("{county_name}\n{comma(emp_sum)}"),
         county_name_label = fct_reorder(county_name_label, -emp_sum))

data_for_plot <- d_nc_2021_top5_sectors_county_nc |>
  select(county_name, emp, naics, naics_descr, emp_rank) |>
  left_join(d_naics_abbr_ref,
             by = c("naics_descr")) |>
  left_join(county_name_label,
             by = c("county_name")) |>
  mutate(pct_emp = emp / emp_sum,
         county_name_label = fct_reorder(county_name_label, -emp, sum)) |>
  complete(county_name_label, naics_abbr, fill = list(emp = NA, pct_emp = NA)) 

data_for_plot |> 
  ggplot() +
  geom_line(aes(x = county_name_label, y = pct_emp, group = naics_abbr, color = naics_abbr),
            show.legend = FALSE, na.rm = TRUE) +
  geom_label(aes(x = county_name_label, y = pct_emp, label = naics_abbr, fill = naics_abbr),
             show.legend = FALSE, na.rm = TRUE, alpha = 0.4, size = data_label_size) +
  scale_x_discrete(position = "top") +
  scale_y_continuous(labels = label_percent()) +
  coord_cartesian(ylim = c(NA, 0.30)) +
  theme(axis.text.x = element_text(size = 10)) +
  labs(
    title = "Top 5 sectors in 10 largest NC counties:\npercent of county employment",
    subtitle = glue("Ordered by total county employment reported in CBP",
                    "; 'Statewide' refers to employees not associated with one county",
                    "\nNot showing Statewide AdminWaste, since it's over 50% of all 'Statewide' employees"),
    x = "",
    y = "Percent of county employment",
    color = NULL,
    caption = my_caption
  )

This plot shows the top 5 sectors for the 10 largest counties by employment in North Carolina, from the largest (Mecklenburg) to the tenth-largest (Catawba). Lines connect the same industry sector in adjacent columns. The Y axis is the percent of county employment.

Figure 1.5: Sector percent of country emplyment rank


The same information is presented below with simple ranking:

Show the code
data_for_plot |>
  ggplot() +
  geom_line(aes(x = county_name_label, y = emp_rank, group = naics_abbr, color = naics_abbr),
            show.legend = FALSE, na.rm = TRUE) +
  geom_label(aes(x = county_name_label, y = emp_rank, label = naics_abbr, fill = naics_abbr),
             show.legend = FALSE, na.rm = TRUE, alpha = 0.4, size = data_label_size) +
  scale_x_discrete(position = "top") +
  scale_y_reverse() +
  theme(axis.text.x = element_text(size = 10)) +
  labs(
    title = "Top 5 sectors in 10 largest NC counties: ranking",
    subtitle = glue("Ordered by total county employment reported in CBP",
                    "; 'Statewide' refers to workers not associated with one county"),
    x = "",
    y = "Rank in county employment",
    color = NULL,
    caption = my_caption
  )

Like the prior plot, this plot shows the top 5 sectors for the 10 largest counties by employment in North Carolina, from the largest (Mecklenburg) to the tenth-largest (Catawba). Lines connect the same industry sector in adaject columns. The difference is that Y axis is a simple ranking 1 to 5 of percent county employment.

Figure 1.6: Sector rank by number of employees


1.6 Tables

Below are the sector summary categories used in the CBP. To simplify plotting, I created some abbreviations:

Show the code
d_naics_abbr_ref |>
  arrange(naics_abbr_num) |>
  select(naics_abbr, naics_descr) |>
  mutate(rowid = row_number()) |>
  gt() |>
  tab_header(md(glue("**NAICS categories and abbreviations used in this analysis**"))) |>
  tab_source_note(md("*US Census County Business Patterns; analysis by Daniel Moul*")) |>
  tab_options(table.font.size = 10)
Table 1.1: NAICS sector categories and abbreviations
NAICS categories and abbreviations used in this analysis
naics_abbr naics_descr rowid
TotalAllSec Total for all sectors 1
AccFood Accommodation and food services 2
AdminWaste Administrative and support and waste management and remediation services 3
AgForFish Agriculture, forestry, fishing and hunting 4
ArtEntRec Arts, entertainment, and recreation 5
Constr Construction 6
Educ Educational services 7
FinIns Finance and insurance 8
HealthSoc Health care and social assistance 9
Info Information 10
Manuf Manufacturing 11
MineOilGas Mining, quarrying, and oil and gas extraction 12
Mgmt Management of companies and enterprises 13
ProfSciTec Professional, scientific, and technical services 14
RealEst Real estate and rental and leasing 15
Retail Retail trade 16
Transpt Transportation and warehousing 17
Util Utilities 18
Whlsale Wholesale trade 19
OtherServ Other services (except public administration) 20
OtherInd Industries not classified 21
US Census County Business Patterns; analysis by Daniel Moul


Sectors sorted by number of employees:

Show the code
d_emp_sector_total_state_nc |>
  filter(year == 2021) |>
  filter(naics_abbr != "OtherInd") |>
  select(naics, naics_abbr, naics_descr, emp_2021 = emp, pct_emp_2021 = pct_emp) |>
  arrange(-emp_2021) |>
  mutate(rowid = row_number()) |>
  relocate(naics_descr, .after = naics) |>
  gt() |>
  tab_header(md(glue("**NC sector employment 2021**",
                     "<br>*Sorted by sector employment*"))) |>
  tab_source_note(md("*US Census County Business Patterns; analysis by Daniel Moul*")) |>
  tab_options(table.font.size = 10) |>
  fmt_number(columns = c(emp_2021), #, avg_wage
             decimals = 0) |>
  fmt_percent(columns = pct_emp_2021, 
             decimals = 0)
Table 1.2: NC state employment by sector 2021
NC sector employment 2021
Sorted by sector employment
naics naics_descr naics_abbr emp_2021 pct_emp_2021 rowid
62---- Health care and social assistance HealthSoc 625,672 16% 1
44---- Retail trade Retail 512,706 13% 2
31---- Manufacturing Manuf 451,487 12% 3
72---- Accommodation and food services AccFood 402,561 10% 4
56---- Administrative and support and waste management and remediation services AdminWaste 290,845 7% 5
54---- Professional, scientific, and technical services ProfSciTec 245,485 6% 6
23---- Construction Constr 228,752 6% 7
52---- Finance and insurance FinIns 212,324 5% 8
42---- Wholesale trade Whlsale 191,495 5% 9
48---- Transportation and warehousing Transpt 159,091 4% 10
81---- Other services (except public administration) OtherServ 156,834 4% 11
55---- Management of companies and enterprises Mgmt 99,410 3% 12
61---- Educational services Educ 98,677 3% 13
51---- Information Info 86,053 2% 14
53---- Real estate and rental and leasing RealEst 58,890 2% 15
71---- Arts, entertainment, and recreation ArtEntRec 54,515 1% 16
22---- Utilities Util 20,391 1% 17
11---- Agriculture, forestry, fishing and hunting AgForFish 4,714 0% 18
21---- Mining, quarrying, and oil and gas extraction MineOilGas 3,464 0% 19
US Census County Business Patterns; analysis by Daniel Moul


Sorted by percent difference from 2001 to 2021

Show the code
d_emp_sector_total_state_nc |>
  filter(naics_abbr != "OtherInd") |>
  mutate(naics_abbr = fct_reorder(naics_abbr, -emp)
         ) |>
  mutate(emp_fist_year = emp[year == min(year)],
         emp_last_year = emp[year == max(year)],
         .by = c("naics")) |>
  mutate(pct_emp_diff = emp_last_year / emp_fist_year - 1) |>
  filter(year == 2021) |>
  select(naics, naics_abbr, emp_2021 = emp, pct_emp_2021 = pct_emp, pct_emp_diff_since_2001 = pct_emp_diff) |>
  arrange(-pct_emp_diff_since_2001) |>
  mutate(rowid = row_number()) |>
  gt() |>
  tab_header(md(glue("**NC sector employment in 2021 and growth since 2001**",
                     "<br>*Sorted by growth since 2001*"))) |>
  tab_source_note(md("*US Census County Business Patterns; analysis by Daniel Moul*")) |>
  tab_options(table.font.size = 10) |>
  fmt_number(columns = c(emp_2021),
             decimals = 0) |>
  fmt_percent(columns = c(pct_emp_2021, pct_emp_diff_since_2001),
             decimals = 0)
Table 1.3: NC state employment growth by sector 2001-2021
NC sector employment in 2021 and growth since 2001
Sorted by growth since 2001
naics naics_abbr emp_2021 pct_emp_2021 pct_emp_diff_since_2001 rowid
48---- Transpt 159,091 4% 59% 1
54---- ProfSciTec 245,485 6% 55% 2
62---- HealthSoc 625,672 16% 52% 3
61---- Educ 98,677 3% 46% 4
72---- AccFood 402,561 10% 43% 5
56---- AdminWaste 290,845 7% 24% 6
71---- ArtEntRec 54,515 1% 24% 7
55---- Mgmt 99,410 3% 23% 8
53---- RealEst 58,890 2% 21% 9
44---- Retail 512,706 13% 16% 10
52---- FinIns 212,324 5% 14% 11
42---- Whlsale 191,495 5% 11% 12
51---- Info 86,053 2% 8% 13
22---- Util 20,391 1% 8% 14
81---- OtherServ 156,834 4% 6% 15
23---- Constr 228,752 6% 1% 16
21---- MineOilGas 3,464 0% −1% 17
11---- AgForFish 4,714 0% −23% 18
31---- Manuf 451,487 12% −35% 19
US Census County Business Patterns; analysis by Daniel Moul

Sorted by average wage:

Show the code
d_emp_sector_total_state_nc |>
  filter(year == 2021) |>
  select(naics, naics_abbr, avg_wage_2021 = avg_wage, emp_2021 = emp, pct_emp_2021 = pct_emp) |>
  arrange(-avg_wage_2021) |>
  mutate(rowid = row_number()) |>
  gt() |>
  tab_header(md(glue("**NC sector employment 2021**",
                     "<br>*Sorted by sector average wage*"))) |>
  tab_source_note(md("*US Census County Business Patterns; analysis by Daniel Moul*")) |>
  tab_options(table.font.size = 10) |>
  fmt_number(columns = c(emp_2021, avg_wage_2021),
             decimals = 0) |>
  fmt_percent(columns = pct_emp_2021, 
             decimals = 0)
Table 1.4: NC state average wage by sector 2021
NC sector employment 2021
Sorted by sector average wage
naics naics_abbr avg_wage_2021 emp_2021 pct_emp_2021 rowid
52---- FinIns 114,024 212,324 5% 1
51---- Info 112,154 86,053 2% 2
22---- Util 108,108 20,391 1% 3
55---- Mgmt 104,025 99,410 3% 4
54---- ProfSciTec 90,430 245,485 6% 5
42---- Whlsale 82,657 191,495 5% 6
21---- MineOilGas 73,410 3,464 0% 7
23---- Constr 59,089 228,752 6% 8
53---- RealEst 58,796 58,890 2% 9
31---- Manuf 58,104 451,487 12% 10
62---- HealthSoc 56,471 625,672 16% 11
61---- Educ 49,027 98,677 3% 12
48---- Transpt 48,231 159,091 4% 13
11---- AgForFish 45,136 4,714 0% 14
56---- AdminWaste 42,286 290,845 7% 15
71---- ArtEntRec 40,880 54,515 1% 16
81---- OtherServ 34,543 156,834 4% 17
44---- Retail 30,474 512,706 13% 18
99---- OtherInd 25,248 448 0% 19
72---- AccFood 20,614 402,561 10% 20
US Census County Business Patterns; analysis by Daniel Moul


Show the code
d_emp_sector_total_state_nc |>
  inner_join(d_infation_adj,
             by = "year") |>
  mutate(avg_wage_adjusted = avg_wage * adj) |>
  mutate(wage_fist_year = avg_wage_adjusted[year == min(year)],
         wage_last_year = avg_wage_adjusted[year == max(year)],
         .by = c("naics")) |>
  mutate(wage_diff = wage_last_year - wage_fist_year,
         pct_wage_diff = wage_last_year / wage_fist_year - 1) |>
  filter(year == 2021) |>
  select(naics, naics_abbr, avg_wage_2021 = wage_last_year, pct_avg_wage_diff_since_2001 = pct_wage_diff, 
         emp_2021 = emp, pct_emp_2021 = pct_emp) |>
  arrange(-pct_avg_wage_diff_since_2001) |>
  mutate(rowid = row_number()) |>
  gt() |>
  tab_header(md(glue("**NC sector average wage 2021 and difference since 2001**",
                     "<br>*Sorted by average wage difference*"))) |>
  tab_source_note(md("*US Census County Business Patterns; analysis by Daniel Moul*")) |>
  tab_options(table.font.size = 10) |>
  fmt_number(columns = c(avg_wage_2021, emp_2021),
             decimals = 0) |>
  fmt_percent(columns = c(pct_avg_wage_diff_since_2001, pct_emp_2021), 
             decimals = 0)
Table 1.5: NC state average wage growth by sector 2001-2021
NC sector average wage 2021 and difference since 2001
Sorted by average wage difference
naics naics_abbr avg_wage_2021 pct_avg_wage_diff_since_2001 emp_2021 pct_emp_2021 rowid
51---- Info 112,154 68% 86,053 2% 1
52---- FinIns 114,024 67% 212,324 5% 2
56---- AdminWaste 42,286 33% 290,845 7% 3
54---- ProfSciTec 90,430 32% 245,485 6% 4
42---- Whlsale 82,657 29% 191,495 5% 5
53---- RealEst 58,796 28% 58,890 2% 6
23---- Constr 59,089 26% 228,752 6% 7
11---- AgForFish 45,136 25% 4,714 0% 8
21---- MineOilGas 73,410 22% 3,464 0% 9
31---- Manuf 58,104 22% 451,487 12% 10
61---- Educ 49,027 21% 98,677 3% 11
72---- AccFood 20,614 20% 402,561 10% 12
81---- OtherServ 34,543 20% 156,834 4% 13
22---- Util 108,108 17% 20,391 1% 14
62---- HealthSoc 56,471 17% 625,672 16% 15
71---- ArtEntRec 40,880 9% 54,515 1% 16
55---- Mgmt 104,025 7% 99,410 3% 17
44---- Retail 30,474 0% 512,706 13% 18
48---- Transpt 48,231 −6% 159,091 4% 19
99---- OtherInd 25,248 −20% 448 0% 20
US Census County Business Patterns; analysis by Daniel Moul