अधिक कुशल स्थानिक बिना QGIS, ArcGIS, PostGIS, आदि के पायथन में शामिल होते हैं


31

मैं यहाँ उदाहरण की तरह एक स्थानिक जुड़ने का प्रयास कर रहा हूँ: क्या "स्थान द्वारा विशेषताओं में शामिल होने" का एक अजगर विकल्प है? । हालाँकि, यह दृष्टिकोण वास्तव में अक्षम / धीमा लगता है। यहां तक ​​कि इसे एक मामूली 250 अंक के साथ चलाने में लगभग 2 मिनट लगते हैं और यह 1,000 अंकों के साथ पूरी तरह से आकार में विफल हो जाता है। क्या एक बेहतर दृष्टिकोण है? मैं आर्कगिस, क्यूजीआईएस, आदि का उपयोग किए बिना इसे पूरी तरह से पायथन में करना चाहता हूं।

मुझे यह जानने में भी रुचि होगी कि क्या यह संभव है कि सभी बिंदुओं के गुण (अर्थात जनसंख्या) एक बहुभुज के भीतर आते हैं और उस मात्रा को बहुभुज के आकार के साथ जोड़ दें।

यहां वह कोड है जिसे मैं बदलने की कोशिश कर रहा हूं। मुझे लाइन 9 पर एक त्रुटि मिलती है:

poly['properties']['score'] += point['properties']['score']

जो कहते हैं:

TypeError: असमर्थित ऑपरेंड प्रकार (ओं) के लिए + =: 'noneType' और 'float'।

यदि मैं "=" को "=" से प्रतिस्थापित करता हूं तो यह ठीक चलता है लेकिन यह खेतों को समेटता नहीं है। मैंने इन्हें पूर्णांक बनाने की भी कोशिश की है, लेकिन यह भी विफल है।

with fiona.open(poly_shp, 'r') as n: 
  with fiona.open(point_shp,'r') as s:
    outSchema = {'geometry': 'Polygon','properties':{'region':'str','score':'float'}}
    with fiona.open (out_shp, 'w', 'ESRI Shapefile', outSchema, crs) as output:
        for point in s:
            for poly in n:
                if shape(point['geometry']).within(shape(poly['geometry'])):  
                    poly['properties']['score']) += point['properties']['score'])
                    output.write({
                        'properties':{
                            'region':poly['properties']['NAME'],
                            'score':poly['properties']['score']},
                        'geometry':poly['geometry']})

मुझे लगता है कि आपको अपने दूसरे प्रश्न को यहां से संपादित करना चाहिए, ताकि जो मैं मानता हूं वह आपके लिए अधिक महत्वपूर्ण प्रश्न हो। दूसरे पर शोध किया जा सकता है / अलग से पूछा जा सकता है।
PolyGeo

जवाबों:


37

फियोना ने पायथन शब्दकोशों को वापस किया और आप poly['properties']['score']) += point['properties']['score'])एक शब्दकोश के साथ उपयोग नहीं कर सकते ।

माइक टी द्वारा दिए गए संदर्भों का उपयोग करके सारांश विशेषताओं का उदाहरण:

यहां छवि विवरण दर्ज करें

# read the shapefiles 
import fiona
from shapely.geometry import shape
polygons = [pol for pol in fiona.open('poly.shp')]
points = [pt for pt in fiona.open('point.shp')]
# attributes of the polygons
for poly in polygons:
   print poly['properties'] 
OrderedDict([(u'score', 0)])
OrderedDict([(u'score', 0)])
OrderedDict([(u'score', 0)])

# attributes of the points
for pt in points:
    print i['properties']
 OrderedDict([(u'score', 1)]) 
 .... # (same for the 8 points)

अब, हम एक स्थानिक सूचकांक के साथ या उसके बिना दो तरीकों का उपयोग कर सकते हैं:

1) बिना

# iterate through points 
for i, pt in enumerate(points):
     point = shape(pt['geometry'])
     #iterate through polygons
     for j, poly in enumerate(polygons):
        if point.within(shape(poly['geometry'])):
             # sum of attributes values
             polygons[j]['properties']['score'] = polygons[j]['properties']['score'] + points[i]['properties']['score']

2) R- ट्री इंडेक्स के साथ (आप पायट्री या rtree का उपयोग कर सकते हैं )

# Create the R-tree index and store the features in it (bounding box)
 from rtree import index
 idx = index.Index()
 for pos, poly in enumerate(polygons):
       idx.insert(pos, shape(poly['geometry']).bounds)

#iterate through points
for i,pt in enumerate(points):
  point = shape(pt['geometry'])
  # iterate through spatial index
  for j in idx.intersection(point.coords[0]):
      if point.within(shape(multi[j]['geometry'])):
            polygons[j]['properties']['score'] = polygons[j]['properties']['score'] + points[i]['properties']['score']

दो समाधानों के साथ परिणाम:

for poly in polygons:
   print poly['properties']    
 OrderedDict([(u'score', 2)]) # 2 points in the polygon
 OrderedDict([(u'score', 1)]) # 1 point in the polygon
 OrderedDict([(u'score', 1)]) # 1 point in the polygon

