knitr::opts_chunk$set(echo = FALSE, fig.align = "center") library(tidyverse) library(gridExtra) library(magick) library(hexSticker) library(showtext) library(knitr) library(cowplot)
sticker <- image_read('https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo.png')
knitr::include_graphics("images/petfinder-website.PNG")
knitr::include_graphics("images/petfinder-dogs.PNG")
https://www.petfinder.com/developers/v2/docs/
New version requires sign-up to receive 'key' and 'secret'
Conduct searches using 'curl' (client url) on the command line
Responses are in JSON format
List search options (available animal types, breeds, etc.)
Search pets and organizations by type, location, id, and more
knitr::include_graphics("images/petfinder-for-developers.PNG")
https://github.com/earl88/PetFindr
knitr::include_graphics("../../man/figures/logo.png")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
Package httr
by Hadley Wickham
GET
, POST
, add_headers
, content
, status_code
Endpoint: https://api.petfinder.com/v2/
Request token
knitr::include_graphics("images/curl-oauth.PNG")
knitr::include_graphics("images/curl-search.PNG")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/logo1.jpg) background-size: 150px background-position: 99.5% 4.5%
To guide users in the authentication process, pf_setup
is there for you.
First, let's install the package!
devtools::install_github("earl88/PetFindr") library(PetFindr)
You need a Petfinder account.
pf_setup()
knitr::include_graphics("https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/setup_message.png")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/logo1.jpg) background-size: 150px background-position: 99.5% 4.5%
Once you create an account, you will be assigned a unique key
and secret
.
knitr::include_graphics("https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/register.png")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/logo1.jpg) background-size: 150px background-position: 99.5% 4.5%
Once you create an account, you will be assigned a unique key
and secret
.
knitr::include_graphics("https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/getanapi.png")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/logo1.jpg) background-size: 150px background-position: 99.5% 4.5%
Once you create an account, you will be assigned a unique key
and secret
.
knitr::include_graphics("https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/secretandkey.png")
These values can be saved to your .Rprofile for future use.
petfindr_key <- "paste_key_here" petfindr_secret <- "paste_secret_here" pf_save_credentials(key = petfindr_key, secret = petfindr_secret)
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/logo1.jpg) background-size: 150px background-position: 99.5% 4.5%
With your key
and secret
, you must now request an access token for the API.
pf_accesstoken <- function(key = NULL, secret = NULL) { if (is.null(key) || is.null(secret)) { stop("You must provide both a key and a secret to receive an access token. Please run 'pf_setup()' for more information.") } auth <- POST(url = "https://api.petfinder.com/v2/oauth2/token", body = list(grant_type = "client_credentials", client_id = key, client_secret = secret), encode = "json") if (auth$status_code != 200) {stop(pf_error(auth$status_code))} accesstoken <- content(auth)$access_token message("Your access token will last for one hour. After that time, you will need to generate a new token.\n") return(accesstoken) }
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/logo1.jpg) background-size: 150px background-position: 99.5% 4.5%
token <- pf_accesstoken(petfindr_key, petfindr_secret)
knitr::include_graphics("https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/tokenmessage.png")
Now you are all set. Let's find pets!
pf_list_breeds(token, type = "cat") %>% head(n = 20)
knitr::include_graphics("https://raw.githubusercontent.com/earl88/PetFindr/master/inst/FinalPresentation/images/chowchow.gif")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
p1 <- ggdraw() + draw_image(image = "./images/list.type.2.jpg", scale = 1.2) p2 <- ggdraw() + draw_image(image = "./images/list.type.4.jpg", scale = 1) p3 <- ggdraw() + draw_image(image = "./images/list.type.3.jpg", scale = 1) p4 <- ggdraw() + draw_image(image = "./images/list.type.6.jpg", scale = 0.9) plot_grid(p1, p2, p3, p4)
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_list_types(token)
data(pf_types)
data("pf_types", package = "PetFindr") pf_types
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_list_breeds(token, type)
A list of all available breeds of each pet
Input: token, type of animal
Output: A character vector of the available breeds for the specified animal type
data(pf_breeds)
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_breeds
data("pf_breeds", package = "PetFindr") #pf_breeds knitr::include_graphics("./images/pf_breeds.png")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_pets(token, type, breed, size, gender, color, location, ...)
.pull-left[ * A data frame of pets info listed on Petfinder.com
knitr::include_graphics(path = "./images/find.pets.3.png")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_pets(token) pf_find_pets(token, type = "horse") pf_find_pets(token, type = "dog", age = "baby", page = 1:5) pf_find_pets(token, type = "Scales, Fins, & Others", breed = "Python", sort = "-recent")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
Column names of data frames output from pf_find_pets
#knitr::include_graphics(path = "./images/find.pets.png") data("LA_puppies", package = "PetFindr") names(LA_puppies)
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
LA_puppies %>% select("species", "breeds.primary","type", "age", "gender","size", "name", "colors.primary" ) %>% head(8)
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_view_photos(animal_df, size)
View the photos of searched pets in a slideshow format
Input:
Photo size
Output: A slideshow of pet pictures
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_view_photos(token, size)
knitr::include_graphics("https://media.giphy.com/media/Maz1hoeGskARW/giphy.gif")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_organizations(token, name, location, distance, ...)
Returns a dataframe of details on a group of organizations based on criteria given in parameters. How does it work?
A GET request structure:
an optional query string consisting of a question mark followed by parameter/value pairs separated by ampersands
Base url: https://api.petfinder.com/v2/organizations?
Example of query string:
location=Ames,%20IA&distance=50&page=2
https://www.petfinder.com/developers/v2/docs/#get-organizations
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_organizations
pf_find_organizations <- function(token = NULL, name = NULL, location = NULL, distance = NULL, state = NULL, country = NULL, sort = "recent", page = 1, limit = 20) { base <- "https://api.petfinder.com/v2/organizations?" args <- as.list(match.call())[-1] query <- args[!names(args) %in% c("token", "page")] %>% purrr::map(eval) query[(query != "") & !is.na(query)] ... query <- paste(names(query), query, sep = "=", collapse = "&") %>% gsub(pattern = "[ ]", replacement = "%20")
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_organizations
Request the listed information on the first page to R!
If the API returns an error, an informative message will be printed in an HTTP response format.
probe <- GET(url = paste0(base, query), add_headers(Authorization = paste("Bearer", token))) if (probe$status_code != 200) {stop(pf_error(probe$status_code))}
Invalid API key/secret/token
https://www.petfinder.com/developers/v2/docs/#errors
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_organizations
Deal with some issues of page specification (default: page=1).
A single page request: use the initial request!
assertthat::assert_that(is.numeric(page)) if (length(page) == 1 && page == 1) { organization_info <- content(probe)$organizations } else { max_page <- content(probe)$pagination$total_pages if (max(page) > max_page) { warning("You have specified one or more page numbers that do not exist.") if (any(page <= max_page)) { page <- page[page <= max_page] } else { warning("No valid pages were specified. Defaulting to page 1.") organization_info <- content(probe)$organizations}}}
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_organizations
Multiple pages: repeat the request by pages with apply-based method.
Listed information for each page is stored in a bigger list.
organization_info <- lapply(paste0(base, query, "&page=", page), function(x) { results <- GET(url = x, add_headers(Authorization = paste("Bearer", token))) if (results$status_code != 200) { stop(pf_error(results$status_code))} content(results)$organizations}) %>% purrr::flatten()
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_find_organizations
The same set of information may not exist for all of the organizations (or pets)
Flatten the list, assign distinct names (e.g., photo1, photo2, ...), and return a dataframe!
organization_df <- purrr::map_dfr(organization_info, .f = function(x) { rlist::list.flatten(x) %>% rbind.data.frame(deparse.level = 0, stringsAsFactors = F) }) return(organization_df) }
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
pf_map_locations
Input: token, a dataframe of pets returned from pf_find_pets
Ouput: locations of organizations of pets on a Leaflet map
How it works: Request location information by organizations' id that are extracted from a dataframe of individual pets
https://www.petfinder.com/developers/v2/docs/#get-organization
Example
data(LA_puppies, package = "PetFindr") PetFindr::pf_map_locations(token, LA_puppies)
background-image: url(https://raw.githubusercontent.com/earl88/PetFindr/master/man/figures/logo1.png) background-size: 150px background-position: 99.5% 4.5%
knitr::include_graphics("images/Shiny-hex.png")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.