आर में KML फ़ाइल पढ़ना?


42

मैं बड़ी .kml फ़ाइलों (10 जीबी तक) के साथ काम कर रहा हूं और उन्हें आर में पढ़ने के लिए एक कुशल तरीके की आवश्यकता है। अब तक मैं उन्हें क्यूजीआईएस के माध्यम से आकार-प्रकार में परिवर्तित कर रहा हूं और फिर आर में पढ़ा जा सकता हूं। , वैसे, पूर्व की तुलना में ~ 1000 तेज है)। मैं आदर्श रूप से QGIS मध्यस्थ चरण को काटना चाहता हूं क्योंकि यह बोझिल और धीमा है।

सीधे पढ़ने के लिए .kml फ़ाइलें कैसे?

मैं देख रहा हूँ यह भी readOGR के साथ किया जा सकता है । दुर्भाग्य से, मैं यह नहीं देख सकता कि कैसे काम किए गए उदाहरण को लागू किया जाए (.kml फ़ाइल की लंबी तैयारी के बाद:) xx <- readOGR(paste(td, "cities.kml", sep="/"), "cities")। ऐसा लगता है कि यहाँ "शहर" स्थानिक वस्तुओं का नाम है।

रोजर बिवांड मानते हैं कि "यह कैसे पता चलता है कि यह नाम स्पष्ट नहीं है, क्योंकि 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 में परतें प्राप्त कर सकते हैं।
मारियो बेसेरा

जवाबों:


37

OGR ड्राइवर के साथ 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

अच्छी तरह से काम करता है।

अब, आप आरएमएल पार्सर का उपयोग करके केएमएल को एक्सएमएल के रूप में पार्स करके नाम प्राप्त कर सकते हैं, या हो सकता है कि आप आर को पाठ फ़ाइल के रूप में तब तक पढ़ने की कोशिश कर सकते हैं जब तक आपको नाम टैग नहीं मिलता।

अन्य दृष्टिकोण कमांड-लाइन ओग्रीनॉफ प्रोग्राम को चलाने के लिए है जो एक केएमएल फ़ाइल की परत नामों को बाहर निकालता है:

$ 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


आपके उत्तर के लिए धन्यवाद Spaced - सीधे समस्या को हल किया। यह इस तरह की स्पष्ट व्याख्या है जो मुझे स्टैक एक्सचेंज से प्यार करती है! एक 'बोनस बिंदु' प्रश्न: क्या मैं डेटा के सबसेट में पढ़ने के लिए एक ही कमांड का उपयोग कर सकता हूं (जैसे पहले 1 मिलियन पॉलीगॉन)? अन्यथा बाहरी किमी के साथ विशाल किमी को विभाजित करने के लिए देखेंगे।
रोबिनवेलवेल्स

2
KML XML को वास्तव में रैंडम एक्सेस के लिए डिज़ाइन नहीं किया गया है। वास्तविक समाधान अपने स्थानिक डेटा को एक स्थानिक डेटाबेस में रखना है, और गति के लिए कुछ स्थानिक सूचकांक हैं। PostGIS देखें।
स्पेन्डमैन

ठीक है अच्छी योजना - मैंने क्लाइंट को बताया है कि पोस्टगिस ऐसे बड़े डेटा के लिए आगे का रास्ता है, और मुझे यकीन है कि यह उस तरह की चीजों के लिए सही विकल्प है जो वह करना चाहता है। मेरे लिए अच्छा बहाना है इसे ठीक से सीखने के लिए!
रॉबिनवेल्स

एक फ़ाइल आधारित डेटाबेस, sqlite का स्थानिक विस्तार भी है , जिसके लिए आपको किसी सेवा को स्थापित करने की आवश्यकता नहीं होगी और PostGIS की तुलना में कम कॉन्फ़िगरेशन की आवश्यकता होगी।
फ्रैंक

काम करने के लिए systemR path.expandपर अजीब तरह से , भले ही यह कमांड लाइन पर unexpanded पथ पर ठीक काम किया (macOS; और समान पथ लौटा)~ogrinfoSys.which('ogrinfo')which ogrinfo
MichaelCirico

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"))

यहां आपको मुख्य स्थानिक बहुभुज वर्ग बनाने के लिए कुछ कदमों के माध्यम से जाने की आवश्यकता है।


हाय @ रानी, ​​मैंने आपके दृष्टिकोण की कोशिश की है लेकिन यह काम नहीं कर रहा है? मेरे पास एक त्रुटि है: बहुभुज (tkml) में त्रुटि: कोयर्स एक दो-कॉलम मैट्रिक्स> हेड (tkml) [[1]] [१] -878.1414१४१ ३०.४ ९ n०० adn होना चाहिए कि मेरे पास एक सूची है: क्या आपको लगता है कि यह ठीक है मैट्रिक्स के लिए निर्देशांक की सूची? तन्क्स!
माईका

1

अगर यह अभी भी किसी और के लिए एक समस्या है पता नहीं है, लेकिन मैं इस के साथ थोड़ी देर के लिए हलकों में चल रहा था। मेरे लिए आखिरकार क्या काम किया गया है। यह सही नोड XMLपर प्राप्त करने के लिए पैकेज का उपयोग करता है xmlValue। मुझे kml फ़ाइल के भीतर फ़ोल्डरों में से एक के नाम का layerपैरामीटर सेट करना था readOGR। जब मैंने layerkml फ़ाइल के पैरामीटर को सेट किया , तो मुझे वही त्रुटि मिलेगी जो ऊपर वर्णित रॉबिनवेल्स ने की थी।

नीचे दिखाए गए कोड लाइनें बहुत हैं जो केवल दिखाती हैं कि किमी डॉक्यूमेंट के विभिन्न नोड स्तर कैसे देखें। मुझे लगता है कि यह kml के स्रोत के आधार पर थोड़ा अलग होगा। लेकिन आपको सही पैरामीटर मान निर्धारित करने के लिए उसी तर्क का उपयोग करने में सक्षम होना चाहिए।

इसके अलावा, मैं kml फ़ाइलें की एक सूची है, तो यह आसानी से एक समारोह है कि एक में रखा जा सकता है में बनाया जा सकता है बनाया lapply- do.callजोड़ी। इसके बाद किमी लंबी फाइलों की लंबी सूची के आंकड़ों को खींचा जा सकता था। या, एक सिंगल किमी फ़ाइल के भीतर बहुत सारे सबफ़ोल्डर हैं क्योंकि ऐसा लगता है readOGRकि एक किमी फ़ाइल में कई सबफ़ोल्डर्स के साथ सौदा नहीं कर सकता है।

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

पता नहीं अगर मुझे अपना पिछला उत्तर संशोधित करना चाहिए था। शायद, लेकिन यह इस जवाब में नहीं कुछ चीजों को शामिल करता है, इसलिए मैंने इसे छोड़ने का फैसला किया।

वैसे भी, नीचे दिया गया कोड मेरे लिए अच्छा काम करता है। यह किमी फाइल में सभी xmlNodes की खोज करता है जिन्हें "फोल्डर" कहा जाता है और फिर उसी के layerपैरामीटर को सेट करता readOGRहै xmlValue। लगभग 6 अलग-अलग किमी फ़ाइलों के साथ कार्य निर्देशिका पर परीक्षण किया गया। आउटपुट आयातित 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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.