KML 파일을 R로 읽으시겠습니까?


41

나는 거대한 .kml 파일 (최대 10Gb)로 작업하고 있으며 R로 읽을 수있는 효율적인 방법이 필요합니다. 지금까지 QGIS를 통해 shapefiles로 변환 한 다음 readShapePoly 및 readOGR (후자)을 사용하여 R로 다시 변환했습니다 그건 그렇고, 전자보다 ~ 1000 빠릅니다). QGIS 중개 단계가 번거롭고 느리기 때문에 잘라내는 것이 이상적입니다.

.kml 파일을 직접 읽는 방법은 무엇입니까?

나는 이 또한 readOGR와 함께 할 수 있습니다 참조 . 불행히도 (.kml 파일을 오랜 시간 준비한 후) 작동하는 예제를 구현하는 방법을 알 수 없습니다 xx <- readOGR(paste(td, "cities.kml", sep="/"), "cities"). 여기서 "도시"는 공간 객체의 이름 인 것 같습니다.

Roger Bivand는 OGR의 KML 드라이버가 파일에 액세스해야하기 때문에이 이름을 발견하는 방법은 분명하지 않습니다. 한 가지 가능성은 다음과 같습니다.

system(paste("ogrinfo", paste(td, "cities.kml", sep="/")), intern=TRUE)

"

그러나 이것은 나에게도 효과가 없습니다. 다음은 테스트 .kml 파일입니다. 내 작업 디렉토리 readOGR("x.kml", "id")에이 오류 메시지가 생성됩니다.

Error in ogrInfo(dsn = dsn, layer = layer, encoding = encoding, use_iconv = use_iconv) : 
  Cannot open layer . 

그리고 다음을 system(paste("ogrinfo", "x.kml"), intern=TRUE)생성합니다.

[1] "Had to open data source read-only."   "INFO: Open of `x.kml'"               
[3] "      using driver `KML' successful." "1: x (3D Polygon)"  

이해가 안됩니다.

겠습니까 getKMLcoordinates{maptools}는 유효한 대안이 될?

나는 또한 이것을 시도했다 :

tkml <- getKMLcoordinates(kmlfile="x.kml", ignoreAltitude=T)
head(tkml[[1]])
tkml <- SpatialPolygons(tkml, 
                        proj4string=CRS("+init=epsg:3857"))

좌표가 올바르게 생성되었지만 다각형 메시지로 다시 변환하려는 시도가 다음 메시지와 함께 실패했습니다.

Error in SpatialPolygons(tkml, proj4string = CRS("+init=epsg:3857")) : 
  cannot get a slot ("area") from an object of type "double"

1
rgdal의 함수 ogrListLayers를 사용하여 kml의 레이어를 얻을 수 있습니다.
마리오 Becerra

답변:


36

OGR 드라이버로 KML을 읽으려면 파일 이름과 레이어 이름을 지정하십시오.

Roger의 의견에 따르면 레이어 이름은 KML 파일에 숨겨져 있으며 KML 생성 방법을 알지 못하면 KML 파일 이름에서 레이어 이름을 유추 할 수 없습니다.

KML의 예를 보면 다음을 볼 수 있습니다.

<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document><Folder><name>x</name>
<Schema name="x" id="x">

레이어 이름이 x아니라고 알려줍니다 id.

> foo = readOGR("/tmp/x.kml", "x")
OGR data source with driver: KML 
Source: "/tmp/x.kml", layer: "x"
with 1 features and 2 fields
Feature type: wkbPolygon with 2 dimensions

잘 작동합니다.

지금, 당신은 노력과 R의 XML 파서를 사용하여 XML로 KML을 분석하여 이름을 얻거나 당신은 할 수 있습니다 어쩌면 당신은 이름 태그를 찾을 때까지 텍스트 파일로 R에서 그것을 읽어보세요.

다른 방법은 KML 파일의 레이어 이름을 뱉어내는 명령 줄 ogrinfo 프로그램을 실행하는 것입니다.

$ ogrinfo /tmp/x.kml 
Had to open data source read-only.
INFO: Open of `/tmp/x.kml'
      using driver `KML' successful.
1: x (Polygon)

여기에라는 폴리곤 레이어가 있음을 보여줍니다 x.


답변 주셔서 감사합니다 간격-문제를 즉시 해결했습니다. 스택 교환을 좋아하게 만드는 이와 같은 명확한 설명입니다! 하나의 '보너스 포인트'질문 : 동일한 명령을 사용하여 데이터의 하위 집합 (예 : 첫 번째 100 만 다각형)을 읽을 수 있습니까? 그렇지 않으면 외부 프로그램으로 거대한 kmls를 분할하는 것을 볼 것입니다.
RobinLovelace

2
XML 인 KML은 실제로 임의 액세스 용으로 설계되지 않았습니다. 실제 솔루션은 공간 데이터를 공간 데이터베이스에 저장하고 속도를위한 공간 인덱스를 갖는 것입니다. PostGIS를 확인하십시오.
Spacedman

괜찮은 계획-고객에게 PostGIS가 그러한 빅 데이터를 향한 길이라고 말했으며, 그가 원하는 종류의 작업에 적합한 옵션이라고 확신합니다. 제대로 배워야 할 좋은 변명!
RobinLovelace

또한 파일 기반 데이터베이스 인 sqlite공간 확장 기능이 있어 서비스를 설치할 필요가 없으며 PostGIS보다 구성이 덜 필요합니다.
Frank

