2014-02-13 43 views
13

我试图画出德国的等值线图,显示各州的贫困率(灵感来源于this question)。ggplot与有孔洞的多边形的等值线图

问题在于,一些州(例如柏林)完全被其他州(勃兰登堡州)包围,而且我无法让ggplot识别勃兰登堡的“洞”。

本示例的数据是here

library(rgdal) 
library(ggplot2) 
library(RColorBrewer) 

map <- readOGR(dsn=".", layer="germany3") 
pov <- read.csv("gerpoverty.csv") 

mrg.df <- data.frame(id=rownames([email protected]),[email protected]$ID_1) 
mrg.df <- merge(mrg.df,pov, by="ID_1") 
map.df <- fortify(map) 
map.df <- merge(map.df,mrg.df[,c("id","poverty")], by="id") 
ggplot(map.df, aes(x=long, y=lat, group=group)) + 
    geom_polygon(aes(fill=poverty))+ 
    geom_path(colour="grey50")+ 
    scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+ 
    labs(x="",y="")+ theme_bw()+ 
    coord_fixed() 

通告柏林和勃兰登堡颜色(东北)如何都是相同的。它们不应该是 - 柏林的贫困率远低于勃兰登堡。看起来ggplot正在渲染柏林多边形,然后渲染勃兰登堡多边形而没有洞。

如果我将电话号码改为geom_polygon(...),建议为here,我可以解决柏林/勃兰登堡问题,但现在三个最北端的州都不正确。

ggplot(map.df, aes(x=long, y=lat, group=group)) + 
    geom_polygon(aes(group=poverty, fill=poverty))+ 
    geom_path(colour="grey50")+ 
    scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+ 
    labs(x="",y="")+ theme_bw()+ 
    coord_fixed() 

我在做什么错?

+0

您是否尝试使用地图<-fortify(地图)为您的地图? http://docs.ggplot2.org/0.9.3.1/fortify.sp.html – Rentrop

+0

请参阅代码第8行:'map.df < - fortify(map)'。还是你的意思是别的? – jlhoward

+0

在https://github.com/hadley/ggplot2/wiki/plotting-polygon-shapefiles有一个针对此问题的解决方法的讨论和示例 – Ista

回答

9

您可以绘制在一个单独的层中的岛屿面,下面就以ggplot2 wiki的例子。我已经修改了你的合并步骤,以使它更容易些:

mrg.df <- data.frame(id=rownames([email protected]),[email protected]$ID_1) 
mrg.df <- merge(mrg.df,pov, by="ID_1") 
map.df <- fortify(map) 
map.df <- merge(map.df,mrg.df, by="id") 

ggplot(map.df, aes(x=long, y=lat, group=group)) + 
    geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+ 
    geom_polygon(aes(fill=poverty), color = "grey50", data =subset(map.df, Id1 %in% c("Berlin", "Bremen")))+ 
    scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+ 
    labs(x="",y="")+ theme_bw()+ 
    coord_fixed() 

map of germany

作为传道的不请自来的行为,我建议你考虑像

library(ggmap) 
qmap("germany", zoom = 6) + 
    geom_polygon(aes(x=long, y=lat, group=group, fill=poverty), 
       color = "grey50", alpha = .7, 
       data =subset(map.df, !Id1 %in% c("Berlin", "Bremen")))+ 
    geom_polygon(aes(x=long, y=lat, group=group, fill=poverty), 
       color = "grey50", alpha= .7, 
       data =subset(map.df, Id1 %in% c("Berlin", "Bremen")))+ 
    scale_fill_gradientn(colours=brewer.pal(5,"OrRd")) 

提供上下文和熟悉参考点。

1

或者,您可以使用rworldmap创建该地图。

library(rworldmap) 
library(RColorBrewer) 
library(rgdal) 

map <- readOGR(dsn=".", layer="germany3") 
pov <- read.csv("gerpoverty.csv") 

#join data to the map 
sPDF <- joinData2Map(pov,nameMap='map',nameJoinIDMap='VARNAME_1',nameJoinColumnData='Id1') 

#default map 
#mapPolys(sPDF,nameColumnToPlot='poverty') 

colours=brewer.pal(5,"OrRd") 
mapParams <- mapPolys(sPDF 
         ,nameColumnToPlot='poverty' 
         ,catMethod="pretty" 
         ,numCats=5 
         ,colourPalette=colours 
         ,addLegend=FALSE) 


do.call(addMapLegend, c(mapParams 
          , legendLabels="all" 
          , legendWidth=0.5 
         )) 

#to test state names 
#text(pov$x,pov$y,labels=pov$Id1) 

German poverty map created using rworldmap

+0

谢谢,但它不是关于这个特定的地图。我试图找出这是ggplot中的错误,还是我做错了什么。 – jlhoward

13

这仅仅是@ Ista答案的扩展,它不需要知道哪些州(柏林,不来梅)需要最后呈现。

该方法利用了fortify(...)生成列hole的事实,该列识别一组坐标是否为空洞。因此,这使得在没有孔的区域之前(例如在其下面)全部区域(id's)和任何孔。

非常感谢@Ista,没有她的答案我不能想出这个(相信我,我花了好几个小时尝试......))

ggplot(map.df, aes(x=long, y=lat, group=group)) + 
    geom_polygon(data=map.df[map.df$id %in% map.df[map.df$hole,]$id,],aes(fill=poverty))+ 
    geom_polygon(data=map.df[!map.df$id %in% map.df[map.df$hole,]$id,],aes(fill=poverty))+ 
    geom_path(colour="grey50")+ 
    scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+ 
    labs(x="",y="")+ theme_bw()+ 
    coord_fixed() 

+0

@jhoward - 我实际上已经尝试过,并且没有为我的原始答案做这件事。我以为'geom_polygon(data = map.df [!map.df $ hole,],aes(fill =贫穷))'应该可以工作,并且感到沮丧的是它没有。很高兴看到你的解决方案。 – Ista

+0

@jhoward非常感谢这个辉煌的解决方案! – ikashnitsky

2

只需添加其他小改进@土改的和@ jhoward的回答(非常感谢你的帮助!)。

@jhoward的修改可以很容易地裹在一个小功能这样

gghole <- function(fort){ 
     poly <- fort[fort$id %in% fort[fort$hole,]$id,] 
     hole <- fort[!fort$id %in% fort[fort$hole,]$id,] 
     out <- list(poly,hole) 
     names(out) <- c('poly','hole') 
     return(out) 
} 
# input has to be a fortified data.frame 

然后,一个并不需要召回如何提取孔信息,每隔一次。代码看起来像

ggplot(map.df, aes(x=long, y=lat, group=group)) + 
      geom_polygon(data=gghole(map.df)[[1]],aes(fill=poverty),colour="grey50")+ 
      geom_polygon(data=gghole(map.df)[[2]],aes(fill=poverty),colour="grey50")+ 
    # (optionally). Call by name 
    #   geom_polygon(data=gghole(map.df)$poly,aes(fill=poverty),colour="grey50")+ 
    #   geom_polygon(data=gghole(map.df)$hole,aes(fill=poverty),colour="grey50")+ 
      scale_fill_gradientn(colours=brewer.pal(5,"OrRd"))+ 
      labs(x="",y="")+ theme_bw()+ 
      coord_fixed() 
+1

缩短版本:ggpolyhole < - function(fort,poly = TRUE){ idx < - fort $ id%in%fort [fort $ hole,] $ id fort [idx - poly,] } –

+0

@PolorBear this一个没有为我工作 – ikashnitsky