Project 2 Data Tidying: BLS Unemployment

Author

Zaina Hassan

Published

October 7, 2026

Approach

Dataset :BLS State Unemployment

For this dataset, I will use state unemployment data from the U.S. Bureau of Labor Statistics. The original table reports unemployment rates for states across multiple time periods in separate columns, making it appropriate for a wide to long transformation. I will preserve the selected BLS table in its original wide structure as a CSV before performing any transformations. Using tidyr and dplyr, I will reshape the unemployment columns into a long format in which each row represents the unemployment rate for one state during one time period. The resulting dataset will contain variables such as state, period, and unemployment rate. I will standardize column names, convert values to appropriate data types, and investigate any missing or inconsistent observations. Using the tidy dataset, I will compare unemployment rates between the available periods and examine how unemployment changed across states. I plan to identify states with the largest increases and decreases, calculate summary statistics for unemployment rates, and compare individual states with the overall distribution. Visualizations will be used to display differences between states and changes over time.

Data Source

The data for this analysis comes from the U.S. Bureau of Labor Statistics (BLS) State Employment and Unemployment release. The dataset contains civilian labor force totals, numbers of unemployed individuals, and unemployment rates for U.S. states and selected areas across January 2025, November 2025, December 2025, and January 2026.

The original table was saved as unemployment_raw.csv and committed to GitHub before any transformations were performed.

Load Packages and Import Raw Data

Code
library(tidyverse)

unemployment_raw <- read.csv("unemployment_raw.csv")

head(unemployment_raw)
       State Labor_Force_Jan_2025 Labor_Force_Nov_2025 Labor_Force_Dec_2025
1    Alabama              2378428              2387873              2387810
2     Alaska               363404               367709               367671
3    Arizona              3781221              3815687              3814917
4   Arkansas              1424605              1448832              1448666
5 California             19764218             19878800             19878043
6   Colorado              3273054              3254030              3254073
  Labor_Force_Jan_2026 Unemployed_Number_Jan_2025 Unemployed_Number_Nov_2025
1              2387649                      72543                      64802
2               368663                      16527                      17537
3              3814207                     157097                     167615
4              1451310                      54116                      62349
5             19862185                    1061763                    1094082
6              3248844                     141216                     124951
  Unemployed_Number_Dec_2025 Unemployed_Number_Jan_2026
1                      64776                      64061
2                      17531                      17722
3                     167319                     171391
4                      62197                      63636
5                    1093176                    1082348
6                     125077                     126262
  Unemployment_Rate_Jan_2025 Unemployment_Rate_Nov_2025
1                        3.1                        2.7
2                        4.5                        4.8
3                        4.2                        4.4
4                        3.8                        4.3
5                        5.4                        5.5
6                        4.3                        3.8
  Unemployment_Rate_Dec_2025 Unemployment_Rate_Jan_2026
1                        2.7                        2.7
2                        4.8                        4.8
3                        4.4                        4.5
4                        4.3                        4.4
5                        5.5                        5.4
6                        3.8                        3.9
Code
str(unemployment_raw)
'data.frame':   52 obs. of  13 variables:
 $ State                     : chr  "Alabama" "Alaska" "Arizona" "Arkansas" ...
 $ Labor_Force_Jan_2025      : int  2378428 363404 3781221 1424605 19764218 3273054 1943229 513593 415267 11122059 ...
 $ Labor_Force_Nov_2025      : int  2387873 367709 3815687 1448832 19878800 3254030 1933758 517116 408918 11116493 ...
 $ Labor_Force_Dec_2025      : int  2387810 367671 3814917 1448666 19878043 3254073 1933851 517069 409140 11117284 ...
 $ Labor_Force_Jan_2026      : int  2387649 368663 3814207 1451310 19862185 3248844 1931321 516215 407967 11124027 ...
 $ Unemployed_Number_Jan_2025: int  72543 16527 157097 54116 1061763 141216 69987 21280 23759 392967 ...
 $ Unemployed_Number_Nov_2025: int  64802 17537 167615 62349 1094082 124951 83534 27606 27600 480808 ...
 $ Unemployed_Number_Dec_2025: int  64776 17531 167319 62197 1093176 125077 83387 27510 27529 479324 ...
 $ Unemployed_Number_Jan_2026: int  64061 17722 171391 63636 1082348 126262 86980 27923 27189 499181 ...
 $ Unemployment_Rate_Jan_2025: num  3.1 4.5 4.2 3.8 5.4 4.3 3.6 4.1 5.7 3.5 ...
 $ Unemployment_Rate_Nov_2025: num  2.7 4.8 4.4 4.3 5.5 3.8 4.3 5.3 6.7 4.3 ...
 $ Unemployment_Rate_Dec_2025: num  2.7 4.8 4.4 4.3 5.5 3.8 4.3 5.3 6.7 4.3 ...
 $ Unemployment_Rate_Jan_2026: num  2.7 4.8 4.5 4.4 5.4 3.9 4.5 5.4 6.7 4.5 ...

