【问题标题】:readOGR (rgdal) fails to fetch polygon names from XMLreadOGR (rgdal) 无法从 XML 中获取多边形名称
【发布时间】:2017-04-08 16:51:09
【问题描述】:

我正在尝试使用包rgdal 中的readOGR 函数将英格兰CCG 边界的KML 地图(Available here, 200Kb) 导入R。我的最终目标是通过根据一些相关值对 CCG 进行着色来创建热图。我有一个列表,其中包含一个数据框中 CCG 名称旁边的这些值。我需要将该数据框中的 CCG 名称与导入的地图对象中的 CCG 名称进行匹配,并根据该值分配颜色。但是,我看不到地图对象中导入的任何 CCG 名称,尽管它们存在于 KML 文件中。这就是我正在做的事情:

library(sp)
library(rgdal)
library(maps)
library(maptools)

假设 KML 文件位于工作目录中。 列出层:

ogrListLayers("Clinical_Commissioning_Groups_April_2016_Ultra_Generalised_Clipped_Boundaries_in_England.KML")

阅读OGRGeoJSON层:

ccg_boundaries <- ReadOGR("Clinical_Commissioning_Groups_April_2016_Ultra_Generalised_Clipped_Boundaries_in_England.KML","OGRGeoJSON")

R Studio 显示对象中有两个部分(正确的词?)。

polygons,其中包含每个多边形的数据,例如第一个:

> ccg_boundaries@polygons[1]
[[1]]
An object of class "Polygons"
Slot "Polygons":
[[1]]
An object of class "Polygon"
Slot "labpt":
[1] -2.104671 54.040320
Slot "area":
[1] 0.168067
...

还有data,有两个变量(NameDescription),我希望它们包含 CCG 名称,但它是空的:

> ccg_boundaries@data
    Name Description
0                   
1                   
2                   
3                   
4                   
5         

但是,CCG 名称存在于 KML 文件中,如果使用 Word 编辑器打开即可看到,例如按字母顺序排列的第一个是“NHS Airedale、Wharfedale 和 Craven”。

<PolyStyle><fill>0</fill></PolyStyle></Style>
    <ExtendedData><SchemaData schemaUrl="#OGRGeoJSON">
        <SimpleData name="objectid">1</SimpleData>
        <SimpleData name="ccg16cd">E38000001</SimpleData>
        <SimpleData name="ccg16nm">NHS Airedale, Wharfedale and Craven CCG</SimpleData>

是否有可能读取 OGR 或其他选项来提取它们并包含在对象中?

【问题讨论】:

    标签: r maps kml rgdal sp


    【解决方案1】:

    好的,如果有人遇到同样的问题,这是我找到的解决方案。

    该网站以两种格式提供地图:KML and SHP。我选择了 KML,因为它用于我正在遵循的一个工作示例中。但是这个特定的 KML 文件或它的生成方式似乎存在问题。我改用 Shapefile (SHP) 尝试了这个过程,它就像一个魅力。

    Shapefiles可以通过相同的函数读入R,但不需要指定层:

    ccg_boundaries <- ReadOGR("Clinical_Commissioning_Groups_April_2016_Ultra_Generalised_Clipped_Boundaries_in_England.SHP")
    

    CCG 名称现在位于 ccg16nm 变量中:

    > head(ccg_boundaries@data)
      objectid   ccg16cd                                 ccg16nm st_areasha st_lengths
    0        1 E38000001 NHS Airedale, Wharfedale and Craven CCG 1224636590  193149.74
    1        2 E38000002                         NHS Ashford CCG  582174805  122841.19
    2        3 E38000003                  NHS Aylesbury Vale CCG  984352696  229544.11
    3        4 E38000004            NHS Barking and Dagenham CCG   36315011   31196.87
    4        5 E38000005                          NHS Barnet CCG   86654018   41833.69
    5        6 E38000006                        NHS Barnsley CCG  327520495  106476.52
    

    【讨论】:

      【解决方案2】:

      您的问题是 windows 没有必要的库来从 KML 中提取 ExtendedData。
      我在这里提供了一个可行的解决方案:https://stackoverflow.com/a/51657844/2763996

      您的问题的解决方案是适用于您的示例 KML 的以下函数:

      library(tidyverse)
      library(xml2)
      library(rgdal)
      
      readKML <- function(file,keep_name_description=FALSE,layer,...) {
        # Set keep_name_description = TRUE to keep "Name" and "Description" columns
        #   in the resulting SpatialPolygonsDataFrame. Only works when there is
        #   ExtendedData in the kml file.
      
        sp_obj<-readOGR(file,layer,...)
        xml1<-read_xml(file)
        if (!missing(layer)) {
          different_layers <- xml_find_all(xml1, ".//d1:Folder") 
          layer_names <- different_layers %>% 
            xml_find_first(".//d1:name") %>% 
            xml_contents() %>% 
            xml_text()
      
          selected_layer <- layer_names==layer
          if (!any(selected_layer)) stop("Layer does not exist.")
          xml2 <- different_layers[selected_layer]
        } else {
          xml2 <- xml1
        }
      
        # extract name and type of variables
      
        variable_names1 <- 
          xml_find_first(xml2, ".//d1:ExtendedData") %>% 
          xml_children() 
      
        while(variable_names1 %>% 
              xml_attr("name") %>% 
              is.na() %>% 
              any()&variable_names1 %>%
              xml_children() %>% 
              length>0) variable_names1 <- variable_names1 %>%
          xml_children()
      
        variable_names <- variable_names1 %>%
          xml_attr("name") %>% 
          unique()
      
        # return sp_obj if no ExtendedData is present
        if (is.null(variable_names)) return(sp_obj)
      
        data1 <- xml_find_all(xml2, ".//d1:ExtendedData") %>% 
          xml_children()
      
        while(data1 %>%
              xml_children() %>% 
              length>0) data1 <- data1 %>%
          xml_children()
      
        data <- data1 %>% 
          xml_text() %>% 
          matrix(.,ncol=length(variable_names),byrow = TRUE) %>% 
          as.data.frame()
      
        colnames(data) <- variable_names
      
        if (keep_name_description) {
          sp_obj@data <- data
        } else {
          try(sp_obj@data <- cbind(sp_obj@data,data),silent=TRUE)
        }
        sp_obj
      }
      

      【讨论】:

        猜你喜欢
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 2020-11-10
        • 1970-01-01
        • 2020-10-27
        • 1970-01-01
        相关资源
        最近更新 更多