Chapter 1 Access Economic Data via the BEA API

While BEA data can be accessed via the official website, programming-inclined users can easily access data through BEA’s Application Programming Interface (API), which is a common way of querying and retrieving data. For R Users, BEA has developed the bea.R library that is optimized for econometricians, statisticians, and data analysts. bea.R can be installed directly from CRAN:

install.packages("bea.R")

Upon installation, load the library:

library(bea.R)

In order for BEA to understand user needs and to ensure a consistent, high level of service, the BEA API requires an API key – a simple 36 character code that opens access to data. The API key is free, asking for your name and email address: https://www.bea.gov/API/signup/index.cfm. Upon submitting an API key request, the key will be emailed to you.

Once you have received your BEA API key, save it to a variable to make it easier to use later:

beaKey <- "[36-Character-Key]"
## Warning in readLines("C:/Users/Jeff/Documents/beakey.txt"): incomplete
## final line found on 'C:/Users/Jeff/Documents/beakey.txt'

1.1 Searching for data

Much like using an index in a textbook, making a successful data retrieval request to the API requires specific information (e.g. variable series code, frequency, geographic units). The R library’s search functionality provides facility to easily surface the necessary information. Search is facilitated by the beaSearch() method, which requires two arguments: keyword and beaKey.

For example, the following keyword search returns a list of all datasets in which the term “Personal Consumption Expenditures” appears. One particularly important aspect of the search result is a pre-populated API call that jump starts the querying process.

beaSearch('Personal Consumption Expenditures', beaKey)
Table 1.1: Example results from through search interface.
SeriesCode DPCERL DPCEDX
RowNumber 20 20
LineDescription Personal consumption expenditures Personal consumption expenditures
LineNumber 2 2
ParentLineNumber
Tier 0 0
Path 2 2
TableID 1 10
DatasetName NIPA NIPA
TableName Table 1.1.1. Percent Change From Preceding Period in Real Gross Domestic Product Table 1.1.6D. Real Gross Domestic Product, Chained (1992) Dollars
ReleaseDate Dec 21 2017 8:30AM Aug 6 2015 12:00AM
NextReleaseDate Jan 26 2018 8:30AM Jan 1 1900 12:00AM
MetaDataUpdated 2017-12-21T21:24:27.427 2017-12-21T21:24:27.427
Account National National
apiCall beaGet(list(‘UserID’ = ‘[your_key]’, ‘Method’ = ‘GetData’, ‘DatasetName’ = ‘NIPA’, ‘TableID’ = ‘1’, …)) beaGet(list(‘UserID’ = ‘[your_key]’, ‘Method’ = ‘GetData’, ‘DatasetName’ = ‘NIPA’, ‘TableID’ = ‘10’, …))
Key NA NA
Desc NA NA
Parameter NA NA

For some keyword searches, a sufficiently specific search will yield only a few results. Given the vast amount of data that BEA publishes, the search functionality will often return a sizable amount of candidate results. This may be more easily evaluated by specifying asHtml = TRUE, which presents search results in an interactive, searchable table.

beaSearch('Final sales of computers to domestic purchasers', beaKey, asHtml = TRUE)

1.2 Get Data

Using the sample API call from the above example, we will retrieve Personal Consumption Expenditures from Table 1.1.1. Percent Change From Preceding Period in Real Gross Domestic Product. But in short, it is TableID = 1 from the NIPA dataset. Below, the list object specifies the relevant parameters, requesting the data at a quarterly frequency for all years.

specs <- list(
    'UserID' = beaKey,
    'Method' = 'GetData',
    'datasetname' = 'NIPA',
    'TableID' = '1',
    'Frequency' = 'Q',
    'Year' = '2010,2012,2013,2014',
    'ResultFormat' = 'json'
)

To retrieve a limited selection of multiple years, list all the years you want to retrieve. For example, to retrieve data for 2010 through 2014, use "Year"="2010,2012,2013,2014".

The beaGet() function can use the spec list to retrieve data. By default, the data are returned in wide form – each row is an indicator and each time period’s data is represented as a separate column.

df <- beaGet(specs);
head(df, 3)
##    TableID TableName SeriesCode LineNumber
## 1:       1    T10101     A191RL          1
## 2:       1    T10101     DPCERL          2
## 3:       1    T10101     DGDSRL          3
##                      LineDescription           METRIC_NAME
## 1:            Gross domestic product Fisher Quantity Index
## 2: Personal consumption expenditures Fisher Quantity Index
## 3:                             Goods Fisher Quantity Index
##                        CL_UNIT UNIT_MULT DataValue_2010Q1 DataValue_2010Q2
## 1: Percent change, annual rate         0              1.7              3.9
## 2: Percent change, annual rate         0              2.2              3.3
## 3: Percent change, annual rate         0              4.0              5.2
##    DataValue_2010Q3 DataValue_2010Q4 DataValue_2012Q1 DataValue_2012Q2
## 1:              2.7              2.5              2.7              1.9
## 2:              2.6              4.2              2.4              0.7
## 3:              3.8              7.6              4.9              1.1
##    DataValue_2012Q3 DataValue_2012Q4 DataValue_2013Q1 DataValue_2013Q2
## 1:              0.5              0.1              2.8              0.8
## 2:              1.1              1.1              1.9              0.8
## 3:              2.7              2.3              5.7              1.3
##    DataValue_2013Q3 DataValue_2013Q4 DataValue_2014Q1 DataValue_2014Q2
## 1:              3.1              4.0             -0.9              4.6
## 2:              1.9              3.4              1.9              3.5
## 3:              2.9              4.0              2.4              6.2
##    DataValue_2014Q3 DataValue_2014Q4
## 1:              5.2              2.0
## 2:              3.9              5.1
## 3:              4.5              5.7

For some use cases, in particular for time series models, obtaining the data in long form is desirable, which can be done by setting asWide = FALSE.

df <- beaGet(specs, asWide = FALSE);
head(df, 3)

In other cases, it may be more desirable to obtain the data in a form in which each column represents a variable, which is accomplished by setting iTableStyle = FALSE.

df <- beaGet(specs, iTableStyle = FALSE)
head(df, 3)