使用ggplot在地图上居中显示名称

19
我试图使用ggplot2和maps绘制纽约州各县的名称。我的方法是找到每个县的纬度和经度的平均值(我假设这是该县的中心,但这可能是错误的想法),然后使用geom_text在地图上绘制名称。但它并没有按照我预期的那样运行,因为它在每个县中绘制了多个名称。
我希望每个文本(县)的中心都位于其相应县的中心位置。
除了解决问题外,我还希望能够理解我在使用ggplot时的错误思路。
提前感谢您的帮助。
library(ggplot2); library(maps)

county_df <- map_data('county')  #mappings of counties by state
ny <- subset(county_df, region=="new york")   #subset just for NYS
ny$county <- ny$subregion
cnames <- aggregate(cbind(long, lat) ~ subregion, data=ny, FUN=mean)

p <- ggplot(ny, aes(long, lat, group=group)) +  geom_polygon(colour='black', fill=NA) 
p #p of course plots as expected

#now add some county names (3 wrong attempts)
p + geom_text(aes(long, lat, data = cnames, label = subregion, size=.5)) #not correct

#I said maybe I'm confusing it with the same names for different data sets
names(cnames) <-c('sr', 'Lo', 'La')
p + geom_text(Lo, La, data = cnames, label = sr, aes(size=.5)) #attempt 2
p + geom_text(aes(Lo, La, data = cnames, label = sr, size=.5)) #attempt 3
4个回答

33

由于您要创建两个图层(一个用于多边形,一个用于标签),因此您需要为每个图层正确指定数据源和映射:

ggplot(ny, aes(long, lat)) +  
    geom_polygon(aes(group=group), colour='black', fill=NA) +
    geom_text(data=cnames, aes(long, lat, label = subregion), size=2)

注意:

  • 由于数据框中都包含了longlat,因此在第一个ggplot调用中,可以使用aes(long, lat)。这里声明的任何映射都适用于所有层。
  • 出于同样的原因,你需要在多边形图层内声明aes(group=group)
  • 在文本层中,需要将数据源移动到aes之外。

完成上述操作并绘制地图后,您会发现中点最好是通过range的平均值来近似,并使用一种保持长宽比和投影的地图坐标系:

cnames <- aggregate(cbind(long, lat) ~ subregion, data=ny, 
                    FUN=function(x)mean(range(x)))

ggplot(ny, aes(long, lat)) +  
    geom_polygon(aes(group=group), colour='black', fill=NA) +
    geom_text(data=cnames, aes(long, lat, label = subregion), size=2) +
    coord_map()

在此输入图片描述


我认为你已经完成了我要求的事情,甚至更多。所以我将标记此线程为已解决。谢谢。我仍然不满意名称的位置,并且现在意识到我需要更好的居中方法。Justin的方法看起来很有趣。我将发布另一个问题,询问一些改进的居中技术。 - Tyler Rinker
对于中点而言,更好的选择是geosphere包中的centroid函数。以下是我在这个答案中使用的代替aggregate函数的方法: cnames <- ddply(ia_pop, .(County, group), summarize, Centroid=centroid(cbind(long, lat))) 然后像这样拆分Centroid列: cnames$long <- cnames$Centroid[,1]cnames$lat <- cnames$Centroid[,2] - Danny

6
我知道这是一个早已被回答的老问题,但我想在这里补充一下,以便今后需要帮助的人查看。
maps包中有一个map.text函数,它使用多边形质心来放置标签。通过查看它的代码,可以看到它使用apply.polygon和centroid.polygon函数来找到质心。当加载该包时,这些函数不可见,但仍然可以访问:
library(ggplot2); library(maps)

county_df <- map_data('county')  #mappings of counties by state
ny <- subset(county_df, region=="new york")   #subset just for NYS
ny$county <- ny$subregion
cnames <- aggregate(cbind(long, lat) ~ subregion, data=ny, FUN=mean)

# Use the map function to get the polygon data, then find the centroids
county_poly <- map("county", "new york", plot=FALSE, fill = TRUE)
county_centroids <- maps:::apply.polygon(county_poly, maps:::centroid.polygon)

# Create a data frame for graphing out of the centroids of each polygon
# with a non-missing name, since these are the major county polygons.
county_centroids <- county_centroids[!is.na(names(county_centroids))]
centroid_array <- Reduce(rbind, county_centroids)
dimnames(centroid_array) <- list(gsub("[^,]*,", "", names(county_centroids)),
                                 c("long", "lat"))
label_df <- as.data.frame(centroid_array)
label_df$county <- rownames(label_df)

p <- ggplot(ny, aes(long, lat, group=group)) + geom_polygon(colour='black', fill=NA) 

plabels <- geom_text(data=label_df, aes(label=county, group=county))
p + plabels

如果代码包括 p 是什么的行会更有帮助。此外,当尝试添加 p + plabels 时,我遇到了一个错误:Error in eval(expr, envir, enclos) : object 'group' not found - Henry E
1
@henry-e,我终于进行了长期以来应该做出的更改。 - Nathan Werth

4

当我尝试创建新的统计数据时,@tjebo向我指出了这个统计数据是解决这个问题的合适方案。虽然它还没有被放在CRAN上,但它存在于github上。(免责声明:我编写了ggh4x)

对于其他遇到类似问题的人,以下是它的工作原理:

library(ggh4x)
#> Loading required package: ggplot2
#> Warning: package 'ggplot2' was built under R version 4.0.2
library(maps)

county_df <- map_data('county')
ny <- subset(county_df, region=="new york")
ny$county <- ny$subregion


ggplot(ny, aes(x = long, y = lat, group = group)) +  
  geom_polygon(colour='black', fill=NA) +
  stat_midpoint(aes(label = subregion), geom = "text",size=3) +
  coord_map()

这段内容是由 reprex package (v0.3.0) 于2020-07-06创建的。


0

似乎kmeans centers会很有用...这是一个糟糕的开始...现在已经晚了!

center.points <- ddply(ny, .(group), function(df) kmeans(df[,1:2], centers=1)$centers)    
center.points$county <- ny$county[ny$group == center.points$group]
p + geom_text(data=center.points, aes(x=V1, y=V2, label=county))

1
不要看它... 它很丑陋! - Justin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接