Ich arbeite mit riesigen .kml-Dateien (bis zu 10 GB) und brauche eine effiziente Methode, um sie in R zu lesen. Bisher habe ich sie über QGIS in Shapefiles konvertiert und dann mit readShapePoly und readOGR (letzteres) wieder in R ist übrigens ~ 1000 schneller als die erstere). Ich möchte die QGIS-Zwischenstufe idealerweise streichen, da sie umständlich und langsam ist.
Wie lese ich .kml-Dateien direkt ein?
Ich sehe, dass dies auch mit readOGR möglich ist . Leider kann ich nicht sehen, wie das Beispiel implementiert wird (nach langwieriger Vorbereitung der .kml-Datei:) xx <- readOGR(paste(td, "cities.kml", sep="/"), "cities")
. Es scheint, dass "Städte" hier der Name der räumlichen Objekte ist.
Roger Bivand gibt zu, dass "es nicht offensichtlich ist, wie man diesen Namen entdeckt, da der KML-Treiber in OGR ihn benötigt, um auf die Datei zuzugreifen. Eine Möglichkeit ist:
system(paste("ogrinfo", paste(td, "cities.kml", sep="/")), intern=TRUE)
"
Aber das funktioniert auch bei mir nicht. Hier ist eine .kml-Testdatei zum Anprobieren . readOGR("x.kml", "id")
Generiert in meinem Arbeitsverzeichnis die folgende Fehlermeldung:
Error in ogrInfo(dsn = dsn, layer = layer, encoding = encoding, use_iconv = use_iconv) :
Cannot open layer .
Und system(paste("ogrinfo", "x.kml"), intern=TRUE)
generiert:
[1] "Had to open data source read-only." "INFO: Open of `x.kml'"
[3] " using driver `KML' successful." "1: x (3D Polygon)"
, was ich einfach nicht verstehe.
Wäre getKMLcoordinates
{maptools} eine gültige Alternative?
Ich habe es auch versucht:
tkml <- getKMLcoordinates(kmlfile="x.kml", ignoreAltitude=T)
head(tkml[[1]])
tkml <- SpatialPolygons(tkml,
proj4string=CRS("+init=epsg:3857"))
Die Koordinaten werden korrekt generiert, aber mein Versuch, sie wieder in ein Polygonobjekt umzuwandeln, schlug mit der folgenden Meldung fehl:
Error in SpatialPolygons(tkml, proj4string = CRS("+init=epsg:3857")) :
cannot get a slot ("area") from an object of type "double"
Antworten:
Um eine KML mit dem OGR-Treiber zu lesen, geben Sie den Dateinamen und den Layernamen an.
Rogers Kommentar ist, dass der Ebenenname in der KML-Datei verborgen ist. Wenn Sie nicht wissen, wie die KML erstellt wurde, können Sie den Ebenennamen nicht aus dem KML-Dateinamen ableiten.
In Ihrem Beispiel-KML sehe ich:
Was mir sagt, dass der Ebenenname
x
nichtid
ist und so:funktioniert gut.
Jetzt können Sie versuchen, den Namen zu erhalten , indem die KML als XML - Parsing eines R XML - Parser verwenden, oder Sie können vielleicht versuchen , es in R als Textdatei zu lesen , bis Sie das Namensschild zu finden.
Der andere Ansatz besteht darin, das Befehlszeilenprogramm ogrinfo auszuführen, das die Ebenennamen einer KML-Datei ausgibt:
Hier wird angezeigt, dass es eine Polygonebene mit dem Namen gibt
x
.quelle
system
in R benötigtpath.expand
auf~
fürogrinfo
zu arbeiten, auch wenn es in Ordnung auf dem nicht ausgedehnten Weg auf der Kommandozeile gearbeitet (macOS;Sys.which('ogrinfo')
undwhich ogrinfo
wieder die gleichen Pfade)Wenn Sie MapTool alternativ verwenden möchten, sollte dies funktionieren:
Der Schlüssel hier ist, dass Sie einige Schritte durchlaufen müssen, um eine räumliche Polygonklasse zu erstellen.
quelle
Ich weiß nicht, ob das für irgendjemanden noch ein Problem ist, aber ich bin eine Weile damit im Kreis gelaufen. Was schließlich für mich funktioniert hat, ist unten. Es verwendet das
XML
Paket, umxmlValue
den richtigen Knoten zu finden. Ich musste denlayer
Parameter vonreadOGR
auf den Namen des einen Ordners in der kml-Datei setzen. Wenn ich denlayer
Parameter auf die der kml-Datei setze, erhalte ich den gleichen Fehler, den RobinLovelace oben beschrieben hat.Unten sind viele Codezeilen dargestellt, die nur zeigen, wie die verschiedenen Knotenebenen des kml-Dokuments angezeigt werden. Ich denke, das wird etwas anders sein, abhängig von der Quelle des kml. Sie sollten jedoch die gleiche Logik verwenden können, um den richtigen Parameterwert zu ermitteln.
Außerdem habe ich eine Liste von KML - Dateien , so dass es leicht in eine Funktion gemacht werden könnten , die in einem genommen werden konnte
lapply
-do.call
Paar. Dadurch könnten Daten aus einer langen Liste von kml-Dateien abgerufen werden. Oder viele Unterordner in einer einzelnen kml-Datei können anscheinendreadOGR
nicht mit mehreren Unterordnern in einer kml-Datei umgehen.quelle
Ich weiß nicht, ob ich meine vorherige Antwort hätte ändern sollen. Vielleicht, aber das deckt einige Dinge nicht in dieser Antwort ab, also habe ich beschlossen, es zu verlassen.
Wie auch immer, der folgende Code funktioniert gut für mich. Es sucht nach allen xmlNodes in der kml-Datei, die als "Ordner" bezeichnet werden, und setzt den
layer
ParameterreadOGR
daraufxmlValue
. Getestet auf Arbeitsverzeichnis mit ungefähr 6 unterschiedlichen kml Akten. Die Ausgabe ist eine Liste der importierten SpatialDataFrames-Objekte. Jeder SpatialDataFrame kann einfach aus der Liste ausgewählt werden.Kml-Dateien mit mehreren Ordnerknoten werden immer noch nicht angesprochen. Diese Funktion kann jedoch problemlos mit einer anderen verschachtelten
apply
Funktion hinzugefügt werden.quelle