Data Structure Before Tidying

The original dataset is stored in wide format. Each geographic area occupies one row, while measurements for different time periods are stored in separate columns. For example, unemployment rates for January 2025, November 2025, December 2025, and January 2026 are represented by four different columns.

This structure stores both the type of measurement and the time period within column names. To create a tidy dataset, these components will be separated into individual variables so that each row represents one state, measurement, and time period.

Code
dim(unemployment_raw)
[1] 52 13
Code
names(unemployment_raw)
 [1] "State"                      "Labor_Force_Jan_2025"      
 [3] "Labor_Force_Nov_2025"       "Labor_Force_Dec_2025"      
 [5] "Labor_Force_Jan_2026"       "Unemployed_Number_Jan_2025"
 [7] "Unemployed_Number_Nov_2025" "Unemployed_Number_Dec_2025"
 [9] "Unemployed_Number_Jan_2026" "Unemployment_Rate_Jan_2025"
[11] "Unemployment_Rate_Nov_2025" "Unemployment_Rate_Dec_2025"
[13] "Unemployment_Rate_Jan_2026"
Code
head(unemployment_raw)
       State Labor_Force_Jan_2025 Labor_Force_Nov_2025 Labor_Force_Dec_2025
1    Alabama              2378428              2387873              2387810
2     Alaska               363404               367709               367671
3    Arizona              3781221              3815687              3814917
4   Arkansas              1424605              1448832              1448666
5 California             19764218             19878800             19878043
6   Colorado              3273054              3254030              3254073
  Labor_Force_Jan_2026 Unemployed_Number_Jan_2025 Unemployed_Number_Nov_2025
1              2387649                      72543                      64802
2               368663                      16527                      17537
3              3814207                     157097                     167615
4              1451310                      54116                      62349
5             19862185                    1061763                    1094082
6              3248844                     141216                     124951
  Unemployed_Number_Dec_2025 Unemployed_Number_Jan_2026
1                      64776                      64061
2                      17531                      17722
3                     167319                     171391
4                      62197                      63636
5                    1093176                    1082348
6                     125077                     126262
  Unemployment_Rate_Jan_2025 Unemployment_Rate_Nov_2025
1                        3.1                        2.7
2                        4.5                        4.8
3                        4.2                        4.4
4                        3.8                        4.3
5                        5.4                        5.5
6                        4.3                        3.8
  Unemployment_Rate_Dec_2025 Unemployment_Rate_Jan_2026
1                        2.7                        2.7
2                        4.8                        4.8
3                        4.4                        4.5
4                        4.3                        4.4
5                        5.5                        5.4
6                        3.8                        3.9

Transformation Steps

I use pivot_longer() to transform the repeated measurement columns into a long format. The original column names contain two pieces of information: the measurement being reported and the corresponding month and year. These components are separated into measure and period variables during the transformation.

The resulting dataset contains one observation for each geographic area, measurement type, and time period.

Code
unemployment_tidy <- unemployment_raw %>%
  pivot_longer(
    cols = -State,
    names_to = c("measure", "period"),
    names_pattern = "(.*)_(Jan_2025|Nov_2025|Dec_2025|Jan_2026)",
    values_to = "value"
  ) %>%
  mutate(
    measure = recode(
      measure,
      "Labor_Force" = "Labor Force",
      "Unemployed_Number" = "Unemployed Number",
      "Unemployment_Rate" = "Unemployment Rate"
    ),
    period = recode(
      period,
      "Jan_2025" = "January 2025",
      "Nov_2025" = "November 2025",
      "Dec_2025" = "December 2025",
      "Jan_2026" = "January 2026"
    )
  ) %>%
  rename(state = State)