अंतर क्या है ?

  • सूचकांक के बिना, आपको सभी ज्यामितीय (बहुभुज और अंक) के माध्यम से पुनरावृति करना होगा।
  • एक बाउंडिंग स्पेसियल इंडेक्स ( स्थानिक सूचकांक आरट्री ) के साथ, आप केवल उन जिओमेट्री के माध्यम से पुनरावृति करते हैं, जो आपके वर्तमान ज्यामिति ('फिल्टर' के साथ अंतर करने का मौका है जो गणना और समय की काफी मात्रा बचा सकते हैं ...)
  • लेकिन एक स्थानिक सूचकांक एक जादू की छड़ी नहीं है। जब डेटासेट के एक बहुत बड़े हिस्से को पुनः प्राप्त किया जाना है, तो एक स्थानिक सूचकांक कोई गति लाभ नहीं दे सकता है।

बाद:

schema = fiona.open('poly.shp').schema
with fiona.open ('output.shp', 'w', 'ESRI Shapefile', schema) as output:
    for poly in polygons:
        output.write(poly)

आगे जाने के लिए, OGR, Shapely, Fiona के साथ Rtree स्थानिक अनुक्रमण का उपयोग करके देखें


15

इसके अतिरिक्त - जिओपांडों में अब वैकल्पिक rtreeरूप से एक निर्भरता के रूप में शामिल है, गितुब रेपो देखें

इसलिए, उपरोक्त सभी (बहुत अच्छा) कोड का अनुसरण करने के बजाय, आप बस कुछ ऐसा कर सकते हैं:

import geopandas
from geopandas.tools import sjoin
point = geopandas.GeoDataFrame.from_file('point.shp') # or geojson etc
poly = geopandas.GeoDataFrame.from_file('poly.shp')
pointInPolys = sjoin(point, poly, how='left')
pointSumByPoly = pointInPolys.groupby('PolyGroupByField')['fields', 'in', 'grouped', 'output'].agg(['sum'])

इस snazzy कार्यक्षमता प्राप्त करने के लिए पहले C- लायब्रेरी libspatialindex स्थापित करना सुनिश्चित करें

EDIT: पैकेज आयात को सही किया


मैं छापा rtreeवैकल्पिक था। स्थापित यह नहीं है कि मतलब आप की जरूरत करने के लिए rtreeऔर साथ ही libspatialindexसी-पुस्तकालय?
कुआनब

यह थोड़ी देर हो गई है, लेकिन मुझे लगता है कि जब मैंने यह स्थापित किया था, rtreeजब मैंने पहली बार स्थापित किया था, तब जीथब्यूस से स्वचालित रूप से जोड़ा गया libspatialindex... उन्होंने काफी बड़ी रिलीज़ की है, इसलिए मुझे यकीन है कि चीजें थोड़ी बदल गई हैं
क्लेटनट्रश

9

बहुत तेजी से जुड़ने के लिए एक सूचकांक के रूप में Rtree का उपयोग करें , फिर एक बिंदु बहुभुज के भीतर है या नहीं यह निर्धारित करने के लिए स्थानिक भविष्यवाणी करने के लिए Shapely। अगर ठीक से किया जाए, तो यह अधिकांश अन्य जीआईएस से तेज हो सकता है।

यहाँ या यहाँ उदाहरण देखें ।

'SUM' से संबंधित आपके प्रश्न का दूसरा भाग, dictबहुभुज आईडी का उपयोग करके कुंजी के रूप में आबादी को संचित करने के लिए एक ऑब्जेक्ट का उपयोग करें। हालाँकि, इस तरह की बात PostGIS के साथ बहुत अधिक की जाती है।


शुक्रिया @ मायके टी ... तानाशाह वस्तु या PostGIS का उपयोग करना महान सुझाव हैं। मैं अभी भी थोड़ा भ्रमित हूं जहां मैं अपने कोड में Rtree को शामिल कर सकता हूं, हालांकि (ऊपर कोड शामिल है)।
jburrfischer

1

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

http://rexdouglass.com/fast-spatial-joins-in-python-with-a-spatial-index/


धन्यवाद @klewis ... कोई भी मौका आप दूसरे भाग के साथ मदद कर सकते हैं? बिंदु विशेषताओं (जैसे जनसंख्या) को योग करने के लिए जो बहुभुज के भीतर आते हैं, मैंने नीचे दिए गए कोड के समान कुछ करने की कोशिश की, लेकिन यह एक त्रुटि थी। अगर आकार (स्कूल ['ज्यामिति')]। (आकार (पड़ोस ['ज्यामिति'))): पड़ोस ['गुण'] ['जनसंख्या'] + = स्कूल ['गुण'] ['जनसंख्या']
jburrfischer

यदि आप 'r' मोड में पड़ोस खोलते हैं, तो यह केवल पढ़ने के लिए हो सकता है। क्या दोनों शेपफाइल्स में क्षेत्र की आबादी है? कौन सी लाइन # त्रुटि फेंक रही है? सौभाग्य।
क्लेविस

धन्यवाद फिर से @klewis ... मैंने अपना कोड ऊपर जोड़ा है और त्रुटि बताई है। इसके अलावा, मैं rtree के साथ खेल रहा हूं और मैं अभी भी थोड़ा उलझन में हूं कि मैं इसे ऊपर दिए गए कोड में कहां जोड़ूंगा। खेद है कि इस तरह के एक परेशान होने के लिए।
jburrfischer

इसे आज़माएं, लगता है कि कोई भी इंट को जोड़ना त्रुटि का कारण है। poly_score = poly ['properties'] ['स्कोर']] बिंदु_score = बिंदु ['गुण'] ['स्कोर']) यदि point_score: यदि poly_score पाली ['properties'] ['स्कोर'] + = बिंदु_score और: पाली ['गुण'] ['स्कोर']] = बिंदु_स्कोर
क्लेविस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.