library(tidyverse)
library(httr)
library(jsonlite)
<- Sys.getenv('api_bea_key')
api_bea_key
<- GET(
bea_nipa_tables ::glue(
glue'https://apps.bea.gov/api/data?UserID={api_bea_key}&method=GetParameterValues&datasetname=NIPA&ParameterName=tablename&ResultFormat=JSON'
)|>
) content(as = 'text') |>
fromJSON() |>
pluck(1,2,1)
7 Deflating nominal values to real values
We saw earlier in this section that it’s important to seasonally adjust a time series so we can make meaningful comparisons between time periods. Similarly, nominal time series (those expressed in current prices) should be deflated to real values in order to remove the effect of price changes over time. Knowing how to perform this operation is essential, as many economic time series are not available in real terms from the source.
To convert nominal data into real data, two things are needed. First, we must choose a base (or reference) year. The prevailing prices in that year will serve as the reference for all other years. For example, we can convert a sample of US nominal GDP from 2000 to 2020 using 2010 prices as the reference. In this case, all the years in the sample will be expressed in 2010 prices. This choice is generally arbitrary, but a good practice is to select a year in which prices were close to the sample average.
More importantly, we need to choose an appropriate price index to use as the deflator. Ideally, the deflator should accurately capture the price changes in the basket of goods or services represented by the series we want to adjust. For instance, it would make no sense to deflate a retail sales series using a construction price index. In the absence of a specific price index for the goods in the retail sales series, we could use a broader consumer price index as a proxy.
Let’s look at a practical example of how to deflate a series. For this, we’ll use data on US nominal GDP provided by the Bureau of Economic Analysis (BEA). It’s also a good opportunity to show how to access data from this relevant source using its API.
The data set containing the US nominal GDP and deflator from BEA is available in the R4ER2data
package under the name nominal_deflator_gdp_us
.
You’ll need to register in order to obtain access to the API. The process only takes a few minutes and requires minimal information. Since this information is personal, I’ve stored my key as an environment variable.
BEA provides a detailed document explaining how to use the API resources. Below, I’ll first retrieve the table names from the NIPA database, where GDP data are stored. Note that I use the pluck
function from the purrr
package as a substitute for [[
. 1 This makes it easier to access lower-level elements in lists.
We can see that the two tables of interest are T10105 (Gross Domestic Product) and T10104 (Price Indexes for Gross Domestic Product). Since the import procedure is the same for both series, it makes sense to create a function with the necessary steps and then use map
to apply it to each table name.
<- list(
bea_tables 'Nominal GDP' = 'T10105',
'Deflator' = 'T10104'
)<- function(tablename, api_bea_key) {
get_bea_data <- glue::glue(
api_bea_request 'https://apps.bea.gov/api/data?UserID={api_bea_key}&method=GetData&DataSetName=NIPA&TableName={tablename}&Frequency=A&Year=ALL&ResultFormat=json'
)<- GET(url = api_bea_request)
gdp_request <- content(gdp_request, as = 'text')
gdp_content <- fromJSON(gdp_content, flatten = FALSE)
gdp_list <- pluck(gdp_list, 1, 2, 4)
gdp_tbl
}<- map(
bea_data .x = bea_tables,
.f = function(x) get_bea_data(x, api_bea_key)
)
Next, I arrange the data in tidy format to facilitate further calculations.
<- map(
bea_data_tbl .x = bea_data,
.f = function(x){
|>
x filter(LineDescription == 'Gross domestic product') |>
select(TimePeriod, DataValue)
}|>
) ::ldply(.id = 'Serie') |>
plyrpivot_wider(names_from = Serie, values_from = DataValue) |>
mutate(across(c(`Nominal GDP`), ~ str_remove_all(.x, ','))) |>
mutate(across(-TimePeriod, ~ .x |> as.numeric())) |>
arrange(TimePeriod)
bea_data_tbl
# A tibble: 96 × 3
TimePeriod `Nominal GDP` Deflator
<chr> <dbl> <dbl>
1 1929 104556 8.75
2 1930 92160 8.41
3 1931 77391 7.58
4 1932 59522 6.72
5 1933 57154 6.54
6 1934 66800 6.86
7 1935 74241 6.99
8 1936 84830 7.08
9 1937 93003 7.34
10 1938 87352 7.20
# ℹ 86 more rows
Now we’re ready to convert nominal GDP into real GDP. To do this, we simply pick an arbitrary year as the reference – say 2005 – and divide the entire price index series by its value in that year. This sets the price index in 2005 equal to 1, with all other values expressed relative to it. Finally, we divide the nominal GDP series by this new price index series.
<- bea_data_tbl |>
gdp_real mutate(
Deflator_2005 = (Deflator / Deflator[which(TimePeriod == 2005)]),
`Real GDP` = `Nominal GDP` / Deflator_2005
)
library(lubridate)
|>
gdp_real pivot_longer(-TimePeriod, names_to = 'var', values_to = 'value') |>
filter(str_detect(var, 'Deflator', negate = TRUE)) |>
mutate(TimePeriod = as_date(TimePeriod, format = '%Y')) |>
ggplot(aes(x = TimePeriod)) +
geom_line(aes(y = value, color = var), lwd = 1) +
scale_y_continuous(
labels = scales::dollar_format(
scale = 1 / 1e6,
prefix = "$",
suffix = "T"
)+
) scale_x_date(date_breaks = '20 years', date_labels = '%Y') +
theme(legend.position = 'top') +
labs(
title = 'US Annual GDP: Nominal vs. Real (2005 Dollars)',
y = '',
x = '',
color = ''
)
It’s clear that ignoring price changes leads to misinterpretation of the GDP growth trajectory. This is precisely the kind of issue we aim to avoid when adjusting the series for inflation.
pluck(.x, 1,2,1)
is equivalent to.x[[1]][[2]][[1]]
↩︎