I wish to generate a map of the state of Kansas in R that displays the border of the state, the borders of each of its counties, and a terrain background. To that end, I use the libraries ggmap and mapdata.
library(ggmap)
library(ggthemes)
library(dplyr)
library(mapdata)
ks_state_map_df <- map_data("state", region="kansas")
ks_counties_map_df <- map_data("county") %>% filter(region=="kansas")
ks_cities_map_df <- us.cities %>% filter(country.etc=="KS")
ks_cities_map_df$name <- gsub(" KS","", ks_cities_map_df$name)
KS_area <- c(left=-102.051744, right=-94.588413, bottom=36.993016, top=40.003162)
KS_map <- get_stadiamap(bbox=KS_area, maptype='outdoors')
ggmap(KS_map) +
theme_map() +
geom_polygon(data=ks_state_map_df, mapping=aes(x=long, y=lat, group=group), color="black", fill=NA) +
geom_polygon(data=ks_counties_map_df, mapping=aes(x=long, y=lat), color="gray", fill=NA) +
geom_point(data=ks_cities_map_df, mapping=aes(x=long, y=lat)) +
geom_text(data=ks_cities_map_df, mapping=aes(x=long, y=lat, label=name), hjust=0, nudge_x=0.1)
However, it seems that my above code attempt does not render the polygons correctly (something to do with the group attribute, I believe). How do I need to fix my code?

Edit 1:
The terrain map areas should be increased to: KS_area <- c(left=-102.2, right=-94.4, bottom=37.2, top=40.2)

Updated answer
As @r2evans mentions, you need to group each individual feature. But when dealing with geospatial point, line, and polygon data, the
sfpackage is almost always the most robust approach. That's because it allows you set the CRS of each layer etc. I haven't usedst_crs()and/orst_transform()in this example and instead am usinginherit.aes = FALSEfor the sf objects.Also, I have used the
ggrepelpackage for dealing with overlapping text labels. Getting thegeom_text_repel()parameters right is more 'art' than science, but it can be an effective approach.