rif-statementgeospatial

st_intersects in an if statement runs when the if statement is not met


I want this function to convert a US state name to uppercase state abbreviation. If (and only if!) the name is not easily convertible, I want it to use the lat/long to find which state it intersects with.

library(tidyverse)
library(sf)

# Import state data to check state names
state.sf <- st_as_sf(maps::map("state", fill=TRUE, plot =FALSE)) %>%
  mutate(state = str_to_title(ID),
         short.state.name = state.abb[match(state, state.name)]) 


# Correct state names
state_name_corrector <- function(State, Lat, Long) {
  
  
  if(State %in% state.abb){
    return(State)
  }else{
    # If the State name is spelled out, find the abbreivation
    state.abbreviation <- state.abb[which(state.name == State)]
    
    # If the spelled out name isn't found, just use the lat/long
    if(length(state.abbreviation) == 0 & !is.na(Lat) & !is.na(Long)){
      sf.for.intersects <- st_as_sf(data.frame(Lat, Long),
                                    coords = c("Long", "Lat"),
                                    crs = st_crs(state.sf))
      sf_use_s2(FALSE)
      intersected_state <- state.sf %>%
        slice(which(st_intersects(sf.for.intersects, state.sf, sparse = FALSE))) %>%
        pull(short.state.name)
      
      # Return the state abbreviation found via lat/long
      if (length(intersected_state) > 0) {
        return(intersected_state)
      } else {
        return(NA)
      }
      
    } else if (length(state.abbreviation) > 0){
      return(state.abbreviation)
    }
    
    # If there's no state and no lat/long, just give up
    return(NA)
    }
  }
  

# test data
test.df <- data.frame(state = c("al", "FL", "NA", "GA"),
                      Lat = c(32.1, 30.2, 30, 30),
                      Long = c(-87, -82, -82, -82))


mapply(state_name_corrector, test.df$state, test.df$Lat, test.df$Long)

This gives four identical warnings:

although coordinates are longitude/latitude, st_intersects assumes that they are planar

Indicating that all four lines of the test data were run through st_intersects, even though only two have state names not in state.abb.

Why is st_intersects evaluated four times??


Solution

  • Your assumption is incorrect. Running:

    st_intersects(sf.for.intersects, state.sf, sparse = FALSE)
    

    generates two warnings.

    This can be easily be seen like so:

    state_name_corrector("al", 1, 1)
    
    although coordinates are longitude/latitude, st_intersects assumes that they are planar
    although coordinates are longitude/latitude, st_intersects assumes that they are planar
    

    My guess is that you get two warnings because the intersection is a binary operation, and a warning is generated for both the x and y arguments.