Fill Dataframe with Outputs of ZipRadius

Hey team! Needed some help onhow to run with a task (maybe a loop?)

I've got a list of a few zipcodes and wanted to get all additional zipcodes that are available on a 100 miles radius distance from the original ones - there's a specific package for that called ZipRadius.

The issue is that ZipRadius can only process one original zip at a time, I needed to process every original zip on the list and then fill a dataframe with ZipRadius output so i can clean it later to leave only the below info:

 original_zip     zips_within_100mi    Distance

1 43207 25095 94.68
2 43207 25106 88.33
3 43208 25187 95.57
4 43208 25123 98.06

Here's an reproductible example of what i've done, I'm limited with just the first zip as you can see - is there a way to do it for all the items of the list?

library(tidyverse)
library(ZipRadius)
zip <- c(43207, 43208, 21201)
rad <- zipRadius(zip[1],100)
rad <- expand_grid(zip[1],rad)
rad <- rad %>% select("zip[1]",zip,Distance)%>%rename(zips_within_100mi = zip, original_zip = "zip[1]")

For people coming here in the future, looks like ZipRadius was archived on CRAN and can be found here.

Now, for the solution - I would use lapply along with dplyr::bind_rows. Just make sure you tack on the original zip using dplyr::mutate inside the lapply function.

# Your original code, except with the edit to coerce zip to character
library(tidyverse)

library(ZipRadius)
zip <- c(43207, 43208, 21201) %>% 
    as.character # Since zipRadius requires zip codes to be characters, not numbers
rad <- zipRadius(zip[1],100)
rad <- expand_grid(zip[1],rad)
rad <- rad %>% 
    select(
        "zip[1]",
        zip,
        Distance
    ) %>% 
    rename(
        zips_within_100mi = zip, 
        original_zip = "zip[1]"
    )

# This is how I would do it
lapply(
    zip,
    function(z) {
        # Where z is an individual zip
        radius <- zipRadius(
            zipcode = z, radius = 100
        ) %>% 
            mutate(
                original_zip = z
            ) %>% 
            select(
                original_zip,
                'zips_within_100mi' = zip,
                'distance' = Distance
            )    
    }
) %>% 
    bind_rows()
#>   original_zip zips_within_100mi distance
#> 1        43207             25095    94.68
#> 2        43207             25106    88.33
#> 3        43207             25123    98.06
#> 4        43207             25187    95.57
#> 5        43207             25239    93.97
#> 6        43207             25241    98.66

Created on 2022-06-01 by the reprex package (v1.0.0)

The biggest issue seems to be that zipRadius doesnt fail nicely when given a zip it doesnt recognise, ie. 43208, your second zip. Therefore I use purrr package twice, once to make a 'safe' version of zipradius, and then to map over each zip to get the related zipradius.

library(tidyverse)
library(ZipRadius)
zip <- c(43207, 43208, 21201)

mysafezipr <- purrr::safely(zipRadius,
                            otherwise = tibble::tibble(
                              zip = character(0),
                              city = character(0),
                              state = character(0),
                              latitude = numeric(0),
                              longitude = numeric(0),
                              Distance = numeric(0)
                            ))

map_dfr(zip, ~{
  mysafezipr(.x,100)$result %>%  mutate(
    original_zip =.x) %>% 
  select(original_zip ,
         zips_within_100mi = zip,
         Distance)
})

Agree that your solution works, but I don't believe there is an issue with the failure behavior of zipRadius. It looks like the default behavior of zipRadius is to warn, but not to fail. Warning instead of failing is not unreasonable, since there are in fact no zip codes within the radius of the given zip

# This works
{
    print('Always Runs')
    zipRadius('43208', 100)
    print('Runs on success of zipRadius')
}

Whereas if you throw an invalid type to zipRadius such as a number, you trigger an actual error instead of a warning, stopping execution:

{
    print('Always Runs')
    zipRadius(12345, 100)
    print('This will never run')
}

I think the confusion on this issue relates to the package version and the removal of the package from cran. I use renv for my package management so I installed it with no issue, automagically from MRAN, this is the last CRAN published version 1.0.1 - that has a defect. You are using the github package you linked to that presumably has fixed the issue.

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.