2017-07-25 1 views
5

Je fais un tracé de carte, où je veux mettre une petite étiquette de texte à l'intérieur de chaque état. Mon problème actuel est que le texte va en dehors des limites de l'État, il ne semble pas agréable: enter image description hereComment s'assurer que le titre du texte est à l'intérieur de l'objet polygone?

J'ai essayé d'utiliser: moyenne, médiane, et ainsi de suite centroïdes.

Ce que je veux est tout texte pour être complètement à l'intérieur ou à l'extérieur du polygone, comme ici: enter image description here (image à partir d'http://www.businessinsider.com/map-what-100-is-actually-worth-in-your-state-2015-7?IR=T)

J'utilise le code suivant pour générer mon image:

library(maps) 
library(dplyr) 
library(ggplot2) 

#data 
mapbase <- map_data("state.vbm")  
data(state.vbm.center) 
df <- state.vbm.center %>% as.data.frame() %>% 
    mutate(region = unique(mapbase$region)) %>% full_join(mapbase) 


#actual plotting 
cnames <- aggregate(cbind(long, lat) ~ region, data=df, FUN=median) 
gmap<- 
    ggplot()+ 
    geom_polygon(data=df2, 
       aes(long, lat, group = region, fill = somevalue,alpha=0.3)) + 
    coord_fixed() + 
    theme_void() + 
    geom_text(data=cnames, aes(fontface=2 ,cnames$long, cnames$lat , label = "text" 
), color= "black" ,size=3,check_overlap = T, position=position_jitter(width=3, height=3) ) + 

    scale_fill_gradient(low="red",high="blue") 

Merci beaucoup pour vos conseils!

Répondre

3

Plusieurs points à considérer.

1 - lieu optimal à des fins d'annotation dans un polygone

Dans un monde idéal, chaque polygone est similaire à un cercle et son centre est le meilleur endroit pour placer une étiquette de texte (par exemple Texas). En réalité, les régions de carte sont de toutes sortes de formes, & peut même ne pas être en une seule pièce (par exemple Michigan). Le point mathématique moyen/médian peut être sur le bord ou à l'extérieur du polygone (par exemple en Floride). R ne va pas être si bon pour essayer de comprendre ces complications. J'utiliserais un logiciel SIG à la place.

Cependant, si votre cas d'utilisation est des États-Unis, l'ensemble de données state.vbm.center vient déjà avec un très bon jeu de coordonnées par défaut. Ses états de fichier d'aide:

state.vbm.center sont les coordonnées des centres d'état pour l'annotation fins.

Jetons un coup d'oeil à où ces points sont les suivants:

#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) 

center location

Ce n'est pas trop mal. Si tout ce que vous devez étiqueter sont des noms d'état, cela devrait suffire:

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) 

abbreviated names

2 - étiquettes longues Montage dans des espaces restreints

Il est très bien ajusté des étiquettes courtes dans les polygones de carte, mais si vous voulez inclure plus d'informations (nom complet de chaque état, taux de natalité, taux de criminalité, taux de chômage, niveau d'éducation, fourchette de revenu, densité de population, proportion de personnes ayant voté aux dernières élections, ...), vais commencer à manquer d'espace dans le plus petit/plus wei polygones formés en forme de.

Une approche double peut être adoptée à ce stade, en gardant l'information dans les plus grands polygones, & en plaçant les plus petits polygones séparément d'un côté comme une légende partielle. Pour les États américains, la zone d'état fait partie du paquet datasets standard, ce qui nous permet d'économiser la peine de le calculer:

# 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 

sorted by area size

Choisissez des belle zone vide sur votre carte pour les petits États. Je décidé de les aligner verticalement dans une colonne de longitude = 140, & latitude allant de 0 à 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) 

Changer l'annotation coordonnées pour ces petits états, de telle sorte qu'ils sont alignés sur les positions de la boîte de légende:

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. 

tout Assemblez:

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) 

legend box

(Remarque: pour un texte plus long, vous devrez probablement également augmenter les limites de l'axe des x et/ou insérer des sauts de ligne.)