Skip to contents

This page provides an overview for the get_builddata() function, highlighting some of its potential uses.

First things first—let’s load the troopdata package

Basic Use

The get_builddata() function returns a data frame containing geocoded location-project-year military construction data. The basic arguments function the same as compared to the previous functions. The primary difference is that the data cover fiscal years 2000 through 2026, as published in the Department of Defense Comptroller Annual Report C-1 exhibits. Note there are also many observations included that contain amounts, but do not disclose location names or other information.


hostlist <- c(200, 260, 211) # United Kingdom, Germany, Belgium (Gleditsch and Ward codes)

buildexample <- get_builddata(host = hostlist, startyear = 2008, endyear = 2019)
#> Warning: Spending values are in thousands of current US dollars.
#> Warning: Data may include unspecified locations and zero or negative spending
#> values.

head(buildexample)
#> # A tibble: 6 × 42
#>   gwcode iso3c state_country state_country_name state_country_sort fiscal_year
#>    <dbl> <chr> <chr>         <chr>              <chr>                    <dbl>
#> 1    211 BEL   BE            NA                 NA                        2008
#> 2    211 BEL   BE            Belgium            NA                        2010
#> 3    211 BEL   BE            Belgium            NA                        2010
#> 4    211 BEL   BE            Belgium            NA                        2010
#> 5    211 BEL   BE            Belgium            NA                        2011
#> 6    211 BEL   BE            Belgium            NA                        2011
#> # ℹ 36 more variables: location_name <chr>, location_name_reported <chr>,
#> #   location_full_name <chr>, location_code <chr>, latitude <dbl>,
#> #   longitude <dbl>, geo_source <chr>, organization <chr>,
#> #   organization_reported <chr>, project_number <chr>, project_title <chr>,
#> #   project_title_reported <chr>, appn_title <chr>, budget_activity <dbl>,
#> #   budget_activity_title <chr>, budget_activity_title_reported <chr>,
#> #   facility_group_title <chr>, facility_category_code <chr>, …

The host argument takes ISO3C codes or Gleditsch and Ward country codes, the same numeric codes the troop deployment data use. Territories carry the same ad hoc codes as in the troop data, so Guam is 1008 (or "GUM") and Puerto Rico is 6 (or "PRI") in both. The data also include construction inside the United States, which you can get with host = "USA" or host = 2. In fact most of the rows are projects in the United States. Leaving host at its default returns everything. Note that startyear and endyear have no defaults in this function, so you always need to supply both.

There are several other ways to narrow things down. The location and project arguments search installation names and project titles, organization picks out a service or defense agency, and facility_category and budget_activity filter on the type of facility and the budget activity. For host, organization, facility_category and budget_activity, a value that does not match anything in the data returns an error that tells you where to look, rather than an empty data frame. The location and project searches simply return no rows when nothing matches.


ramstein <- get_builddata(location = "Ramstein", startyear = 2010, endyear = 2020)
#> Warning: Spending values are in thousands of current US dollars.
#> Warning: Data may include unspecified locations and zero or negative spending
#> values.

ramstein[, c("fiscal_year", "location_name", "organization", "project_title", "appn_amount")]
#> # A tibble: 9 × 5
#>   fiscal_year location_name organization               project_title appn_amount
#>         <dbl> <chr>         <chr>                      <chr>               <dbl>
#> 1        2010 Ramstein AB   Air Force                  Contingency …       23200
#> 2        2010 Ramstein AB   Air Force                  Construct AG…       11500
#> 3        2011 Ramstein AB   Air Force                  UAS SATCOM R…       10476
#> 4        2011 Ramstein AB   Air Force                  Construct C-…        7954
#> 5        2011 Ramstein AB   Air Force                  Deicing Flui…        2671
#> 6        2012 Ramstein AB   Air Force                  Dormitory (1…       34697
#> 7        2014 Ramstein AB   Department of Defense Edu… Ramstein Hig…       98762
#> 8        2017 Ramstein AB   Air Force                  37 As Squadr…       13437
#> 9        2019 Ramstein AB   Air Force                  EDI - KMC DA…      119000

