ArcGIS डेस्कटॉप का उपयोग करके क्रमबद्ध तालिका में अनुक्रमिक संख्याओं की गणना?


12

क्या अनुक्रमिक संख्याओं के साथ एक सॉर्ट किए गए फ़ील्ड की गणना करने का एक तरीका है ? मैंने ArcGIS फ़ील्ड कैलकुलेटर का उपयोग करके अनुक्रमिक आईडी फ़ील्ड की गणना करने के लिए सॉर्टिंग फ़ीचर वर्ग देखा है ? यह रेखांकित करता है कि अनुक्रमिक संख्याओं की गणना कैसे की जाती है, लेकिन यह हमेशा FID आदेश पर गणना की जाती है, क्रमबद्ध क्रम पर नहीं।

#Pre-logic Script Code:
rec=0
def autoIncrement(): 
    global rec 
    pStart = 1  
    pInterval = 1 
    if (rec == 0):  
        rec = pStart  
    else:  
        rec += pInterval  
    return rec

#Expression:
autoIncrement()

मैं जो करने की कोशिश कर रहा हूं उसका एक उदाहरण । मैंने वर्ष, महीने, दिन के अनुसार सॉर्ट करने के लिए एक उन्नत प्रकार का उपयोग किया है, और अब Seqक्षेत्र में अनुक्रमिक संख्याएं रखना चाहता हूं । आप देखेंगे कि मेरा OBJECTIDक्षेत्र क्रम में नहीं है, इसलिए उपरोक्त कोड काम नहीं करेगा।

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

क्या यह फील्ड कैलकुलेटर में किया जा सकता है या आर्कपी में अपडेट कर्सर का उपयोग कर सकता है?


एक ITableSort के साथ ArcObjects में आप इसे करने में सक्षम होना चाहिए .. अजगर में इतना नहीं। तालिका कैसे क्रमबद्ध है? आप इसे OID के साथ एक शब्दकोश तक पढ़ सकते हैं और फ़ील्ड को क्रमबद्ध कर सकते हैं, शब्दकोश को टाइप कर सकते हैं, OID और मान के साथ एक और शब्दकोश बना सकते हैं, दूसरे शब्द के साथ असाइन करने के माध्यम से दूसरे और फिर कर्सर को मान देने के लिए सॉर्ट किए गए पहले शब्दकोश को सॉर्ट करते हैं ... a बिट के आसपास mucking लेकिन यह सब मैं ArcObjects का उपयोग किए बिना सोच सकता है।
माइकल स्टिम्सन

@ माइकलमिल्स-स्टिमसन यह एक बुरा विचार नहीं है, मैं शायद इसे सॉर्ट करने के लिए शब्दकोशों में लोड कर सकता हूं, फिर उन मूल्यों को Seq पर लिख सकता हूं।
Midavalo

मैंने पहले भी ऐसा किया है और यह ठीक काम किया है। मुझे अभी अपना कोड नहीं मिल रहा है; यह एक बंद था इसलिए यह शायद मेरी एक बैकअप डिस्क पर है ... यदि मैं इसके पार आता हूं तो उत्तर के रूप में पोस्ट करूंगा - बशर्ते इस प्रश्न का पहले से ही कोई अच्छा जवाब नहीं है।
माइकल स्टिम्सन

मैं हमेशा से नाराज था कि यह आसानी से आर्कगिस में नहीं किया जा सकता है। जबकि, यह MapInfo में तुच्छ है। सबसे आसान तरीका जो मुझे आया है वह है सॉर्ट टूल का उपयोग करना लेकिन यह एक और डेटासेट बनाता है जिसे आपको वापस जोड़ना होगा।
Fezter

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

जवाबों:


14

2 हल क्षेत्रों (आरोही) के साथ "समाधान":

mxd = arcpy.mapping.MapDocument("CURRENT")
lr=arcpy.mapping.ListLayers(mxd)[0]
tbl=arcpy.da.TableToNumPyArray(lr,("oid","A","B"))
bs=sorted(tbl, key=lambda x: (x[1], x[2]))
def sortSeq(fid,a,b):
 for i,ent in enumerate(bs):
   if ent[0]==fid: return i

--------------------------------------

