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?”
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)
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
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
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
# 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.
# 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()
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.