Instructions

The Federal Reserve’s mandate from Congress is to control inflation and to maintain low unemployment. These seem to be contradictory objectives. For this story you will need to source the following data for the last 25 years; The Consumer Price Index (CPI) (Bureau of Labor Statistics) The FED Funds Rate (FRED) (Federal Reserve Board) Unemployment Rate (Bureau of Labor Statistics)

Your Data Visualizations should be designed to answer the question “Has the FED been able to fulfill the mandate given to it by Congress?”

Getting Started

Load R packages necessary for data manipulation, visualization, and API interaction and retrieve API key Source from https://www.bls.gov to access CPI and employment data.

library(blsAPI)
library(fredr)
library(httr)
library(jsonlite)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(devtools)
## Loading required package: usethis
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(stringr)
library(ggplot2)
install_github("mikeasilva/blsAPI")
## Skipping install of 'blsAPI' from a github remote, the SHA1 (a125b3a7) has not changed since last install.
##   Use `force = TRUE` to force installation
library(httr)
library(glue)

Import Consumer Price Index (CPI) data

Source from https://api.bls.gov

# Insert API key
api_key <- "4a2d974fa90e43f7a80ac58413209058"
series_id <- "CUUR0000SA0"

# API URL
url <- "https://api.bls.gov/publicAPI/v2/timeseries/data/"

# Payload Body
cpi_payload <- glue('{
  "seriesid" : ["CUUR0000SA0"],
    "startyear" : "1999",
    "endyear" : "2024",
    "registrationkey" : "{{api_key}}"
}', .open="{{", .close="}}")

# Post request
cpi_response <- httr::POST(url,
                       body = cpi_payload,
                       content_type("application/json"),
                       encode = "json")

# Convert JSON to list
cpi_x <- httr::content(cpi_response, "text") %>% jsonlite::fromJSON()
## No encoding supplied: defaulting to UTF-8.
# Extract data and create a tibble
cpi_data_tibble <- cpi_x$Results$series$data[[1]] %>% as_tibble()

# Remove the last column
cpi_data_tibble <- cpi_data_tibble[, -ncol(cpi_data_tibble)]


# Payload Body
cpi_payload1 <- glue('{
  "seriesid" : ["CUUR0000SA0"],
    "startyear" : "2019",
    "endyear" : "2024",
    "registrationkey" : "{{api_key}}"
}', .open="{{", .close="}}")

# Post request
cpi_response1 <- httr::POST(url,
                       body = cpi_payload1,
                       content_type("application/json"),
                       encode = "json")

# Convert JSON to list
cpi_x1 <- httr::content(cpi_response1, "text") %>% jsonlite::fromJSON()
## No encoding supplied: defaulting to UTF-8.
# Extract data and create a tibble
cpi_data_tibble1 <- cpi_x1$Results$series$data[[1]] %>% as_tibble()

# Remove unwanted variables in data frame
cpi_data_tibble1 <- cpi_data_tibble1[, -ncol(cpi_data_tibble1)]
cpi_data_tibble1 <- cpi_data_tibble1 %>% select(-latest)

# combine two data frames for 25 years
cpi_data <- bind_rows(cpi_data_tibble, cpi_data_tibble1)
cpi_data <- cpi_data %>% select(-periodName)
names(cpi_data)=c("Year","Month","CPI_value")

# View the resulting combined data frame
cpi_data$Year <- as.numeric(cpi_data$Year)
cpi_data$CPI_value <- as.numeric(cpi_data$CPI_value)
summary(cpi_data)
##       Year         Month             CPI_value    
##  Min.   :1999   Length:301         Min.   :164.3  
##  1st Qu.:2005   Class :character   1st Qu.:194.4  
##  Median :2011   Mode  :character   Median :225.9  
##  Mean   :2011                      Mean   :224.3  
##  3rd Qu.:2017                      3rd Qu.:246.7  
##  Max.   :2024                      Max.   :308.4

Access FED Funds Rate data

Source the data from https://fred.stlouisfed.org/

# Set a API key 
fredr_set_key("5b8e7823eb18f0816dba09f9293a4083")
# Specify the series ID for FED Funds Rate
series_id <- "FEDFUNDS"

# Get FED funds rate data for the last 25 years
fed_funds_data <-  fredr(
  series_id = "FEDFUNDS",
  observation_start = as.Date("1999-01-01"),
  observation_end = as.Date("2024-01-01"))

# Cleaning FED Funding data
fed_funds_data <- fed_funds_data %>% select(-series_id, -realtime_start, -realtime_end)
names(fed_funds_data)=c("Date","FED_value")
fed_funds_data$Year <- year(fed_funds_data$Date)
fed_funds_data$Month <- month(fed_funds_data$Date)
fed_funds_data <- fed_funds_data %>% select(-Date)

