草庐IT

关于 r:ggplot 在地图上居中名称

codeneng 2023-03-28 原文

ggplot centered names on a map

我正在尝试使用 ggplot2 和地图来绘制纽约state的县名。我的方法是按县查找经纬度的平均值(我假设这是县的中心,但这可能是错误的想法),然后使用 geom_text 在地图上绘制名称。它的行为不像我预期的那样,因为它在每个县绘制了多个名称。

我正在寻找的结果是每个文本(县)的中心位于它各自县的中心。

除了解决问题之外,我希望能帮助理解我对 ggplot 的想法有什么问题。

提前谢谢你。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

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

1
2
3
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 的平均值,并使用尊重纵横比和投影的地图坐标系:

1
2
3
4
5
6
7
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()

  • 我认为你已经完成了我的要求,甚至更多。所以我将此线程标记为已解决。谢谢你。我仍然对名称的位置不满意,现在意识到我需要一种更好的居中方法。贾斯汀的方法看起来很有趣。我将发布另一个关于一些改进的居中技术的问题。
  • 对中点更好的是 geosphere 包中的质心函数。这是我在此答案中所做的,而不是聚合函数: cnames <- ddply(ia_pop, .(County, group), summarize, Centroid=centroid(cbind(long, lat))) 然后像这样拆分 Centroid 列: cnames$long <- cnames$Centroid[,1]cnames$lat <- cnames$Centroid[,2]


我知道这是一个已经回答的老问题,但我想补充一下,以防有人在这里寻求未来的帮助。

地图包有 map.text 功能,它使用多边形质心来放置标签。查看它的代码,可以看到它使用 apply.polygoncentroid.polygon 函数来查找质心。这些函数在加载包时不可见,但仍然可以访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 进行了更改,尽管我早就应该这样做了。


@tjebo 在我尝试创建一个新的统计数据时向我指出,这个统计数据将是这个问题的合适解决方案。 它不在 CRAN 上(还),但生活在 github 上。(免责声明:我写了 ggh4x)

对于处理类似问题的其他人,这是如何工作的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 包 (v0.3.0) 创建于 2020-07-06


似乎kmeans中心会很有用...这是一个糟糕的开始...为时已晚!

1
2
3
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))

  • 别看它……它丑陋!

有关关于 r:ggplot 在地图上居中名称的更多相关文章

  1. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  2. ruby-on-rails - 应用程序的名称是否可以作为变量使用? - 2

    当我创建一个Rails应用程序时,控制台:railsnewfoo我的代码可以使用字符串“foo”吗?puts"Yourapp'snameis"+app_name_bar 最佳答案 Rails.application.class将为您提供应用程序的全名(例如YourAppName::Application)。从那里您可以使用Rails.application.class.parent获取模块名称。 关于ruby-on-rails-应用程序的名称是否可以作为变量使用?,我们在StackOve

  3. ruby-on-rails - 如何从过时的 TZInfo 标识符中获取 Rails TimeZone 名称? - 2

    已经有一个问题回答了如何将“America/Los_Angeles”转换为“PacificTime(US&Canada)”。但是我想将“美国/太平洋”和其他过时的时区转换为RailsTimeZone。我无法在图书馆中找到任何可以帮助我完成此任务的东西。 最佳答案 来自RailsActiveSupport::TimeZonedocs:TheversionofTZInfobundledwithActiveSupportonlyincludesthedefinitionsnecessarytosupportthezonesdefinedb

  4. ruby - 解释为局部变量会覆盖方法名称吗? - 2

    如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f

  5. ruby-on-rails - 如何让 Rails View 返回其关联的操作名称? - 2

    我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam

  6. ruby-on-rails - ActiveAdmin 自定义选择过滤器下拉名称 - 2

    对于用户模型,我有一个过滤器来检查用户的预订状态,该状态由整数值(0、1或2)表示。UserActiveAdmin索引页上的过滤器是通过以下代码实现的:filter:booking_status,as::select然而,这会导致下拉选项为0、1或2。当管理员用户从下拉列表中选择它们时,我更愿意自己将它们命名为“未完成”、“待定”和“已确认”之类的名称。有没有办法在不改变booking_status在模型中的表示方式的情况下做到这一点? 最佳答案 假设booking_status是模型中的枚举字段,您可以使用:过滤器:booking

  7. ruby-on-rails - 关于 Ruby 的一般问题 - 2

    我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia

  8. ruby-on-rails - 使用 gmaps4rails 动态加载谷歌地图标记 - 2

    如何只加载map边界内的标记gmaps4rails?当然,在平移和/或缩放后加载新的。与此直接相关的是,如何获取map的当前边界和缩放级别? 最佳答案 我是这样做的,我只在用户完成平移或缩放后替换标记,如果您需要不同的行为,请使用不同的事件监听器:在你看来(index.html.erb):{"zoom"=>15,"auto_adjust"=>false,"detect_location"=>true,"center_on_user"=>true}},false,true)%>在View的底部添加:functiongmaps4rail

  9. ruby - Ruby 中 <=> 运算符的名称是什么?他们怎么调用它? - 2

    在Ruby中有运算符(operator)。在API中,他们没有命名它的名字,只是:Theclassmustdefinetheoperator...Comparableusestoimplementtheconventionalcomparison......theobjectsinthecollectionmustalsoimplementameaningfuloperator...它叫什么名字? 最佳答案 参见上面的@Tony。然而,它也被称为(俚语)“宇宙飞船运算符(operator)”。

  10. ruby - 将 Logstash 中的时间戳时区转换为输出索引名称 - 2

    在我的场景中,Logstash收到的系统日志行的“时间戳”是UTC,我们在Elasticsearch输出中使用事件“时间戳”:output{elasticsearch{embedded=>falsehost=>localhostport=>9200protocol=>httpcluster=>'elasticsearch'index=>"syslog-%{+YYYY.MM.dd}"}}我的问题是,在UTC午夜,Logstash在外时区(GMT-4=>America/Montreal)结束前将日志发送到不同的索引,并且索引在20小时(晚上8点)之后没有日志,因为“时间戳”是UTC。我们已

随机推荐