पायथन के साथ विशेषता तालिकाओं को संशोधित करने के लिए सबसे तेज़ तरीके?


12

कुछ समय पहले, मैंने एक विशेषता तालिका को एक अजगर शब्दकोश में परिवर्तित करने के लिए एक त्वरित पायथन फ़ंक्शन लिखा था, जहां कुंजी उपयोगकर्ता द्वारा निर्दिष्ट अद्वितीय आईडी फ़ील्ड (आमतौर पर ओआईडी क्षेत्र) से ली गई है। इसके अतिरिक्त, डिफ़ॉल्ट रूप से सभी फ़ील्ड को शब्दकोश में कॉपी किया जाता है, लेकिन मैंने एक पैरामीटर को शामिल किया है जिसमें केवल एक सबसेट निर्दिष्ट करने की अनुमति है।

def make_attribute_dict(fc, key_field, attr_list=['*']):
    dict = {}
    fc_field_objects = arcpy.ListFields(fc)
    fc_fields = [field.name for field in fc_field_objects if field.type != 'Geometry']
    if attr_list == ['*']:
        valid_fields = fc_fields
    else:
        valid_fields = [field for field in attr_list if field in fc_fields]
    if key_field not in valid_fields:
        cursor_fields = valid_fields + [key_field]
    else:
        cursor_fields = valid_fields
    with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
        for row in cursor:
            key = row[cursor_fields.index(key_field)]
            subdict = {}
            for field in valid_fields:
                subdict[field] = row[cursor_fields.index(field)]
            dict[key] = subdict
            del subdict
    return dict

यह अपेक्षाकृत छोटे डेटासेट के लिए बहुत अच्छा काम करता है, लेकिन मैंने इसे एक टेबल पर लगभग 750,000 पंक्तियों और 15 फ़ील्डों के साथ चलाया - एक फ़ाइल जियोडेटाबेस में लगभग 100 एमबी। इन पर, फ़ंक्शन बहुत धीमी गति से चलता है जितना मैंने उम्मीद की होगी: लगभग 5-6 मिनट (और यह in_memoryकार्यक्षेत्र की तालिका की नकल करने के बाद है )। मैं वास्तव में शब्दकोश में रूपांतरण को गति देने का एक तरीका खोजना चाहता हूं, या पायथन का उपयोग करके बड़ी मात्रा में विशेषता डेटा में हेरफेर करने के लिए बेहतर रणनीति पर कुछ अंतर्दृष्टि प्राप्त करना चाहता हूं।

अपडेटसर्कर्स मेरे लिए अच्छा काम नहीं करेंगे, क्योंकि जब एक पंक्ति बदलती है, तो इसमें कई अन्य लोगों में परिवर्तन को ट्रिगर करने की क्षमता होती है। एक बार में उन्हें लूपिंग करना और उन्हें संसाधित करना, जो मुझे चाहिए उसके लिए बहुत बोझिल है।


2
आपके स्क्रिप्ट को कितना ऑप्टिमाइज़ किया जा सकता है, इसमें सीमित कारक आपके कर्सर के माध्यम से पुनरावृति करने में लगने वाले समय की लंबाई हो सकती है। क्या आपने अपने शब्दकोशों का निर्माण किए बिना कर्सर के माध्यम से पुनरावृति में लगने वाले समय की तुलना की है?
जेसन

2
@ जेसन के बारे में 10 सेकंड के प्रसंस्करण समय पैदावार के subdict = {}माध्यम से लाइनों की टिप्पणी del subdict
नंपेटर्स

आप शायद इस बारे में मुझसे अधिक जानते हैं, लेकिन अनुकूलन के संदर्भ में केवल एक चीज जो मैं पेश करता हूं वह यह है कि क्या कॉलिंग subdict[field] = row[cursor_fields.index(field)]की तुलना में कॉलिंग तेज है subdict[field] = row.getValue(field)। बाद के परिदृश्य में आप एक कदम का प्रदर्शन करेंगे ... हालांकि दो सूचियों ( cursor_fieldsऔर row) को सूचीबद्ध करने और एक एकल ESRI प्रक्रिया का उपयोग करने के बीच प्रदर्शन में अंतर बहुत बेहतर नहीं हो सकता है और अभी भी बदतर हो सकता है!
जेसन

जवाबों:


16

मुझे लगता है कि समस्या आपकी दो पंक्तियों की संभावना है जहां आप खेतों पर जा रहे हैं और प्रत्येक क्षेत्र को व्यक्तिगत रूप से अपने subdictशब्दकोश में जोड़ रहे हैं ।

for field in valid_fields:
    subdict[field] = row[cursor_fields.index(field)]

आपकी rowवस्तु पहले से ही आपके क्षेत्रों के समान क्रम में एक टपल है, इसका लाभ उठाएं और zipफ़ंक्शन का उपयोग करें ।

def make_attribute_dict(fc, key_field, attr_list=['*']):
    attdict = {}
    fc_field_objects = arcpy.ListFields(fc)
    fc_fields = [field.name for field in fc_field_objects if field.type != 'Geometry']
    if attr_list == ['*']:
        valid_fields = fc_fields
    else:
        valid_fields = [field for field in attr_list if field in fc_fields]
    #Ensure that key_field is always the first field in the field list
    cursor_fields = [key_field] + list(set(valid_fields) - set([key_field]))
    with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
        for row in cursor:
            attdict[row[0]] = dict(zip(cursor.fields,row))
    return attdict

यह मेरे सिस्टम पर 8 सेकंड में एक 218k रिकॉर्ड 16 फील्ड फ़ाइल जियोडैटेबेस सुविधा वर्ग के माध्यम से चुगली करता है।

संपादित करें: अधिक कठोर परीक्षण का प्रयास किया। OBJECTID और आकार सहित 16 क्षेत्रों के साथ एक दूरस्थ एसडीई कनेक्शन पर 518k रिकॉर्ड, 32-बिट पर चलता है। 11 सेकंड :)


1
ध्यान दें कि मैंने key_fieldपहला क्षेत्र बनाया ताकि मैं row[0]मूल्य के संदर्भ में उपयोग करने पर भरोसा कर सकूं key_field। मैं भी अपने चर बदलना पड़ा dictकरने के लिए attdict। तानाशाह एक कीवर्ड है, और उस कीवर्ड के बिना मैं उपयोग नहीं कर सकता थाdict(zip())
ब्लॉर्ड-कास्टिलो

6
चालाक। यह ठीक उसी प्रकार का मीठा मुहावरेदार पायथन है जो arcpy.daसक्षम करने के लिए है।
जेसन शहीर

महान अंतर्दृष्टि। विधि से प्यार है, और यह वास्तव में मदद की।
नॅम्पेटर्सन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.