R SF Object – Creating an SF Object from the Maps Package in R for Advanced Geospatial Analysis

ggplot2rsf

I am trying to use data from the maps package in an sf workflow. I'm not sure if I have the operation correct (see below). It seems to work until state 20 (massachusetts). What am I doing wrong? Maybe there is a better way to do this?

state_data <- ggplot2::map_data("state")
state_data_sf <- lapply(unique(state_data$region),
                function(x)
                  list(matrix(unlist(
                  state_data[state_data$region == x,][,c("long", "lat")]),
                  ncol = 2)))

sf::st_polygon(state_data_sf[[19]])

POLYGON((-87.4620056152344 30.3896808624268, -87.4849319458008 39.6200332641602, -78.1113357543945 39.6658706665039, -78.1342544555664 39.67732…

sf::st_polygon(state_data_sf[[20]])

Error in MtrxSet(x, dim, type = "POLYGON", needClosed = TRUE) :
polygons not (all) closed

Best Answer

I figured it out. The polygons need to be manually closed by rbinding the first row:

state_data <- ggplot2::map_data("state")
state_data_sf <- lapply(unique(state_data$region),
                function(x)
                  list(matrix(unlist(
                  rbind(
                    state_data[state_data$region == x,][,c("long", "lat")],
                    state_data[state_data$region == x,][1, c("long", "lat")])),
                  ncol = 2)))
res <- lapply(state_data_sf, sf::st_polygon)

EDIT

This is a much better solution. It is cleaner and does not suffer from closed polygon issues.

states <- sf::st_as_sf(maps::map("state", plot = FALSE, fill = TRUE))