head(unemployment_tidy, 12)
# A tibble: 12 × 4
   state   measure           period            value
   <chr>   <chr>             <chr>             <dbl>
 1 Alabama Labor Force       January 2025  2378428  
 2 Alabama Labor Force       November 2025 2387873  
 3 Alabama Labor Force       December 2025 2387810  
 4 Alabama Labor Force       January 2026  2387649  
 5 Alabama Unemployed Number January 2025    72543  
 6 Alabama Unemployed Number November 2025   64802  
 7 Alabama Unemployed Number December 2025   64776  
 8 Alabama Unemployed Number January 2026    64061  
 9 Alabama Unemployment Rate January 2025        3.1
10 Alabama Unemployment Rate November 2025       2.7
11 Alabama Unemployment Rate December 2025       2.7
12 Alabama Unemployment Rate January 2026        2.7
Code
dim(unemployment_tidy)
[1] 624   4
Code
str(unemployment_tidy)
tibble [624 × 4] (S3: tbl_df/tbl/data.frame)
 $ state  : chr [1:624] "Alabama" "Alabama" "Alabama" "Alabama" ...
 $ measure: chr [1:624] "Labor Force" "Labor Force" "Labor Force" "Labor Force" ...
 $ period : chr [1:624] "January 2025" "November 2025" "December 2025" "January 2026" ...
 $ value  : num [1:624] 2378428 2387873 2387810 2387649 72543 ...
Code
colSums(is.na(unemployment_tidy))
  state measure  period   value 
      0       0       0       0 

The missing value check returned zero missing values across all four variables, so no imputation or row removal was necessary.

Analytical Methods

The analysis uses only the tidy version of the dataset. I focus on unemployment rates to compare geographic areas across the four reported periods and examine how unemployment changed between January 2025 and January 2026.

I calculate summary statistics for each period and identify the geographic areas with the largest increases and decreases in unemployment rates over the one-year period. Visualizations are used to show both overall unemployment patterns and changes across geographic areas.

Unemployment Rates by Period

Code
unemployment_summary <- unemployment_tidy %>%
  filter(measure == "Unemployment Rate") %>%
  group_by(period) %>%
  summarise(
    `Mean Rate (%)` = round(mean(value), 2),
    `Median Rate (%)` = round(median(value), 2),
    `Minimum Rate (%)` = min(value),
    `Maximum Rate (%)` = max(value),
    .groups = "drop"
  )

knitr::kable(
  unemployment_summary,
  caption = "Summary of Unemployment Rates by Period"
)
Summary of Unemployment Rates by Period
period Mean Rate (%) Median Rate (%) Minimum Rate (%) Maximum Rate (%)
December 2025 4.10 4.20 2.2 6.7
January 2025 3.89 3.85 2.0 5.7
January 2026 4.13 4.30 2.2 6.7
November 2025 4.10 4.25 2.2 6.7

Change from January 2025 to January 2026

Code
rate_change <- unemployment_tidy %>%
  filter(
    measure == "Unemployment Rate",
    period %in% c("January 2025", "January 2026")
  ) %>%
  select(state, period, value) %>%
  pivot_wider(
    names_from = period,
    values_from = value
  ) %>%
  mutate(
    change = `January 2026` - `January 2025`
  ) %>%
  arrange(desc(change))

rate_change
# A tibble: 52 × 4
   state                `January 2025` `January 2026` change
   <chr>                         <dbl>          <dbl>  <dbl>
 1 Delaware                        4.1            5.4  1.3  
 2 Minnesota                       3.4            4.4  1    
 3 District of Columbia            5.7            6.7  1    
 4 Florida                         3.5            4.5  1    
 5 Connecticut                     3.6            4.5  0.9  
 6 South Carolina                  4.1            4.9  0.800
 7 Maryland                        3.5            4.3  0.8  
 8 Oklahoma                        3.1            3.9  0.8  
 9 West Virginia                   3.8            4.6  0.8  
10 Montana                         2.9            3.6  0.7  
# ℹ 42 more rows

