Chapter 18 UK Economic Data

Note: Chapter under development

18.1 ONS

The Office of National Statistics (ONS) collates and publishes most of the UK’s economic data sets.

There’s two main ways to access this data. Option 1, poorly formatted spreadsheets. Option 2, an API (which has been in beta for over 5 years). We’ll step through both.

There’s several R packages out there that either ping the ONS’ API or web scrape the data. Kostas Vasilopoulos has produced one of the better ones (and it’s on CRAN) called onsr.

library(onsr)

#Get a list of all datasets available
ons_ids()
##  [1] "wellbeing-quarterly"                          
##  [2] "wellbeing-local-authority"                    
##  [3] "weekly-deaths-region"                         
##  [4] "weekly-deaths-local-authority"                
##  [5] "weekly-deaths-health-board"                   
##  [6] "weekly-deaths-age-sex"                        
##  [7] "uk-spending-on-cards"                         
##  [8] "uk-business-by-enterprises-and-local-units"   
##  [9] "traffic-camera-activity"                      
## [10] "trade"                                        
## [11] "tax-benefits-statistics"                      
## [12] "suicides-in-the-uk"                           
## [13] "sexual-orientation-by-region"                 
## [14] "sexual-orientation-by-age-and-sex"            
## [15] "retail-sales-index-large-and-small-businesses"
## [16] "retail-sales-index-all-businesses"            
## [17] "retail-sales-index"                           
## [18] "regional-gdp-by-year"                         
## [19] "regional-gdp-by-quarter"                      
## [20] "projections-older-people-sex-ratios"          
## [21] "projections-older-people-in-single-households"
## [22] "output-in-the-construction-industry"          
## [23] "online-job-advert-estimates"                  
## [24] "older-people-sex-ratios"                      
## [25] "older-people-net-internal-migration"          
## [26] "older-people-economic-activity"               
## [27] "mid-year-pop-est"                             
## [28] "life-expectancy-by-local-authority"           
## [29] "labour-market"                                
## [30] "index-private-housing-rental-prices"          
## [31] "house-prices-local-authority"                 
## [32] "health-accounts"                              
## [33] "gva-by-industry-by-local-authority"           
## [34] "generational-income"                          
## [35] "gdp-to-four-decimal-places"                   
## [36] "gdp-by-local-authority"                       
## [37] "faster-indicators-shipping-data"              
## [38] "cpih01"                                       
## [39] "childrens-wellbeing"                          
## [40] "ashe-tables-9-and-10"                         
## [41] "ashe-tables-7-and-8"                          
## [42] "ashe-tables-3"                                
## [43] "ashe-tables-27-and-28"                        
## [44] "ashe-tables-26"                               
## [45] "ashe-tables-25"                               
## [46] "ashe-tables-20"                               
## [47] "ashe-tables-11-and-12"                        
## [48] "ashe-table-5"                                 
## [49] "ageing-population-projections"                
## [50] "ageing-population-estimates"                  
## [51] "TS079"                                        
## [52] "TS078"                                        
## [53] "TS077"                                        
## [54] "TS076"                                        
## [55] "TS075"                                        
## [56] "TS074"                                        
## [57] "TS073"                                        
## [58] "TS072"                                        
## [59] "TS071"                                        
## [60] "TS070"
ons_datasets()
## # A tibble: 60 × 23
##    contacts     description      keywords id    last_updated links$editions$href
##    <list>       <chr>            <list>   <chr> <chr>        <chr>              
##  1 <df [1 × 3]> Seasonally and … <chr>    well… 2023-12-13T… https://api.beta.o…
##  2 <df [1 × 3]> Estimates of li… <chr>    well… 2023-12-13T… https://api.beta.o…
##  3 <df [1 × 3]> Provisional cou… <chr>    week… 2025-05-30T… https://api.beta.o…
##  4 <df [1 × 3]> Provisional cou… <chr>    week… 2024-01-09T… https://api.beta.o…
##  5 <df [1 × 3]> Provisional cou… <chr>    week… 2024-01-09T… https://api.beta.o…
##  6 <df [1 × 3]> Provisional cou… <chr>    week… 2025-05-30T… https://api.beta.o…
##  7 <df [1 × 3]> These data seri… <NULL>   uk-s… 2024-05-16T… https://api.beta.o…
##  8 <df [1 × 3]> The data contai… <chr>    uk-b… 2022-11-03T… https://api.beta.o…
##  9 <df [1 × 3]> Experimental da… <NULL>   traf… 2024-06-20T… https://api.beta.o…
## 10 <df [1 × 3]> Country by comm… <chr>    trade 2025-05-19T… https://api.beta.o…
## # ℹ 50 more rows
## # ℹ 20 more variables: links$latest_version <df[,2]>, $self <df[,1]>,
## #   $taxonomy <df[,1]>, methodologies <list>, national_statistic <lgl>,
## #   next_release <chr>, qmi <tibble[,1]>, related_datasets <list>,
## #   release_frequency <chr>, state <chr>, title <chr>, unit_of_measure <chr>,
## #   type <chr>, publications <list>, license <chr>, is_based_on <df[,2]>,
## #   canonical_topic <chr>, subtopics <list>, survey <chr>, …
onsgdp <- onsr::ons_get(id = "gdp-to-four-decimal-places")

