For the U.S., I can get the centroids of all the counties in a state. However, upon closer inspection, the centroid of some counties is not correct. How can I manually correct the point geometry (latitude and longitude) for a given county?
Example of Virginia
library(dplyr) # data wrangling
library(sf) # for getting centroids
library(tigris) # for getting county shapefile
library(cdlTools) # converting state fips to state name
library(ggplot2) # for mapping
### Extract centroids for each county in the USA
centroids <- counties(resolution = "20m") %>%
st_centroid()
centroids$STATE_NAME <- fips(centroids$STATEFP, to = 'Name')
va_cnty <- centroids[centroids$STATE_NAME %in% 'Virginia',]
### Make map of VA showing location of county centroids ----
state_shp <- states(cb = T)
state_shp$STATEFP <- as.numeric(state_shp$STATEFP)
state_shp <- state_shp[state_shp$STATEFP %in% c(1,3:14,16:56),]
cnty_shp <- counties(cb = TRUE)
cnty_shp$STATEFP <- as.numeric(cnty_shp$STATEFP)
lower48_shp <- cnty_shp[cnty_shp$STATEFP %in% c(1,3:14,16:56),]
va_shp <- lower48_shp[lower48_shp$STUSPS == 'VA',]
ggplot() +
geom_sf(data = state_shp,
mapping = aes(geometry = geometry),
color = 'black',
fill = 'gray70') +
geom_sf(data = va_shp,
mapping = aes(geometry = geometry),
color = 'black',
fill = 'lightyellow') +
geom_sf(data = va_cnty,
mapping = aes(geometry = geometry),
color = "black",
fill = 'red',
shape = 21,
size = 3) +
coord_sf(xlim = c(-83.5, -75), ylim = c(36.4, 39.5), expand = TRUE) +
theme_bw() +
theme(text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black"),
panel.grid.major = element_blank(),
panel.background = element_rect(fill = "lightblue"))
Map of the center lat and long of each county in Virginia
How can I change the latitude and longitude in the geometry column of va_cnty
? The correct latitude and longitude are: 37.772236, -75.660827
Two unsuccessful attempts
va_cnty[va_cnty$NAME %in% 'Accomack',7] <- st_point(c(-75.660827,37.772236))
# Error in `[<-.data.frame`(`*tmp*`, va_cnty$NAME %in% "Accomack", 7, value = c(-75.660827,: replacement has 2 rows, data has 1
sfc = st_sfc(st_point(c(-75.660827,37.772236)), crs = 'NAD83')
va_cnty[va_cnty$NAME %in% 'Accomack',7] <- sfc
# Warning message:
# In `[<-.data.frame`(`*tmp*`, va_cnty$NAME %in% "Accomack", 7, value = # list( : replacement element 1 has 2 rows to replace 1 rows
Geometry column in sf is a list-column, so you'd have to handle it like a list when working with individual elements:
library(sf)
# sf example dataset
nc <- st_read(system.file("shape/nc.shp", package="sf")) |>
st_centroid()
nc[1:5,"NAME"]
#> Simple feature collection with 5 features and 1 field
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: -81.49823 ymin: 36.40714 xmax: -76.02719 ymax: 36.49111
#> Geodetic CRS: NAD27
#> NAME geometry
#> 1 Ashe POINT (-81.49823 36.4314)
#> 2 Alleghany POINT (-81.12513 36.49111)
#> 3 Surry POINT (-80.68573 36.41252)
#> 4 Currituck POINT (-76.02719 36.40714)
#> 5 Northampton POINT (-77.41046 36.42236)
# logical index
nc$geometry[nc$NAME == "Ashe"] <- st_point(c(111,111))
# numeric index
nc$geometry[[2]] <- st_point(c(222,222))
# st_geometry method instead of $
st_geometry(nc)[[3]] <- st_point(c(333,333))
# replace just lon
nc$geometry[[4]][1] <- 123
# replace just lat
nc$geometry[[4]][2] <- 321
Result:
nc[1:5,"NAME"]
#> Simple feature collection with 5 features and 1 field
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: -77.41046 ymin: 36.42236 xmax: 333 ymax: 333
#> Geodetic CRS: NAD27
#> NAME geometry
#> 1 Ashe POINT (111 111)
#> 2 Alleghany POINT (222 222)
#> 3 Surry POINT (333 333)
#> 4 Currituck POINT (123 321)
#> 5 Northampton POINT (-77.41046 36.42236)
Created on 2023-05-09 with reprex v2.0.2