# Reorder columns by Year, Month, and FED_value
fed_funds_data <- fed_funds_data %>% select(Year, Month, FED_value)
# Assuming your data frame is named fed_funds_data
fed_funds_data$Month <- ifelse(fed_funds_data$Month < 10, sprintf("M%02d", fed_funds_data$Month), sprintf("M%d", fed_funds_data$Month))

# View the resulting data frame
summary(fed_funds_data)
##       Year         Month             FED_value    
##  Min.   :1999   Length:301         Min.   :0.050  
##  1st Qu.:2005   Class :character   1st Qu.:0.140  
##  Median :2011   Mode  :character   Median :1.220  
##  Mean   :2011                      Mean   :1.924  
##  3rd Qu.:2017                      3rd Qu.:3.620  
##  Max.   :2024                      Max.   :6.540

Retrieve Unemployment Data

Source from https://api.bls.gov

# Insert API key
api_key <- "4a2d974fa90e43f7a80ac58413209058"
series_id <- "LNU04000000"

# API URL
url <- "https://api.bls.gov/publicAPI/v2/timeseries/data/"

# Payload Body
payload <- glue('{
  "seriesid" : ["LNU04000000"],
    "startyear" : "1999",
    "endyear" : "2016",
    "registrationkey" : "{{api_key}}"
}', .open="{{", .close="}}")

# Post request
response <- httr::POST(url,
                       body = payload,
                       content_type("application/json"),
                       encode = "json")

# Convert JSON to list
x <- httr::content(response, "text") %>% jsonlite::fromJSON()
## No encoding supplied: defaulting to UTF-8.
# Extract data and create a tibble
data_tibble <- x$Results$series$data[[1]] %>% as_tibble()

# Remove the last column
data_tibble <- data_tibble[, -ncol(data_tibble)]

# Payload Body
payload1 <- glue('{
  "seriesid" : ["LNU04000000"],
    "startyear" : "2017",
    "endyear" : "2024",
    "registrationkey" : "{{api_key}}"
}', .open="{{", .close="}}")

# Post request
response1 <- httr::POST(url,
                       body = payload1,
                       content_type("application/json"),
                       encode = "json")

# Convert JSON to list
x1 <- httr::content(response1, "text") %>% jsonlite::fromJSON()
## No encoding supplied: defaulting to UTF-8.
# Extract data and create a tibble
data_tibble1 <- x1$Results$series$data[[1]] %>% as_tibble()

# Remove the last column
data_tibble1 <- data_tibble1[, -ncol(data_tibble1)]


# combine two data frames for 25 years
unemployment_data <- bind_rows(data_tibble, data_tibble1)
unemployment_data <- unemployment_data %>% select(-latest)


# View the combined data frame
unemployment_data <- unemployment_data %>% select(-periodName)
names(unemployment_data)=c("Year","Month","UNEMP_value")
unemployment_data$Year <- as.numeric(unemployment_data$Year)
unemployment_data$UNEMP_value <- as.numeric(unemployment_data$UNEMP_value)
head(unemployment_data)
## # A tibble: 6 × 3
##    Year Month UNEMP_value
##   <dbl> <chr>       <dbl>
## 1  2016 M12           4.5
## 2  2016 M11           4.4
## 3  2016 M10           4.7
## 4  2016 M09           4.8
## 5  2016 M08           5  
## 6  2016 M07           5.1

Plot Annual CPI vs Inflaction Rate

# Merge fed_funds_data and cpi_data based on Year and Month
merged_data <- merge(fed_funds_data, cpi_data, by = c("Year", "Month"))

# Merge the result with unemployment_data based on Year and Month
final_data <- merge(merged_data, unemployment_data, by = c("Year", "Month"))

# view merged data frame
head(final_data)
##   Year Month FED_value CPI_value UNEMP_value
## 1 1999   M01      4.63     164.3         4.8
## 2 1999   M02      4.76     164.5         4.7
## 3 1999   M03      4.81     165.0         4.4
## 4 1999   M04      4.74     166.2         4.1
## 5 1999   M05      4.74     166.2         4.0
## 6 1999   M06      4.76     166.2         4.5
# Plot annually values of CPI, FED Fund Rate and Unemployment Rate
ggplot(final_data, aes(x = Year)) +
  geom_line(aes(y = FED_value, color = "FED Funds Rate"), linewidth = 1) +
  geom_line(aes(y = CPI_value, color = "Consumer Price Index"), linewidth = 1) +
  geom_line(aes(y = UNEMP_value, color = "Unemployment Rate"), linewidth = 1) +
  labs(title = "Annual Unemployment Rate, Consumer Price Index, and FED Funds Rate",
       x = "Year",
       y = "Values") +
  scale_color_manual(values = c("FED Funds Rate" = "blue", 
                                "Consumer Price Index" = "green", 
                                "Unemployment Rate" = "red")) +
  theme_minimal()

