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:
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
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.