使用ggplot绘制带有地图的图表

22

我希望使用ggplot2(v.9)绘制世界地图,将两个信息合并在一起。以下示例说明:

library(rgdal)
library(ggplot2)
library(maptools)

# Data from http://thematicmapping.org/downloads/world_borders.php.
# Direct link: http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip
# Unpack and put the files in a dir 'data'

gpclibPermit()
world.map <- readOGR(dsn="data", layer="TM_WORLD_BORDERS_SIMPL-0.3")
world.ggmap <- fortify(world.map, region = "NAME")

n <- length(unique(world.ggmap$id))
df <- data.frame(id = unique(world.ggmap$id),
                 growth = 4*runif(n),
                 category = factor(sample(1:5, n, replace=T)))

## noise
df[c(sample(1:100,40)),c("growth", "category")] <- NA


ggplot(df, aes(map_id = id)) +
     geom_map(aes(fill = growth, color = category), map =world.ggmap) +
     expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
     scale_fill_gradient(low = "red", high = "blue", guide = "colorbar")

然而,这个解决方案并不是一个好的方式来展示growthcategoryGrowth非常明显,但category几乎看不到,因为它只是一个边框。
我已经尝试增加边框的大小,但没有成功(新的geom_map很难使用)。 有人知道如何在上面的示例中增加边框大小,或者更好的机制来显示两个因素吗? 额外的问题:地图包使用的国家名称(其中包括苏联!)在示例中使用的数据是脆弱的。 我更喜欢使用ISO 3166-1 alpha-3(1)。 有人知道是否有可与ggplot2一起使用的数据,其中包含ISO 3166-1 alpha-3国家名称(包含在链接数据中)
结果: result http://ompldr.org/vY3hsYQ

什么是world.map?在你的代码中没有定义。如果我尝试fortify(w,region="NAME"),我会得到一个“无效的多字节字符”错误。请提供可重现的代码。 - Ian Fellows
我在fortify行收到以下错误:“nchar(ID)中的错误:无效的多字节字符串1”。 - Ian Fellows
我无法在UTF8系统上重现;我怀疑字体编码是一个问题。iconv(.)可以将一种编码系统转换为另一种。 - Rasmus
2个回答

13

我会为填充颜色和线条颜色使用不同的色调范围:

ggplot(df, aes(map_id = id)) +
  geom_map(aes(fill = growth, color = category), map =world.ggmap) +
  expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
  scale_fill_gradient(high = "red", low = "white", guide = "colorbar") +
  scale_colour_hue(h = c(120, 240))

在此输入图片描述

或者,使用“填充”表示类别,使用“透明度”表示增长水平。

ggplot(df, aes(map_id = id)) +
  geom_map(aes(alpha = growth, fill = category), map =world.ggmap) +
  expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
  scale_alpha(range = c(0.2, 1), na.value = 1)

图片描述

这取决于你想要展示什么。

以防万一,这里是更改行大小的方法:

ggplot(df, aes(map_id = id)) +
 geom_map(aes(fill = growth, color = category, size = factor(1)), map =world.ggmap) +
 expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
 scale_fill_gradient(high = "red", low = "white", guide = "colorbar") +
 scale_colour_hue(h = c(120, 240)) + 
 scale_size_manual(values = 2, guide = FALSE)

这里是HSV版本:

df$hue <- ifelse(is.na(df$category), 0, as.numeric(df$category)/max(as.numeric(df$category), na.rm=T))
df$sat <- ifelse(is.na(df$growth), 0, df$growth/max(df$growth, na.rm=T))
df$fill <- ifelse(is.na(df$category), "grey50", hsv(df$hue, df$sat))

ggplot(df, aes(map_id = id)) +
 geom_map(aes(fill = fill), map =world.ggmap) +
 expand_limits(x = world.ggmap$long, y = world.ggmap$lat) +
 scale_fill_identity(guide = "none")

enter image description here


1
谢谢!问题在于让“足够粗”的线条即使在小图形打印时也能被注意到。 - Rasmus
1
我认为你要求过高了。我不认为在一张小纸上展示那么多信息是可能的。 - kohske
Alpha-proposal非常好!谢谢。它让我想到,最好的方法是为每个类别设置一个基本颜色,然后根据增长确定饱和度。这更或多或少是alpha所做的,特别是如果使用空白主题(或专门将bg设置为白色)。据您所知,有比您的alpha方法更直接的方法来获得此结果吗? - Rasmus
1
色调和饱和度的组合效果不错,我认为。ggplot2的未来版本可能会有这样的功能,即将色调、饱和度和明度作为单独的aes。无论如何,你可以通过手动设置来实现。我会发布更新。 - kohske
@kohske 如果您感兴趣,我在这里提出了一个相关问题(使用相同的示例):https://dev59.com/kGYs5IYBdhLWcg3wAfLO - Xu Wang
显示剩余3条评论

9

一种选择是将增长映射到在多边形重心绘制的某些点的大小。

centroids <- as.data.frame(coordinates(world.map))
df <- data.frame(df,centroids)

choropleth <-ggplot() +
     geom_map(aes(fill = category, map_id = id),data = df, map =world.ggmap) +
     expand_limits(x = world.ggmap$long, y = world.ggmap$lat) + 
    scale_fill_hue(na.value=NA)
choropleth



choropleth + geom_point(aes(x=V1,y=V2,size=growth),data=df) +
    scale_area(range=c(0,3))

在此输入图片描述

如果您真的想要将编码颜色加倍,您可以着色点。请注意,您还可以使用新的OpenStreetMap包添加卫星图像的光栅地图(厚颜无耻的广告)。

library(OpenStreetMap)
library(raster)
rastermap <- openmap(c(70,-179),
        c(-70,179),zoom=2,type='bing')
rastermap <- openproj(rastermap)
autoplot(rastermap,expand=FALSE) +
     geom_map(aes(x=70,y=70,fill = category, map_id = id),data = df,
        map =world.ggmap) +
     expand_limits(x = world.ggmap$long, y = world.ggmap$lat) + 
    scale_fill_hue(na.value=NA) + 
    geom_point(aes(x=V1,y=V2,colour=growth),data=df) +
    scale_colour_gradient(low = "red", high = "blue", 
        guide = "colorbar",na.value=NA)

enter image description here


Ian,你的程序包看起来很不错!它确实增添了一些亮点。加入alpha(ed)-fill可能会非常酷。顺便问一下:你是否知道ggmap程序包?根据摘要,它们听起来很相似。点的想法是一个好主意。通过使用星形或其他看起来不像墨水渍的东西,这可以变成一些漂亮的东西。谢谢! - Rasmus
我知道这个软件包。OpenStreetMap基本上替代了RGoogleMaps和ggmap两个软件包。它可以做很酷的事情,如瓷片缓存和地图投影转换。 - Ian Fellows
@IanFellows 如果您感兴趣,我刚刚在这里提出了一个相关问题(使用相同的示例):https://dev59.com/kGYs5IYBdhLWcg3wAfLO - Xu Wang

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