2014-02-13 82 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