sortSeq( !OID!, !A!, !B! )

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

अपडेट किया गया वर्ज़न:

mxd = arcpy.mapping.MapDocument("CURRENT")
lr=arcpy.mapping.ListLayers(mxd)[0]
tbl=arcpy.da.TableToNumPyArray(lr,("oid","A","B"))
bs=sorted(tbl, key=lambda x: (x[1], x[2]))
aDict={}
for i,row in enumerate(bs):
 aDict[row[0]]=i
def sortSeq(fid):
 return aDict[fid]

-----------------------

sortSeq( !OID!)

10000 रिकॉर्ड पर काम पूरा करने के लिए 1.5 सेकंड लगते हैं। ओरिजिनल 2 मिनट से थोड़ा अधिक समय लेता है


मेरा मानना ​​है कि इस कोड की पहली चार पंक्तियाँ प्रत्येक रिकॉर्ड के लिए चलाई जा रही हैं। इसकी अनुमति नहीं दी जानी चाहिए, क्योंकि परत को केवल संपूर्ण गणना के लिए एक बार क्रमबद्ध करने की आवश्यकता होती है। मेरे पोस्ट में दिखाए गए ट्रिक का उपयोग करने पर विचार करें या प्रदर्शित करें कि केवल पहले रिकॉर्ड के लिए रिकॉर्ड सॉर्ट क्रम को निर्धारित करने के लिए परत को केवल एक बार पढ़ा जा रहा है।
रिचर्ड फेयरहर्स्ट

@RichardFairhurst मैंने 10 हजार रिकॉर्ड पर अपनी मूल अभिव्यक्ति का परीक्षण किया, इसे पूरा करने में 2 मिनट 06 सेकंड लगे, संशोधन के परिणामस्वरूप 5 सेकंड में सुधार हुआ। ऐसा लगता है कि पहली पंक्तियों को हर रिकॉर्ड पर दोहराया नहीं गया है। हां फील्ड कैलकुलेटर स्क्रिप्ट की तुलना में बहुत धीमा है, हालांकि सुविधाजनक है
फेलिक्सिप

मेरी गणना के खिलाफ एक ही तालिका का परीक्षण करें। यदि वे गणना करने के लिए लगभग समान समय लेते हैं तो मैं आपकी धारणा को स्वीकार करूंगा कि यह केवल एक बार संसाधित किया जा रहा है। 2 मिनट और 6 सेकंड काफी धीमा है।
रिचर्ड फेयरहर्स्ट

ठीक 1.5 सेकंड में यह प्रतीत होता है कि प्रत्येक रिकॉर्ड के लिए पहले 4 पंक्तियों को संसाधित नहीं किया जा रहा है। वैसे भी, शब्दकोश किसी भी मामले में जाने का तरीका है। हालाँकि, आप क्या करते हैं जब मैं चाहता हूं कि जब सीक नंबर प्रत्येक रिकॉर्ड पर अद्वितीय न हो, जब अन्य फ़ील्ड में मान समान हों? यह वही होगा जो मैं 1: M संबंध में संबंधित तालिका के लिए चाहूंगा।
रिचर्ड फेयरहर्स्ट

शब्दकोश के लिए +1 @ रीचर्डफेयरहर्स्ट। सूची में फेरबदल मेरे मूल में एक धीमा हिस्सा था। अद्वितीय न होने के लिए यह ओपी का एक बड़ा बदलाव है
फेलिक्सिप

6

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

तीन क्षेत्र मूल्यों को एक कुंजी के रूप में कार्य करने के लिए एक टपल में रखा जाना चाहिए जो ठीक से सॉर्ट करेगा। मैं मान लूंगा कि सभी 3-फील्ड संयोजन मूल्य सैंपलपॉइंट टेबल में अद्वितीय हैं, लेकिन मैंने यह सुनिश्चित करने के लिए ऑब्जेक्ट को जोड़ा कि यह अद्वितीय है। आपको लाइन 8 में पथ और आकार का नाम प्रदान करना होगा (या मैं उस तकनीक का उपयोग कर सकता हूं जो फेलिक्सिप वर्तमान मानचित्र में पहली परत का उपयोग करता है)। यदि आप एक कुंजी के लिए विभिन्न क्षेत्रों का उपयोग करना चाहते हैं, तो आपको पंक्ति 10 में फ़ील्ड सूची को बदलना होगा और उन्हें पंक्ति 3 और पंक्ति 15 में इनपुट फ़ील्ड के साथ मेल खाना चाहिए।

