R ggplot2与shapefile和csv数据合并以填充特定的多边形

时间:2014-02-27 10:12:42

标签: r merge ggplot2 polygon

我知道这个问题已经回答elsewhere了。我试图按照@jlhoward的指示,但显然我的技能太有限了。我可以再次问你的帮助,R社区吗?

这就是我所拥有的:

瑞士的shapefile:Link

相应的CSV文件,包含市政名称及其邮政编码:Link

数据网站:cadastre.ch

上次热门投票的其他数据:Direct link, excel-file

我通过合并在CSV文件(wow.csv)(我要说明的数据)中添加一列。该文件现在看起来像这样:

Gemeinden   code    Ja.Anteil   Ortschaft       PLZ Zusatzziffer    Kantonskürzel   E   N
1   Aadorf  4551    78.78638    Aawangen        8522    2           TG            710206    263564
2   Aadorf  4551    78.78638    Ettenhausen TG  8356    0           TG            710129    259411
3   Aadorf  4551    78.78638    Aadorf          8355    0           TG            710588    261648
4   Aadorf  4551    78.78638    Guntershausen   8357    0           TG            711741    258934
5   Aadorf  4551    78.78638    Wittenwil       9547    0           TG            712002    262572

之后我尝试按照@jlhoward:

的说明操作
  1. 导入温度数据文件
  2. 导入市政的多边形shapefile
  3. muni多边形转换为数据框以进行绘图
  4. 加入ch12@datach12.df
  5. 的列
  6. 加入wowch12.df
  7. 的列
  8. 制作情节
  9. 我尝试使用以下代码:

    require("rgdal")
    require("maptools")
    require("ggplot2")
    require("plyr")
    
    # read share data and the file from cadastre.ch (zip-codes)
    asyl <- <- read.csv("~/FS14-1/PLZO_SHP_LV03/Asylgesetz_csv.csv", sep=";")
    mydata1 <- read.table("~/FS14-1/PLZO_SHP_LV03/PLZO_CSV_LV03.csv", sep=";", quote="\"")
    
    #merge the two files
    wow <- merge(x = asyl, y = mydata1, by = "Gemeinden", all = TRUE)
    
    # read municipality polygons
    ch12 <- readOGR(work.dir, layer = "PLZO_PLZ")
    
    # fortify and merge: muni.df is used in ggplot
    ch12@data$id <- rownames(ch12@data)
    ch12.df <- fortify(ch12)
    ch12.df <- join(ch12.df, ch12@data, by="id")
    ch12.df <- merge(ch12.df, wow, by="PLZ", all.x=T, a..ly=F)
    
    #create the map layers
    gp <- ggplot(data=ch12.df, aes(x=long, y=lat, group=group)) + 
          geom_polygon(aes(group = group))+         # draw polygons
          geom_path(color="grey", linestyle=2)+  # draw boundaries
          coord_equal() +
          scale_fill_gradient(low = "#ffffcc", high = "#ff4444", 
                                 space = "Lab", na.value = "grey50",
                                 guide = "colourbar")+
          labs(title="Zustimmung auf Gemeindelevel")
    gp
    

    好吧,直到最后一步,R工作(到目前为止,我可以告诉),但如果我尝试创建ggplot,我得到没有错误,R不知何故终止。我想要实现的是根据数据控制多边形的颜色(在我的市政情况下)......

    任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:6)