head(onsgdp,100)
## $message
##                                              
## "`file` is not one of the supported inputs:" 
## 
## $trace
##      ▆
##   1. └─onsr::ons_get(id = "gdp-to-four-decimal-places")
##   2.   └─onsr:::read_csv_silent(raw$downloads$csv$href, ons_read, ...)
##   3.     ├─base::tryCatch(...)
##   4.     │ └─base (local) tryCatchList(expr, classes, parentenv, handlers)
##   5.     │   └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
##   6.     │     └─base (local) doTryCatch(return(expr), name, parentenv, handler)
##   7.     ├─base::suppressMessages(...)
##   8.     │ └─base::withCallingHandlers(...)
##   9.     └─readr::read_csv(x, ...)
##  10.       └─vroom::vroom(...)
##  11.         └─vroom:::standardise_path(file)
##  12.           └─cli::cli_abort(...)
##  13.             └─rlang::abort(...)
## 
## $parent
## NULL
## 
## $body
##                                             * 
## "A filepath or character vector of filepaths" 
##                                             * 
##         "A connection or list of connections" 
##                                             * 
##                        "Literal or raw input" 
## 
## $rlang
## $rlang$inherit
## [1] TRUE
## 
## 
## $call
## vroom::vroom(file, delim = ",", col_names = col_names, col_types = col_types, 
##     col_select = {
##         {
##             col_select
##         }
##     }, id = id, .name_repair = name_repair, skip = skip, n_max = n_max, 
##     na = na, quote = quote, comment = comment, skip_empty_rows = skip_empty_rows, 
##     trim_ws = trim_ws, escape_double = TRUE, escape_backslash = FALSE, 
##     locale = locale, guess_max = guess_max, show_col_types = show_col_types, 
##     progress = progress, altrep = lazy, num_threads = num_threads)
## 
## $use_cli_format
## [1] TRUE

18.2 Nomis

Census data, as well as economic and social data sets that take into account location, are produced by the ONS’ Nomis service. Nomis has it’s very own R package called nomisr.

The last UK census was in 2021. While there is a census slated for 2031, there is a growing consensus that this may not be necessary, with new administrative data sets providing a more accurate picture of the UK’s population.

18.3 Trade

In April 2025, trade is well and truly the talk of the town.

UK trade data is collated by HM Revenue & Customs (HMRC) and published on the website https://www.uktradeinfo.com/.

Peter van der Meulen has developed a wonderful R package uktrade to query HMRC’s database and stitch together tables.

Here’s a worked example: