rerror-handlingtry-catchgtgtextras

How do I perform error-handling on non-existent web image that throws a HTTP 404 error?


I am trying to create a gt table with cropped headshots of baseball players, however there is no image available for one player (Cameron Sisneros) and this causes an HTTP error 404. Ideally, absence of a player image would default to a cropped version of the logo for Minor League Baseball (included in code below). If I omit this one player, the code runs fine, see image below. However, I'd like a more scalable solution to handle this type of error and display all players, with a fallback image for those that don't have an available headshot.

library(cropcircles)
library(tidyverse)
library(gt)
library(gtExtras)
 
df_test <- structure(list(player = c("Matt Shaw", "Owen Caissie", 
                                     "Cameron Sisneros"), 
          matchup_batter_id = c(807713L, 683357L, 815133L), 
          HR = c(4L, 4L, 3L)), 
          row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame")) %>%  
   
 # filter(player != 'Cameron Sisneros') %>% 
  mutate(headshot = paste0("https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/",matchup_batter_id,"/headshot/milb/current")) %>% 
  mutate(headshot = cropcircles::circle_crop(headshot,
                                border_size = 12,
                                border_colour = "black")
          ) # Ideally an HTTP error 404 would default to cropped image of the league logo
  # League logo found here: https://images.ctfassets.net/iiozhi00a8lc/7eeTdW5zGYe0sW2ZlIle7E/990464d4b5e4e3b3a65cb6c56ce808ea/milb-alt.svg

# Construct gt table
df_test %>% 
  gt() %>% 
  gt_img_rows(headshot, height = 37, img_source = "local") #add cropped headshots 

Example of gt table without photo-less player


Solution

  • You could use purrr::possibly() adverb to create a modified version of cropcircles::circle_crop() that returns some default value instead of an error.

    To avoid replacing all values with the default when there's even a single bad URL in the input column, you'd need to process one URL at a time, so for example purrr:map_chr() in a mutate() call or just use rowwise() grouping:

    library(cropcircles)
    library(tidyverse)
    library(gt)
    library(gtExtras)
    
    # default image
    default_headshot <- 
      cropcircles::circle_crop("https://images.ctfassets.net/iiozhi00a8lc/7eeTdW5zGYe0sW2ZlIle7E/990464d4b5e4e3b3a65cb6c56ce808ea/milb-alt.svg",
                               border_size = 12, border_colour = "black")
    
    # return default_headshot in case of an error,
    cc_possibly <- possibly(cropcircles::circle_crop, otherwise = default_headshot)
    
    
    df_test <- structure(list(player = c("Matt Shaw", "Owen Caissie", 
                                         "Cameron Sisneros"), 
                              matchup_batter_id = c(807713L, 683357L, 815133L), 
                              HR = c(4L, 4L, 3L)), 
                         row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame")) %>%  
      mutate(headshot = paste0("https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_360/v1/people/",matchup_batter_id,"/headshot/milb/current")) %>% 
      # process URLs one by one
      rowwise() %>%
      mutate(headshot = cc_possibly(headshot, border_size = 12, border_colour = "black")) %>%
      # drop rowwise grouping
      ungroup() 
    
    # Construct gt table
    df_test %>% 
      gt() %>% 
      gt_img_rows(headshot, height = 37, img_source = "local") %>%
      # for reprex output
      gt_reprex_image()
    

    Created on 2024-09-29 with reprex v2.1.1