Je travaille avec d’énormes fichiers .kml (jusqu’à 10 Gb) et j’ai besoin d’un moyen efficace de les lire en R. Jusqu’à présent, je les ai convertis en fichiers de formes via QGIS, puis en R avec readShapePoly et readOGR (ce dernier Soit dit en passant, est environ 1000 fois plus rapide que l’ancien). J'aimerais idéalement couper le stade intermédiaire de QGIS car il est lourd et lent.
Comment lire les fichiers .kml directement?
Je vois que cela peut également être fait avec readOGR . Malheureusement, je ne vois pas comment implémenter l'exemple travaillé (après une longue préparation du fichier .kml:) xx <- readOGR(paste(td, "cities.kml", sep="/"), "cities")
. Il semble que "villes" soit le nom des objets spatiaux.
Roger Bivand admet que "la manière dont on découvre ce nom n’est pas évidente, car le pilote KML dans OGR en a besoin pour accéder au fichier. Une possibilité est:
system(paste("ogrinfo", paste(td, "cities.kml", sep="/")), intern=TRUE)
"
Mais cela ne fonctionne pas pour moi non plus. Voici un fichier test .kml pour l'essayer. Avec cela dans mon répertoire de travail, readOGR("x.kml", "id")
génère ce message d'erreur:
Error in ogrInfo(dsn = dsn, layer = layer, encoding = encoding, use_iconv = use_iconv) :
Cannot open layer .
Et system(paste("ogrinfo", "x.kml"), intern=TRUE)
génère:
[1] "Had to open data source read-only." "INFO: Open of `x.kml'"
[3] " using driver `KML' successful." "1: x (3D Polygon)"
, que je ne comprends tout simplement pas.
Est-ce que getKMLcoordinates
{} maptools être une alternative valable?
J'ai aussi essayé ceci:
tkml <- getKMLcoordinates(kmlfile="x.kml", ignoreAltitude=T)
head(tkml[[1]])
tkml <- SpatialPolygons(tkml,
proj4string=CRS("+init=epsg:3857"))
Les coordonnées sont générées correctement, mais ma tentative de les reconvertir en objet polygone a échoué avec le message suivant:
Error in SpatialPolygons(tkml, proj4string = CRS("+init=epsg:3857")) :
cannot get a slot ("area") from an object of type "double"
Réponses:
Pour lire un fichier KML avec le pilote OGR, vous devez lui donner le nom du fichier et le nom de la couche.
Selon le commentaire de Roger, le nom de la couche est masqué dans le fichier KML. Si vous ne savez pas comment le fichier KML a été créé, vous ne pouvez pas en déduire le nom de la couche à partir du nom du fichier KML.
En regardant votre exemple KML, je peux voir:
Ce qui me dit que le nom de la couche est
x
, pasid
, et ainsi:fonctionne bien.
Maintenant, vous pouvez essayer d'obtenir le nom en analysant le fichier KML au format XML à l'aide d'un analyseur syntaxique R, ou vous pouvez éventuellement essayer de le lire dans R sous forme de fichier texte jusqu'à ce que vous trouviez la balise name.
L’autre approche consiste à exécuter le programme ogrinfo en ligne de commande qui crache les noms de couche d’un fichier KML:
ici montrant qu'il existe une couche de polygone appelée
x
.la source
system
dans la R nécessairepath.expand
sur~
pourogrinfo
travailler, même si elle a bien fonctionné sur le chemin non déployée sur la ligne de commande (macOS,Sys.which('ogrinfo')
etwhich ogrinfo
retourné les mêmes chemins)Si vous souhaitez utiliser maptool de manière alternative, cela devrait fonctionner:
La clé ici est que vous devez suivre quelques étapes pour créer une classe de polygone spatial.
la source
Je ne sais pas si c'est toujours un problème pour quelqu'un d'autre, mais je tournais en rond pendant un moment avec ça. Ce qui a finalement fonctionné pour moi est ci-dessous. Il utilise le
XML
paquet pour obtenirxmlValue
le bon noeud. Je devais définir lelayer
paramètre dereadOGR
sur le nom de l'un des dossiers dans le fichier kml. Lorsque je règle lelayer
paramètre sur le fichier kml, j'obtiens la même erreur que RobinLovelace décrite ci-dessus.Vous trouverez ci-dessous un grand nombre de lignes de code qui montrent uniquement comment afficher les différents niveaux de nœud du document kml. Je pense que ce sera légèrement différent en fonction de la source du kml. Mais vous devriez pouvoir utiliser la même logique pour déterminer la valeur de paramètre correcte.
En outre, j'ai créé une liste de fichiers kml afin qu'il puisse être facilement transformé en une fonction qui pourrait être mis dans une
lapply
-do.call
deux. Cela pourrait alors extraire une donnée d'une longue liste de fichiers kml. Ou bien, un grand nombre de sous-dossiers dans un fichier kml unique, car il semblereadOGR
ne pas pouvoir gérer plusieurs sous-dossiers dans un fichier kml.la source
Je ne sais pas si j'aurais dû modifier ma réponse précédente. Peut-être, mais cela couvre des choses qui ne sont pas dans cette réponse, alors j'ai décidé de la laisser.
Quoi qu'il en soit, le code ci-dessous fonctionne bien pour moi. Il recherche tous les xmlNodes dans le fichier kml qui s'appellent "Dossier", puis définit le
layer
paramètre dereadOGR
àxmlValue
. Testé sur un répertoire de travail avec environ 6 fichiers kml distincts. La sortie est une liste d'objets SpatialDataFrames importés. Chaque SpatialDataFrame peut facilement être un sous-ensemble de la liste.N'adresse toujours pas les fichiers kml avec plusieurs nœuds de dossiers. Mais cette fonctionnalité pourrait facilement être ajoutée à une autre
apply
fonction imbriquée .la source