Largest Changes in Unemployment Rates

Code
largest_changes <- bind_rows(
  rate_change %>%
    slice_max(change, n = 5, with_ties = FALSE),
  
  rate_change %>%
    slice_min(change, n = 5, with_ties = FALSE)
) %>%
  arrange(desc(change)) %>%
  rename(
    `Geographic Area` = state,
    `January 2025 Rate (%)` = `January 2025`,
    `January 2026 Rate (%)` = `January 2026`,
    `Change (Percentage Points)` = change
  )

knitr::kable(
  largest_changes,
  caption = "Largest Changes in Unemployment Rates, January 2025 to January 2026"
)
Largest Changes in Unemployment Rates, January 2025 to January 2026
Geographic Area January 2025 Rate (%) January 2026 Rate (%) Change (Percentage Points)
Delaware 4.1 5.4 1.3
Minnesota 3.4 4.4 1.0
District of Columbia 5.7 6.7 1.0
Florida 3.5 4.5 1.0
Connecticut 3.6 4.5 0.9
Alabama 3.1 2.7 -0.4
Colorado 4.3 3.9 -0.4
Indiana 3.9 3.4 -0.5
Kentucky 4.8 4.3 -0.5
Ohio 4.8 4.3 -0.5

Average Unemployment Rates Over Time

Code
unemployment_rates <- unemployment_tidy %>%
  filter(measure == "Unemployment Rate") %>%
  mutate(
    period = factor(
      period,
      levels = c(
        "January 2025",
        "November 2025",
        "December 2025",
        "January 2026"
      )
    )
  )

average_rates <- unemployment_rates %>%
  group_by(period) %>%
  summarise(
    average_rate = mean(value),
    .groups = "drop"
  )

ggplot(
  average_rates,
  aes(x = period, y = average_rate, group = 1)
) +
  geom_line(linewidth = 1) +
  geom_point(size = 3) +
  labs(
    title = "Average Unemployment Rate Across Geographic Areas",
    subtitle = "January 2025 to January 2026",
    x = "Period",
    y = "Average Unemployment Rate (%)"
  ) +
  theme_minimal()

Areas with Largest Changes

Code
ggplot(
  largest_changes,
  aes(
    x = reorder(`Geographic Area`, `Change (Percentage Points)`),
    y = `Change (Percentage Points)`,
    fill = `Change (Percentage Points)` > 0
  )
) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  scale_fill_manual(
    values = c("TRUE" = "coral", "FALSE" = "lightgreen")
  ) +
  labs(
    title = "Largest Changes in Unemployment Rates",
    subtitle = "January 2025 to January 2026",
    x = "Geographic Area",
    y = "Change in Unemployment Rate (Percentage Points)"
  ) +
  theme_minimal()

Results

The average unemployment rate across the 52 geographic areas increased from 3.89% in January 2025 to 4.13% in January 2026. The median increased from 3.85% to 4.30% over the same period. The maximum unemployment rate also increased from 5.7% to 6.7%, while the minimum increased from 2.0% to 2.2%.

The largest increase occurred in Delaware, where the unemployment rate rose from 4.1% to 5.4%, an increase of 1.3 percentage points. Minnesota, the District of Columbia, and Florida each increased by 1.0 percentage point, while Connecticut increased by 0.9 percentage points.

The largest decreases occurred in Indiana, Kentucky, and Ohio, where unemployment rates each fell by 0.5 percentage points. Alabama and Colorado each decreased by 0.4 percentage points. Overall, the results indicate that unemployment rates were somewhat higher across the included geographic areas in January 2026 than in January 2025, although the direction and magnitude of change varied considerably by location.

Conclusion

Transforming the BLS unemployment data from wide to long format separated the measurement type and reporting period that were originally embedded within the column names. The resulting tidy structure makes it possible to filter, group, summarize, and visualize labor-market measures consistently across geographic areas and time periods.

The analysis shows a modest overall increase in unemployment rates between January 2025 and January 2026. However, the changes were not uniform across geographic areas. Delaware experienced the largest increase, while Indiana, Kentucky, and Ohio experienced the largest decreases. This demonstrates how a tidy structure makes both overall trends and differences between individual geographic areas easier to identify.