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)
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)