이상하게 systemR의 필요 path.expand~대한 ogrinfo(; 맥 OS를 명령 줄에 확장되지 않은 경로에 벌금을했다하더라도, 작업을 Sys.which('ogrinfo')하고 which ogrinfo같은 경로를 반환)
MichaelChirico

5

maptool을 사용하여 다른 방법을 원한다면 다음과 같이 작동합니다.

tkml <- getKMLcoordinates(kmlfile="yourkml.kml", ignoreAltitude=T)
#make polygon
p1 = Polygon(tkml)
#make Polygon class
p2 = Polygons(list(p1), ID = "drivetime")
#make spatial polygons class
p3= SpatialPolygons(list(p2),proj4string=CRS("+init=epsg:4326"))

여기서 핵심은 공간 폴리곤 클래스를 만들기 위해 몇 단계를 거쳐야한다는 것입니다.


안녕 @ 본, 귀하의 접근 방식을 시도했지만 작동하지 않는 것 같습니다? 오류가 발생했습니다. Polygon (tkml) 오류 : 좌표는 2 열 행렬이어야합니다.> head (tkml) [[1]] [1] -87.88141 30.49800 adn 목록으로 가지고 있습니다. 행렬 좌표 목록? tahnks!
maycca

1

이것이 여전히 다른 사람에게 문제가되는지 모르겠지만, 잠시 동안 서클에서 달리고있었습니다. 마침내 나를 위해 일한 것은 다음과 같습니다. XML패키지를 사용하여 xmlValue올바른 노드 를 얻습니다 . kml 파일 내의 폴더 중 하나의 이름으로 layer매개 변수 를 설정해야했습니다 readOGR. layerkml 파일 의 매개 변수를 설정하면 위에서 설명한 RobinLovelace와 동일한 오류가 발생합니다.

아래는 kml 문서의 다양한 노드 레벨을 보는 방법 만 보여주는 많은 코드 라인입니다. kml의 출처에 따라 약간 다를 것이라고 생각합니다. 그러나 동일한 논리를 사용하여 올바른 매개 변수 값을 결정할 수 있어야합니다.

그것은 쉽게에 넣어 수있는 기능으로 할 수 있도록 또한, 나는 KML 파일의 목록을 생성 lapply- do.call쌍. 그러면 긴 kml 파일 목록에서 데이터를 가져올 수 있습니다. 또는 kml 파일의 readOGR여러 하위 폴더를 처리 할 수 ​​없기 때문에 단일 kml 파일 내에 많은 하위 폴더가 있습니다.

library(rgdal); library(XML)

# SET WORKING DIRECTORY FIRST!!
dir <- getwd()

kmlfilelist <- list.files(dir, pattern =".kml$", full.names=TRUE, recursive=FALSE)

doc0 <- xmlTreeParse(kmlfilelist[2], useInternal = TRUE)
rootNode0 <- xmlRoot(doc0)
rootName0 <- xmlName(rootNode0)
element1Name0 <- names(rootNode0)

nodeNames <- names(rootNode0[1][[1]])

# entire rootNode - kml Document level
rootNode0[[1]]

# 1st element of rootNode - kml file name
rootNode0[[1]][[1]] 

# 2nd element of rootNode - kml Style Map 
rootNode0[[1]][[2]] 

# 3rd element of rootNode - Style
rootNode0[[1]][[3]]

# 4th element of rootNode - Style
rootNode0[[1]][[4]] 

# 5th element of rootNode - kml Folder with data in it.
rootNode0[[1]][[5]] 

# 5th element 1st subelement of rootNode - kml Folder name with data in it. 
#  What to set readOGR() layer parameter to.
rootNode0[[1]][[5]][[1]] 

kmlfoldername <- xmlValue(rootNode0[[1]][[5]][[1]]) # Folder name to set = layer.

readOGR(dsn=kmlfilelist[2], layer =  kmlfoldername)

0

이전 답변을 수정했는지 모르겠습니다. 아마도, 그러나 그것은이 답변에없는 것들을 다루므로, 나는 그것을 떠나기로 결정했습니다.

어쨌든 아래 코드는 저에게 효과적입니다. kml 파일에서 "Folder"라는 모든 xmlNode를 찾은 다음 layer매개 변수를 readOGR로 설정합니다 xmlValue. 약 6 개의 별도 kml 파일이있는 작업 디렉토리에서 테스트되었습니다. 출력은 가져온 SpatialDataFrames 객체의 목록입니다. 각 SpatialDataFrame은 목록에서 쉽게 하위 집합이 될 수 있습니다.

여러 폴더 노드가있는 kml 파일은 여전히 ​​해결되지 않습니다. 그러나이 기능은 다른 중첩 apply함수를 사용 하여 쉽게 추가 할 수 있습니다 .

library(rgdal); library(XML)

# SET WORKING DIRECTORY FIRST!!
dir <- getwd()

kmlfilelist <- list.files(dir, pattern =".kml$", full.names=TRUE, recursive=FALSE)

ImportKml <- function (kmlfile) {
  doc0 <- xmlTreeParse(kmlfile, useInternal = TRUE)
  rootNode0 <- xmlRoot(doc0)
  rootName0 <- xmlName(rootNode0)
  element1Name0 <- names(rootNode0)

  kmlNodeNames <- unname(names(rootNode0[1][[1]]))
  kmlFolderNodeNum <- which(kmlNodeNames == "Folder")
  kmlFolderNodeName <- xmlValue(rootNode0[[1]][[kmlFolderNodeNum]][[1]])

  kmlIn <- readOGR(dsn=kmlfile, layer = kmlFolderNodeName)
}
ImportedKmls <- lapply(kmlfilelist, ImportKml)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.