Kilka punktów do rozważenia.
1 - Optymalne miejsce dla celów adnotacji wewnątrz wielokąta
w idealnym świecie, każdy wielokąt jest podobna do okręgu, a jej centrum jest najlepszym miejscem, aby umieścić etykietę tekstową (np Teksas). W rzeczywistości regiony map są w różnych kształtach, & może nawet nie być w jednym kawałku (np. Michigan). Średnia matematyczna/mediana może znajdować się na krawędzi lub poza poligonem (na przykład na Florydzie).
R nie będzie tak wielki, próbując zrozumieć te komplikacje. Zamiast tego użyłbym oprogramowania GIS.
Jeśli jednak Twój przypadek użycia to USA, zestaw danych state.vbm.center
ma już całkiem niezły zestaw domyślnych współrzędnych. Jej stany plików pomocy:
state.vbm.center są współrzędne ośrodkach państwowych dla adnotacji celów.
Rzućmy okiem na których te punkty to:
#data
mapbase <- map_data("state.vbm")
data(state.vbm.center)
cnames <- state.vbm.center %>% as.data.frame() %>%
mutate(region = unique(mapbase$region))
#actual plotting
ggplot()+
geom_polygon(data=mapbase,
aes(long, lat, group = region, fill = region),
alpha = 0.3) +
coord_fixed() + theme_void() +
geom_point(data = cnames,
aes(x, y)) +
scale_fill_discrete(guide = F)

to nie jest zbyt brudny. Jeśli wszystko, co potrzebne do znakowania są nazwy stanów, to powinno wystarczyć:
cnames$abb <- state.abb
ggplot()+
geom_polygon(data=mapbase,
aes(long, lat, group = region, fill = region),
alpha = 0.3) +
coord_fixed() + theme_void() +
geom_text(data=cnames,
aes(x, y , label = abb),
color= "black", size=3, fontface = 2,
hjust = 0.5, vjust = 0.5) + #central alignment
scale_fill_discrete(guide = F)

2 - Montaż długich etykiet w ciasnych przestrzeniach
To bardzo dobrze przylegające krótkie etykiety zasięgu map wielokątów, ale jeśli chcesz podać więcej informacji (pełna nazwa każdego stanu, wskaźnik urodzeń, wskaźnik przestępczości, stopa bezrobocia, poziom wykształcenia, zasięg dochodów, gęstość zaludnienia, odsetek osób, które głosowały w ostatnich wyborach, ...), ostatecznie zaczną brakować miejsca w mniejszych/więcej wei Wieloboki w kształcie rdly.
W tym miejscu można przyjąć podejście podwójne, zachowując informacje w obrębie większych wielokątów, & umieszczając mniejsze wielokąty oddzielnie po jednej stronie, jak w częściowej legendzie. Dla stanów USA, strefa stan jest częścią standardowego datasets
pakietu, co oszczędza nam kłopotu z jej obliczenia:
# incorporate area information & identify small area states
cnames$area <- state.area
ggplot(cnames %>%
mutate(region = factor(region, levels = region[order(area)])),
aes(x = region, y = area)) + geom_col() +
theme_classic() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
# the first 7 states (up to Maryland) are noticeably smaller than the rest

Wybierz jakieś fajne pusty obszar na mapę dla małych państw. I postanowił dostosować je pionowo w 1 kolumnie na długości = 140 & szerokość w zakresie od 0 do 60:
library(tidyr)
legend.states <- cnames$region[which(cnames$area <= 10577)]
legend.states <- as.data.frame(legend.states)
legend.states$long1 <- 140
legend.states$lat1 <- seq(0, 60, length.out = nrow(legend.states))
legend.states <- legend.states %>%
mutate(long2 = long1 + 5, lat2 = lat1) %>%
mutate(long3 = long2, lat3 = lat2 - 5) %>%
mutate(long4 = long1, lat4 = lat3) %>%
mutate(long5 = long1, lat5 = lat1) %>%
gather(k, v, -legend.states) %>%
mutate(order = as.integer(substring(k, nchar(k))),
k = gsub("[0-9]", "", k)) %>%
spread(k, v) %>%
rename(region = legend.states) %>%
mutate(group = mapbase$group[match(region, mapbase$region)]) %>%
select(long, lat, group, order, region) %>%
mutate(subregion = NA)
# add legend polygons to the original polygon dataset
mapbase2 <- rbind(mapbase, legend.states)
przekształcenie współrzędnych Adnotacja tych małych stanach, tak że są dostosowane do położeń legendę:
cnames2 <- left_join(cnames,
legend.states %>% filter(order %in% c(1, 4)) %>%
group_by(region) %>%
summarise(long = mean(long) + 7,
lat = mean(lat))) %>%
mutate(x = coalesce(long, x),
y = coalesce(lat, y),
hjust = ifelse(is.na(lat), 0.5, 0))
# left alignment (hjust=0) for small state text, central alignment (hjust=0.5) otherwise.
umieścić wszystko razem:
ggplot()+
geom_polygon(data=mapbase2,
aes(long, lat, group = region, fill = region),
alpha = 0.3) +
coord_fixed() + theme_void() +
geom_text(data=cnames2,
aes(x, y , label = abb, hjust = hjust),
size=3, fontface = 2,
vjust = 0.5) +
scale_fill_discrete(guide = F)

(Uwaga: w przypadku dłuższego tekstu prawdopodobnie będziesz musiał również zwiększyć ograniczenia osi X i/lub wstawić znaki linii podziału.)