Pracuję z dużymi plikami .kml (do 10 Gb) i potrzebuję wydajnego sposobu na ich odczytanie do R. Do tej pory przekształcałem je w pliki shapefile za pomocą QGIS, a następnie z powrotem w R z readShapePoly i readOGR (ten ostatni , nawiasem mówiąc, jest ~ 1000 szybszy niż poprzedni). Idealnie chciałbym wyciąć etap pośredni QGIS, ponieważ jest on uciążliwy i powolny.
Jak odczytywać bezpośrednio pliki .kml?
I zobaczyć można również dokonać z readOGR . Niestety nie widzę sposobu wdrożenia działającego przykładu (po długim przygotowaniu pliku .kml:) xx <- readOGR(paste(td, "cities.kml", sep="/"), "cities")
. Wydaje się, że „miasta” to tutaj nazwy obiektów przestrzennych.
Roger Bivand przyznaje, że „odkrycie tej nazwy nie jest oczywiste, ponieważ sterownik KML w OGR potrzebuje go do uzyskania dostępu do pliku. Jedną z możliwości jest:
system(paste("ogrinfo", paste(td, "cities.kml", sep="/")), intern=TRUE)
„
Ale to też nie działa dla mnie. Oto testowy plik .kml do wypróbowania. Z tym w moim katalogu roboczym readOGR("x.kml", "id")
generuje ten komunikat o błędzie:
Error in ogrInfo(dsn = dsn, layer = layer, encoding = encoding, use_iconv = use_iconv) :
Cannot open layer .
I system(paste("ogrinfo", "x.kml"), intern=TRUE)
generuje:
[1] "Had to open data source read-only." "INFO: Open of `x.kml'"
[3] " using driver `KML' successful." "1: x (3D Polygon)"
, którego po prostu nie rozumiem.
Czy getKMLcoordinates
{maptools} byłoby prawidłową alternatywą?
Próbowałem także:
tkml <- getKMLcoordinates(kmlfile="x.kml", ignoreAltitude=T)
head(tkml[[1]])
tkml <- SpatialPolygons(tkml,
proj4string=CRS("+init=epsg:3857"))
Współrzędne są generowane poprawnie, ale moja próba przekształcenia ich z powrotem w obiekt wieloboku nie powiodła się z następującym komunikatem:
Error in SpatialPolygons(tkml, proj4string = CRS("+init=epsg:3857")) :
cannot get a slot ("area") from an object of type "double"
Odpowiedzi:
Aby odczytać plik KML za pomocą sterownika OGR, podaj mu nazwę pliku i nazwę warstwy.
Komentarz Rogera jest taki, że nazwa warstwy jest ukryta w pliku KML, i jeśli nie wiesz, jak KML został utworzony, nie możesz wywnioskować nazwy warstwy na podstawie nazwy pliku KML.
Patrząc na twój przykładowy KML, widzę:
Co mówi mi, że nazwa warstwy to
x
: nieid
, a więc:działa ładnie.
Teraz można spróbować uzyskać nazwę przez parsowania KML jako XML przy użyciu parsera XML R, można też może spróbować go czytać w R jako plik tekstowy, aż znajdziesz plakietkę.
Inne podejście polega na uruchomieniu programu ogrinfo z linii poleceń, który wyrzuca nazwy warstw pliku KML:
tutaj pokazano, że istnieje warstwa wielokąta o nazwie
x
.źródło
system
w badania potrzebnepath.expand
na~
naogrinfo
do pracy, mimo że pracował dobrze na nierozszerzonym ścieżki w linii poleceń (MacOS;Sys.which('ogrinfo')
iwhich ogrinfo
wrócił te same ścieżki)Jeśli chcesz zrobić alternatywny sposób za pomocą maptool, powinno to działać:
Kluczem tutaj jest to, że musisz przejść kilka kroków, aby stworzyć klasę wielokąta przestrzennego.
źródło
Nie wiem, czy to nadal stanowi problem dla kogokolwiek innego, ale przez jakiś czas biegałem w kółko. Co w końcu dla mnie zadziałało, poniżej. Używa
XML
pakietu, aby dostać sięxmlValue
do właściwego węzła. Musiałem ustawićlayer
parametrreadOGR
na nazwę jednego z folderów w pliku kml. Gdylayer
ustawię parametr na plik kml, otrzymam ten sam błąd, co RobinLovelace opisany powyżej.Poniżej pokazano wiele linii kodu, które pokazują tylko, jak zobaczyć różne poziomy węzłów dokumentu kml. Myślę, że będzie to nieco inne w zależności od źródła kml. Ale powinieneś być w stanie użyć tej samej logiki, aby określić poprawną wartość parametru.
Ponadto, stworzyłem listę plików KML więc może być łatwo przekształcony funkcji, które można umieścić w
lapply
-do.call
pary. Może to następnie pobrać dane z długiej listy plików kml. Lub wiele podfolderów w jednym pliku kml, jak się wydaje,readOGR
nie radzi sobie z wieloma podfolderami w pliku kml.źródło
Nie wiem, czy powinienem zmodyfikować poprzednią odpowiedź. Być może, ale dotyczy to niektórych kwestii, których nie ma w tej odpowiedzi, więc postanowiłem to zostawić.
W każdym razie poniższy kod działa dla mnie dobrze. Wyszukuje wszystkie xmlNodes w pliku kml o nazwie „Folder”, a następnie ustawia
layer
parametrreadOGR
na toxmlValue
. Testowany na katalogu roboczym z około 6 oddzielnymi plikami kml. Dane wyjściowe to lista importowanych obiektów SpatialDataFrames. Każdy SpatialDataFrame może być łatwo podzbiór z listy.Nadal nie adresuje plików kml z wieloma węzłami folderów. Ale tę funkcję można łatwo dodać za pomocą innej
apply
funkcji zagnieżdżonej .źródło