How values are handled

A few things are worth knowing before you start adding up dollars.

Each row is one line of a report. A row is a single project at a single location in a single fiscal year. It is not a country total. To get spending by country and year you need to add the rows up yourself:


library(dplyr)

buildexample %>%
  group_by(iso3c, fiscal_year) %>%
  summarise(projects = n(),
            appropriations = sum(appn_amount, na.rm = TRUE)) %>%
  head()
#> # A tibble: 6 × 4
#> # Groups:   iso3c [1]
#>   iso3c fiscal_year projects appropriations
#>   <chr>       <dbl>    <int>          <dbl>
#> 1 BEL          2008        1           5992
#> 2 BEL          2010        3          99524
#> 3 BEL          2011        2          98975
#> 4 BEL          2012        1          24118
#> 5 BEL          2013        1          24854
#> 6 BEL          2014        2          67613

Amounts are in thousands of current US dollars. There are four amount columns: appropriations (appn_amount), authorizations (auth_amount), authorization of appropriations (auth_appn_amount) and total obligational authority (toa_amount). They are not adjusted for inflation. Negative values are real. They show up where money was rescinded or reprogrammed. Not every report gives every amount: the FY2006 report has appropriations only, and total obligational authority is also missing for FY2000. The spend_type, min_amount and max_amount arguments let you pick an amount column and filter on it.

Each fiscal year comes from one report. Every C-1 report covers two or three fiscal years, so the same year appears in more than one report, often with revised figures. The data take each fiscal year from the most recent report that covers it, so a project-year is only counted once. For every year but one that is an enacted or actual figure. The exception is FY2016, where the only report we have is the one that requests it. FY2010 also has 26 lines that come from a request sheet for overseas contingency operations and do not appear on any enacted sheet. All of these rows are flagged with is_request, and include_requests = FALSE drops them.

Some rows have no location. About a quarter of the rows report an amount under a label such as “Unspecified Worldwide Locations” rather than a place. These rows have no country code, so they are only returned when host is left at its default. One group is an exception: the base realignment and closure lines for FY2007 through FY2016 are filed under that label, but their project titles name a US installation (for example “USA-224: Fort Hood, TX”). Those rows carry the US country code and the installation’s coordinates, so host = "USA" returns them.

Coordinates. The latitude and longitude columns come from geocoding the location name. A point is only kept if it falls inside the country or state the row is filed under. Installations that the geocoder put in the wrong place were corrected by hand, and the geo_source column tells you whether a point came from a geocoding service ("arcgis") or was entered by hand ("manual"). Rows with no location, and the few locations we could not find, have no coordinates and will drop out of a map.

Not every column is reported every year. The layout of the C-1 reports changed over time. Columns such as transaction_type, project_number and facility_category_title only exist for some fiscal years, and filtering on one of them quietly limits you to those years. The help page for build_data_20260918 lists the coverage of each column.

Applications

As with the base data you can build cool maps using the construction data. You can also size the points according to the amount of spending associated with a particular location, adding some additional details to maps and other figures.


library(ggplot2)

map <- ggplot2::map_data("world")
basepoints <- troopdata::get_builddata(host = NA, startyear = 2009, endyear = 2019)


buildmap <- ggplot() +
  geom_polygon(data = map, aes(x = long, y = lat, group = group), fill = "gray80", color = "white", size = 0.1) +
  geom_point(data = basepoints, aes(x = longitude, y = latitude, size = toa_amount), color = "purple", alpha = 0.4) +
  coord_equal(ratio = 1.3) +
  theme_void() +
  theme(plot.title = element_text(face = "bold", size = 15)) +
  labs(title = "Locations of U.S. military construction spending, 2009-2019",
       size = "Spending Amount")


buildmap