77# ' @param as_list boolean, default `FALSE`. The default behaviour is to
88# ' extract the data from the list and return it as a tibble. If set `TRUE`,
99# ' an unprocessed list of the JSON data from the API will be returned instead
10- # ' @param include_codes boolean, default `TRUE`. Include columns for the ONS
11- # ' administrative codes for geographic units in the returned tibble. Irrelevant
12- # ' if `as_list` is `TRUE`; in this case all ONS codes are included as a
13- # ' nested list in the list data for each postcode.
14- # ' See \url{https://postcodes.io/docs/postcode/lookup} for details
10+ # ' @param filter character vector or helper function. The default is
11+ # ' [filter_fields], which by default evaluates to `NULL`, which means no
12+ # ' fields will be filtered out from the returned data. You can also use
13+ # ' [filter_fields] to validate a vector of field names that you supply - see
14+ # ' Examples below.
15+ # ' The full list of field names is available in the [schema_table] data. Some
16+ # ' other helper functions are provided for common scenarios: [exclude_codes]
17+ # ' and [minimal_fields].
18+ # ' See \url{https://postcodes.io/docs/postcode/bulk} for details.
1519# ' @examples
16- # ' get_postcode_data(c("NP22 3PS", "NP22 4PS", "NP22 5PS"))
20+ # ' codes <- c("NP22 3PS", "NP22 4PS", "NP22 5PS")
21+ # ' get_postcode_data(codes)
22+ # ' my_fields <- c("postcode", "lsoa", "codes.lsoa", "eastings", "northings")
23+ # ' # get_postcode_data(codes, filter = my_fields) is fine, but using
24+ # ' # filter_fields() to wrap your vector gives you a validation check:
25+ # ' get_postcode_data(codes, filter = filter_fields(my_fields))
26+ # ' # The `schema_table` dataset within NHSRpostcodetools contains a "field"
27+ # ' # column with all available fields. You can use this as a starting point:
28+ # ' excl_fields <- setdiff(schema_table[["field"]], c("quality", "country"))
29+ # ' get_postcode_data(codes, filter = filter_fields(excl_fields))
30+ # ' # or use a helper function as a starting point to add to:
31+ # ' get_postcode_data(codes, TRUE, filter_fields(c(minimal_fields(), "region")))
1732# ' @returns A tibble by default, otherwise a list if `as_list` is TRUE
1833# ' @export
19- get_postcode_data <- function (x , as_list = FALSE , include_codes = TRUE ) {
34+ get_postcode_data <- function (x , as_list = FALSE , filter = filter_fields() ) {
2035 x <- unique(toupper(purrr :: discard(x , is.na )))
2136 assertthat :: assert_that(length(x ) > 0L , msg = " No postcodes have been found." )
2237
@@ -37,19 +52,18 @@ get_postcode_data <- function(x, as_list = FALSE, include_codes = TRUE) {
3752 if (length(valid_codes ) > 0L ) {
3853 results_list <- valid_codes | >
3954 batch_it(100L ) | >
40- purrr :: map(bulk_lookup , .progress = " Looking up postcode data..." )
55+ purrr :: map(
56+ \(x ) bulk_lookup(x , filter_fields = filter ),
57+ .progress = " Looking up postcode data..."
58+ )
4159
4260 if (as_list ) {
4361 results_list
4462 } else {
45- results_df <- tibblise_results_list(results_list )
46- if (! include_codes ) {
47- dplyr :: select(results_df , ! tidyselect :: ends_with(" _code" ))
48- } else {
49- results_df
50- }
63+ tibblise_results_list(results_list )
5164 }
5265 } else {
66+ cli :: cli_alert_warning(" No valid postcodes were supplied" )
5367 invisible (NULL )
5468 }
5569}
@@ -69,12 +83,23 @@ get_postcode_data <- function(x, as_list = FALSE, include_codes = TRUE) {
6983# ' ) |>
7084# ' postcode_data_join()
7185# ' @export
72- postcode_data_join <- function (tbl , .col = " postcode" , include_codes = TRUE ) {
86+ postcode_data_join <- function (
87+ tbl ,
88+ .col = " postcode" ,
89+ filter = filter_fields()
90+ ) {
7391 assertthat :: assert_that(
7492 inherits(tbl , " data.frame" ),
7593 .col %in% colnames(tbl )
7694 )
77- api_data <- get_postcode_data(tbl [[.col ]], include_codes = include_codes )
95+ assertthat :: assert_that(
96+ (is.null(filter ) || " postcode" %in% filter ),
97+ msg = cli :: cli_abort(paste0(
98+ " The {.val postcode} field must be included in {.arg filter} in order " ,
99+ " for {.fn postcode_data_join} to work."
100+ ))
101+ )
102+ api_data <- get_postcode_data(tbl [[.col ]], filter = filter )
78103 dplyr :: left_join(tbl , api_data , by = dplyr :: join_by({{ .col }} == " postcode" ))
79104}
80105
0 commit comments