#Pre-logic Script Code:
relateDict = {}
def autoIncrement(myYear, myMonth, myDay, OID): 
    global relateDict  
    # only populate the dictionary if it has no keys  
    if len(relateDict) == 0:  
        # Provide the path to the relate feature class/table  
        relateFC = r"C:\Users\OWNER\Documents\ArcGIS\SamplePoints.shp"  
        # create a field list with the relate fields in sort order  
        relateFieldsList = ["Year", "Month", "Day", "OID@"]  
        # process a da search cursor to transfer the data to the dictionary  
        relateList = sorted([(r[0:]) for r in arcpy.da.SearchCursor(relateFC, relateFieldsList)])
        for relateSort in range(0, len(relateList)):
            relateDict[relateList[relateSort]] = relateSort + 1
    return relateDict[(myYear,myMonth,myDay,OID)]    

#Expression:
autoIncrement(!Year!, !Month!, !Day!, !OBJECTID!)

मैं वर्ष, माह और दिन के क्षेत्र के नाम का उपयोग करने की भी सिफारिश नहीं करूंगा, क्योंकि वे केवल आकार-प्रकार में काम करते हैं और जियोडैट डेटाबेस में अनुमति नहीं है। यदि आप तालिका के गुणों में फ़ील्ड सूची में उन्हें जोड़ने का प्रयास करते हैं तो एक जियोडैटेबेस नाम को वर्ष_1, महीना 1, दिन 1 में बदल देगा।

यदि इस तालिका का उद्देश्य इसे किसी अन्य फ़ील्ड / कुंजी वर्ग से संबंधित किसी अन्य फ़ील्ड / कुंजी वर्ग से संबंधित करना है, तो मैंने अपने ब्लॉग में बनाए गए टूल का उपयोग करके मल्टीपल फ़ील्ड कुंजी को सिंगल फ़ील्ड कुंजी टूल नाम दिया है - संबंधित दो परतें एक से अधिक के आधार पर खेत


यह डुप्लिकेट को कैसे संभालता है?
फेलिक्सिप

फ़ील्ड सूची में OID जोड़ें। मैंने यह सुनिश्चित करने के लिए फ़ील्ड सूची में OID को जोड़ा है कि यह अद्वितीय है।
रिचर्ड फेयरहर्स्ट

वैकल्पिक रूप से यदि डुप्लिकेट हैं और उपयोगकर्ता चाहता है कि सभी डुप्लिकेट सभी का समान SEQ मान हो, तो ऑब्जेक्ट को बाहर छोड़ें और लूप के लिए चलने से पहले सूची में सेट () का उपयोग करें और इसे शब्दकोश में जोड़ें।
रिचर्ड फेयरहर्स्ट

+1 धन्यवाद @RichardFairhurst, arcpy में लिखने के लिए मेरे प्रयास के रूप में ज्यादा एक ही है, हालांकि मुझे नहीं पता था कि आप से फील्ड कैलक्यूलेटर के भीतर उस के सबसे कह सकते हैं
Midavalo

3

मेरे पास एक ही सवाल था लेकिन एक साधारण समस्या के लिए, केवल एक फ़ील्ड को सॉर्ट करने के आधार पर। मैं निम्नलिखित स्क्रिप्ट के साथ सफल रहा:

# Pre-Logic Script Code:
# Specify that the target Map Document is the current one
mxd = arcpy.mapping.MapDocument("CURRENT")
# Specify that the target layer is the first layer in the table of 
# content
lr=arcpy.mapping.ListLayers(mxd)[0]

tbl=arcpy.da.TableToNumPyArray(lr,("fid","Name_of_sorted_Field"))
bs=sorted(tbl,key=lambda x: x[1])
aDict={}
for i,row in enumerate(bs):
 aDict[row[0]]=i
def sortSeq(fid):
 return aDict[fid]

---------------------------------------------------------------
# to run the code, the following goes in the expression window
sortSeq(!FID!)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.