readOGR (rgdal) 无法从 XML 获取多边形名称
readOGR (rgdal) fails to fetch polygon names from XML
我正在尝试使用包 rgdal
中的 readOGR
函数将英格兰 (Available here, 200Kb) 的 CCG 边界 KML 地图导入 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
,有两个变量(Name
和 Description
),我希望它包含 CCG 名称,但它是空的:
> ccg_boundaries@data
Name Description
0
1
2
3
4
5
但是,CCG 名称存在于 KML 文件中,如果使用 Word 编辑器打开,则可以看到该文件,例如按字母顺序排列的第一个是 "NHS Airedale, Wharfedale and 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>
是否可以选择 readOGR 或其他一些选项来提取它们并将其包含在对象中?
好的,如果有人遇到同样的问题,这是我找到的解决方案。
网站提供两种格式的地图: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
您的问题是 windows 没有必要的库来从 KML 中提取 ExtendedData。
我在这里提供了一个可行的解决方案:
您的问题的解决方案是以下适用于您的示例 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
}
我正在尝试使用包 rgdal
中的 readOGR
函数将英格兰 (Available here, 200Kb) 的 CCG 边界 KML 地图导入 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
,有两个变量(Name
和 Description
),我希望它包含 CCG 名称,但它是空的:
> ccg_boundaries@data
Name Description
0
1
2
3
4
5
但是,CCG 名称存在于 KML 文件中,如果使用 Word 编辑器打开,则可以看到该文件,例如按字母顺序排列的第一个是 "NHS Airedale, Wharfedale and 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>
是否可以选择 readOGR 或其他一些选项来提取它们并将其包含在对象中?
好的,如果有人遇到同样的问题,这是我找到的解决方案。
网站提供两种格式的地图: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
您的问题是 windows 没有必要的库来从 KML 中提取 ExtendedData。
我在这里提供了一个可行的解决方案:
您的问题的解决方案是以下适用于您的示例 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
}