有点不清楚你要做什么,所以我需要做一些假设。

  1. 您的Excel文件在Gemeinden(市政府)的国家反对大规模移民倡议中有临时投票结果。所以我假设您想要一个等值线图,例如%YES。在下文中,我通过提取包含实际投票结果的2353行(第13行至第2365行),添加标题(从第11行开始)并保存为vote.csv来稍微清理Excel文件。 Ja in %列已重命名为Yes.Pct
  2. 您的shapefile按邮政编码(PLZ)组织(或多或少)。由于后面解释的各种原因,这产生了巨大的问题。所以我在谷歌上喋喋不休,几乎立即找到了由Swiss Federal Office of Topography市政府组织的形状文件。你必须“订购”文件here,但它是免费的 - 所以基本上你需要做的就是注册,他们会通过电子邮件向你发送文件链接。我使用的特定文件集是VEC200_Commune.*
  3. 来自地形局的文件的一个优点是它具有市政数字(大致相当于美国联邦政府使用的FIPS代码)。您的Excel文件也有这些数字(在Excel文件中称为Gemeinde-Nr.,在shapefile中称为BFSNR。基于这些id的匹配比尝试使用名称匹配要可靠得多。
  4. 所以将所有这些放在一起产生以下地图: 从这段代码:

    library(plyr)    # for join(...)
    library(rgdal)   # for readOGR(...)
    library(ggplot2)
    
    setwd("< directory with all files >")
    votes <- read.csv("vote.csv")
    map   <- readOGR(dsn=".",layer="VEC200_Commune")
    map   <- map[map$COUNTRY=="CH",]   # extract just Swiss Gemeinde
    
    data <- data.frame(id=rownames(map@data), 
                       GEMNAME=map@data$GEMNAME,
                       BFSNR=map@data$BFSNR)
    # convert id to char from factor
    data$id <- as.character(data$id)
    # merge vote data based on Gemeinden (different columns names in the two df...)
    data    <- merge(data,votes,by.x="BFSNR",by.y="Gemeinde.Nr.", all.x=T)
    
    map.df <- fortify(map)
    map.df <- join(map.df,data,by="id")
    ggplot(map.df, aes(long,lat, group=group))+
      geom_polygon(aes(fill=Yes.Pct))+
      coord_fixed()+
      scale_fill_gradient(low = "#ffffcc", high = "#ff4444", 
                          space = "Lab", na.value = "grey80",
                          guide = "colourbar")+
      labs(title="Zustimmung auf Gemeindelevel", x="", y="")+
      theme(axis.text=element_blank(),axis.ticks=element_blank())
    

    可以使用shapefile(基于邮政编码),但这会增加复杂性并且可能不可靠。有几个原因:

    1. 您的shapefile有4175个多边形,但只有3201个唯一邮政编码。这意味着许多PLZ都是重复的(或更糟)。你的PLZO_CSV_LV03.csv也是如此:PLZ不是唯一的。在PLZ上合并时,这是一个问题。例如,考虑根据公共列PLZ合并两个数据帧X和Y.如果X有一个给定PLZ的5行,而Y有3行具有相同的PLZ,那么结果将有15行与PLZ。
    2. 事实证明,合并两个 PLZ和Zusatzziffer改善了这种情况,但并没有完全消除重复(即,即使在考虑PLC和Zusatzziffer的组合时,也存在一些重复)。 / LI>
    3. 所有包含PLZ的文件都没有Gemeinde-Nr.,因此唯一的选择是根据Gemeindename合并投票数据。这是有风险的,因为通常名称在不同来源中拼写不完全相同。
    4. PLZ shapefile非常大,部分原因是多边形的数量(4175),部分原因是空间分辨率(例如每个多边形的点数更多)。结果,fortify(...)非常慢,甚至渲染地图本身也很慢。这可能就是你的R会话崩溃的原因。
    5. 考虑到所有这些警告,可以使用PLZ级shapefile生成以下地图: 使用此代码:

      votes    <- read.csv("vote.csv")
      zipcodes <- read.csv(sep=";","PLZO_CSV_LV03.csv")
      ch12 <- readOGR(dsn=".",layer="PLZO_PLZ")
      # associate id, PLZ, and Zusatzziffer
      data <- data.frame(id=rownames(ch12@data), 
                         PLZ=ch12@data$PLZ, 
                         Zusatzziffer=ch12@data$ZUSZIFF)
      # convert id to char from factor
      data$id <- as.character(data$id)
      # need to merge based on PLZ *and* Zusatzziffer
      data    <- merge(data,zipcodes[2:4],by=c("PLZ","Zusatzziffer"), all.x=T)
      # merge vote data based on Gemeinden (different columns names in the two df...)
      data    <- merge(data,votes,by.x="Gemeindename",by.y="Gemeinden", all.x=T)
      
      ch12.df <- fortify(ch12) 
      # join data to ch12.df based in id
      ch12.df <- join(ch12.df, data, by="id")
      
      gp <- ggplot(data=ch12.df, aes(x=long, y=lat, group=group)) + 
        geom_polygon(aes(fill = Yes.Pct))+    # draw polygons
        coord_equal() +
        scale_fill_gradient(low = "#ffffcc", high = "#ff4444", 
                            space = "Lab", na.value = "grey80",
                            guide = "colourbar")+
        labs(title="Zustimmung auf Gemeindelevel", x="", y="")+
        theme(axis.text=element_blank(),axis.ticks=element_blank())
      gp
      

      请注意,这两张地图相似,但不完全相同。我倾向于相信第一个,因为它是使用Gemeine Nr。而不是名称,因为它涉及较少的合并。