These three lines graph shows clearly that annual values of Federal Funds Rate from 1997-2024 is pretty small amount compared to that of consumer price index and unemployment rate for past 25 years.

Then, the BLS uses the current year’s CPI and the prior year’s CPI to calculate the inflation rate. \[ \text { Inflation Rate }=\frac{\text { New CPI }- \text { Prior CPI }}{\text { Prior CPI }} \times 100 \]

The inflation rate can be calculated for a given month or annual period; in either case, the appropriate new and prior period must be selected. The inflation rate is reported as a percentage and is often positive (assuming current market prices are appreciating).

# Calculate Inflation Rate value and keep it in the last column of final_data 
final_data$InflationRate <- (final_data$CPI_value - lag(final_data$CPI_value)) / lag(final_data$CPI_value) * 100

# View the resulting data frame with the new InflationRate column
head(final_data)
##   Year Month FED_value CPI_value UNEMP_value InflationRate
## 1 1999   M01      4.63     164.3         4.8            NA
## 2 1999   M02      4.76     164.5         4.7     0.1217285
## 3 1999   M03      4.81     165.0         4.4     0.3039514
## 4 1999   M04      4.74     166.2         4.1     0.7272727
## 5 1999   M05      4.74     166.2         4.0     0.0000000
## 6 1999   M06      4.76     166.2         4.5     0.0000000
# To fill  NAs in column 'InflationRate' with the mean
mean_value <- mean(final_data$InflationRate, na.rm = TRUE)
final_data$InflationRate[is.na(final_data$InflationRate)] <- mean_value
summary(final_data)
##       Year         Month             FED_value       CPI_value    
##  Min.   :1999   Length:301         Min.   :0.050   Min.   :164.3  
##  1st Qu.:2005   Class :character   1st Qu.:0.140   1st Qu.:194.4  
##  Median :2011   Mode  :character   Median :1.220   Median :225.9  
##  Mean   :2011                      Mean   :1.924   Mean   :224.3  
##  3rd Qu.:2017                      3rd Qu.:3.620   3rd Qu.:246.7  
##  Max.   :2024                      Max.   :6.540   Max.   :308.4  
##   UNEMP_value     InflationRate    
##  Min.   : 3.100   Min.   :-1.9153  
##  1st Qu.: 4.300   1st Qu.: 0.0000  
##  Median : 5.100   Median : 0.2066  
##  Mean   : 5.698   Mean   : 0.2109  
##  3rd Qu.: 6.500   3rd Qu.: 0.4627  
##  Max.   :14.400   Max.   : 1.3736
# Create Annual Inflation Rate from 1994 to 2024
ggplot(final_data, aes(x = Year, y = InflationRate), size = 1) +
  geom_point() +  # Use geom_point for scatter plot
  labs(title = "US Annual Inflation Rate from 1999 to 2024",
       x = "Year",
       y = "Inflation Rate (%) ") +
  theme_minimal()

The Consumer Price Index is indeed a key indicator used to measure inflation by tracking the changes in prices paid by consumers for a basket of goods and services over time. When the CPI increases, it indicates that, on average, prices for goods and services are rising.

The expected average consumer price vs inflation rates in the beginning of years are (5.44% in 2024, 7.99% in 2023 and 8.41% in 2022). A decrease in the inflation rate could suggest a potential slowing down of the increase in the cost of living. When there is an upward change in the CPI, there has been an increase in the average change in prices over time.

Visualize Unemployment Rate, Inflaction Rate, and FED Funds Rate

# Plot annually values of CPI, FED Fund Rate and Unemployment Rate
ggplot(final_data, aes(x = Year)) +
  geom_line(aes(y = FED_value, color = "FED Funds Rate"), linewidth = 1) +
  geom_line(aes(y = InflationRate, color = "Inflaction Rate"), linewidth = 1) +
  geom_line(aes(y = UNEMP_value, color = "Unemployment Rate"), linewidth = 1) +
  labs(title = "Annual Unemployment Rate, Inflaction Rate, and FED Funds Rate",
       x = "Year",
       y = "Values") +
  scale_color_manual(values = c("FED Funds Rate" = "blue", 
                                "Inflaction Rate" = "orange", 
                                "Unemployment Rate" = "red")) +
  theme_minimal()

Conclusions

The FED Funds Rate influences maximum sustainable employment and price stability or inflation. Lowering FED funds rates may contribute to higher inflation, while raising rates can help prevent excessive inflation. According the above graphs, it is found that the FED Funds Rate was not able to fulfill the mandate given to it by Congress from 2008-2022 during global economic recessions, unexpected financial crisis and pubic health epidemic such as COVID-19 pandemic.