在SpatialPolygonsDataFrame对象上使用Rcartogram

时间:2013-08-24 14:28:47

标签: r maps rgdal cartogram

我正在尝试在这个问题中提出同样的问题Cartogram + choropleth map in R,但是从SpatialPolygonsDataFrame开始并希望最终得到相同类型的对象。

我可以将对象保存为shapefile,使用scapetoad,重新打开它并转换回来,但我宁愿把它全部放在R中,这样程序就可以完全重现了,所以我可以编写几十个变化自动。

我已经在github上分享了Rcartogram代码,并加入了我迄今为止的努力here

本演示基本上是在地图上创建一个SpatialGrid,在网格的每个点查找人口密度,并将其转换为cartogram()所需格式的密度矩阵。到目前为止一切都很好。

但是,如何根据cartogram()的输出插入原始地图点?

这里有两个问题。第一种是将地图和网格放入相同的单位以允许插值。第二种是访问每个多边形的每个点,对其进行插值,并使它们保持正确的顺序。

网格采用网格单位,地图采用投影单位(例如longlat示例)。必须将网格投影到longlat中,或将地图投影到网格单元中。我的想法是制作一个假的CRS,并将其与spTransform()中的package(rgdal)函数一起使用,因为它可以轻松处理对象中的每个点。

访问每个点很困难,因为它们是SpPDF对象的几个层:对象>多边形>多边形>线> coords我认为。任何想法如何访问这些,同时保持整个地图的结构完整?

1 个答案:

答案 0 :(得分:2)

这个问题可以通过Chris Brunsdon's GitHub上提供的getcartr软件包解决,在this博文中有详细说明。

quick.carto函数完全符合您的要求 - 以SpatialPolygonsDataFrame作为输入并输出SpatialPolygonsDataFrame

在博客文章中重现示例的精髓,以防链接失效,我自己的风格混合在&拼写错误:

Shapefile; World Bank population data

library(getcartr)
library(maptools)
library(data.table)

world <- readShapePoly("TM_WORLD_BORDERS-0.3.shp")
#I use data.table, see blog post if you want a base approach;
#  data.table wonks may be struck by the following step as seeming odd;
#  see here: http://stackoverflow.com/questions/32380338
#  and here: https://github.com/Rdatatable/data.table/issues/1310
#  for some background on what's going on.
world@data <- setDT(world@data)

world.pop <- fread("sp.pop.totl_Indicator_en_csv_v2.csv",
                   select = c("Country Code", "2013"),
                   col.names = c("ISO3", "pop"))

world@data[world.pop, Population := as.numeric(i.pop), on = "ISO3"]

#calling quick.carto has internal calls to the
#  necessary functions from Rcartogram
world.carto <- quick.carto(world, world$Population, blur = 0)

#plotting with a color scale
x <- world@data[!is.na(Population), log10(Population)]
ramp <- colorRampPalette(c("navy", "deepskyblue"))(21L)
xseq <- seq(from = min(x), to = max(x), length.out = 21L)
#annoying to deal with NAs...
cols <- ramp[sapply(x, function(y)
  if (length(z <- which.min(abs(xseq - y)))) z else NA)]

plot(world.carto, col = cols,
     main = paste0("Cartogram of the World's",
                   " Population by Country (2013)"))

enter image description here