การคำนวณตัวเลขเรียงลำดับลงในตารางที่เรียงลำดับโดยใช้ ArcGIS Desktop หรือไม่


12

มีวิธีการคำนวณที่เรียงลำดับข้อมูลที่มีหมายเลขลำดับ? ฉันเคยเห็นclass feature sorting เพื่อคำนวณเขตข้อมูล ID ตามลำดับโดยใช้ ArcGIS Field Calculator หรือไม่ ที่สรุปวิธีการคำนวณตัวเลขตามลำดับ แต่จะคำนวณตามลำดับ 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ฟิลด์ของฉันไม่เป็นไปตามลำดับดังนั้นโค้ดด้านบนจะไม่ทำงาน

ป้อนคำอธิบายรูปภาพที่นี่

สามารถทำได้ทั้งในเครื่องคำนวณภาคสนามหรือใช้ Update Cursor ใน arcpy?


ใน ArcObjects ด้วย ITableSort คุณควรจะทำได้ .. ไม่มากในงูหลาม ตารางเรียงลำดับอย่างไร คุณสามารถอ่านได้ถึงพจนานุกรมที่มี OID และฟิลด์เรียงลำดับจัดเรียงพจนานุกรมสร้างพจนานุกรมใหม่ด้วย OID และค่าวนซ้ำพจนานุกรมแรกที่เรียงแล้วเพื่อกำหนดค่าให้กับวินาทีจากนั้นเคอร์เซอร์ผ่านการกำหนดด้วยพจนานุกรมที่สอง ... a บิตของการล้อเล่น แต่นั่นคือทั้งหมดที่ฉันสามารถคิดได้โดยไม่ต้องใช้ ArcObjects
Michael Stimson

@ MichaelMiles-Stimson นั่นไม่ใช่ความคิดที่แย่ฉันอาจโหลดมันลงในพจนานุกรมเพื่อกำหนดลำดับการจัดเรียงแล้วเขียนค่าเหล่านั้นออกไปยัง Seq
Midavalo

นั่นเป็นวิธีที่ฉันเคยทำมาก่อนและใช้ได้ดี ฉันหารหัสของฉันไม่พบในตอนนี้ มันเป็นแบบครั้งเดียวดังนั้นอาจเป็นหนึ่งในดิสก์สำรองของฉัน ... ถ้าฉันเจอมันฉันจะโพสต์เป็นคำตอบ - ถ้าไม่มีคำตอบที่ดีสำหรับคำถามนี้
Michael Stimson

ฉันรำคาญเสมอที่ไม่สามารถทำได้อย่างง่ายดายใน ArcGIS ในขณะที่มันเป็นเรื่องเล็กน้อยใน MapInfo วิธีที่ง่ายที่สุดที่ฉันเจอคือการใช้เครื่องมือเรียงลำดับแต่สร้างชุดข้อมูลอื่นที่คุณต้องเข้าร่วม
Fezter

ไพ ธ อนของคุณทำงานได้อย่างสมบูรณ์ขอบคุณสำหรับสิ่งนั้น ฉันแค่สงสัยว่าเป็นไปได้หรือไม่ที่จะเริ่มแถวแรกด้วย 1 แทนที่จะเป็น 0 หากเป็นไปได้คุณสามารถให้รหัสแก่ฉันได้หรือไม่ จบสัปดาห์ที่ดี Fred
Fred

คำตอบ:


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

ใช้เวลา 1.5 วินาทีในการทำงานให้เสร็จสมบูรณ์บน 10,000 ระเบียน ต้นฉบับใช้เวลามากกว่า 2 นาที


ฉันเชื่อว่าสี่บรรทัดแรกของรหัสนี้กำลังถูกเรียกใช้สำหรับแต่ละระเบียน ต้องไม่อนุญาตเนื่องจากเลเยอร์จะต้องเรียงลำดับเพียงครั้งเดียวสำหรับการคำนวณทั้งหมด พิจารณาใช้เคล็ดลับที่ฉันแสดงในโพสต์ของฉันหรือแสดงให้เห็นว่าเลเยอร์กำลังอ่านเพียงครั้งเดียวเพื่อกำหนดลำดับการบันทึกสำหรับบันทึกแรกเท่านั้น
Richard Fairhurst

@RichardFairhurst ฉันทดสอบนิพจน์ดั้งเดิมของฉันบนบันทึกกว่า 10,000 รายการใช้เวลา 2 นาทีในการดำเนินการ 6 วินาทีทำให้การแก้ไขมีผลในการปรับปรุง 5 วินาที ดูเหมือนว่าบรรทัดแรกจะไม่ซ้ำกับทุกระเบียน ใช่เครื่องคิดเลขภาคสนามช้ากว่าสคริปต์มากสะดวกมาก
เฟลิกซ์

ทดสอบตารางเดียวกันกับการคำนวณของฉัน หากพวกเขาใช้เวลาเดียวกันในการคำนวณแล้วฉันจะยอมรับสมมติฐานของคุณว่ามีการประมวลผลเพียงครั้งเดียว 2 นาทีและ 6 วินาทีค่อนข้างช้า
Richard Fairhurst

ตกลง 1.5 วินาทีดูเหมือนจะบ่งบอกว่า 4 บรรทัดแรกไม่ได้รับการประมวลผลสำหรับแต่ละระเบียน อย่างไรก็ตามพจนานุกรมเป็นวิธีที่จะไปในทั้งสองกรณี อย่างไรก็ตามคุณจะทำอย่างไรเมื่อฉันต้องการให้หมายเลข Seq ไม่ซ้ำกันในแต่ละระเบียนเมื่อค่าในเขตข้อมูลอื่นเหมือนกัน นั่นคือสิ่งที่ฉันต้องการสำหรับตารางที่เกี่ยวข้องในความสัมพันธ์ 1: M
Richard Fairhurst

+1 @RichardFairhurst สำหรับพจนานุกรม การสับเปลี่ยนรายการเป็นส่วนที่ช้าในต้นฉบับของฉัน ไม่ควรเป็นเอกลักษณ์มันเป็นการเปลี่ยนแปลงที่ยิ่งใหญ่ของ OP
FelixIP

6

นี่เป็นกระบวนการสองขั้นตอนและด้วยเหตุนี้เครื่องคำนวณฟิลด์จึงไม่เหมาะสำหรับมัน มันจะดีกว่าที่จะเรียกใช้ในสคริปต์แบบสแตนด์อโลน อย่างไรก็ตามมันสามารถทำได้ในเครื่องคิดเลขฟิลด์หากคุณใช้เคล็ดลับ คุณจำเป็นต้องใช้เคอร์เซอร์เพื่อโหลดค่าทั้งหมดไปยังพจนานุกรมโกลบอลจากรายการที่เรียงลำดับ แต่ระหว่างการคำนวณของระเบียนแรกเท่านั้น สำหรับระเบียนอื่น ๆ ทั้งหมดคุณต้องข้ามการสร้างพจนานุกรมเพื่อหลีกเลี่ยงการอ่านซ้ำทั้งตารางสำหรับแต่ละแถวอย่างต่อเนื่อง

ต้องใส่ค่าฟิลด์ทั้งสามไว้ใน tuple เพื่อทำหน้าที่เป็นคีย์ที่จะเรียงลำดับอย่างถูกต้อง ฉันจะสมมติว่าค่าชุดค่าผสม 3 ฟิลด์ทั้งหมดไม่ซ้ำกันในตาราง SamplePoint แต่ฉันเพิ่ม ObjectID เพื่อให้แน่ใจว่าเป็นค่าที่ไม่ซ้ำกัน คุณต้องระบุชื่อพา ธ และรูปร่างไฟล์ในบรรทัดที่ 8 (หรือฉันสามารถใช้เทคนิคที่ FelixIP ใช้โดยที่จะใช้เลเยอร์แรกในแผนที่ปัจจุบัน) ถ้าคุณต้องการใช้ฟิลด์ต่าง ๆ สำหรับคีย์คุณต้องเปลี่ยนรายการฟิลด์ในบรรทัด 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!)

ฉันจะไม่แนะนำให้ใช้ชื่อเขตข้อมูลของปี, เดือนและวันเนื่องจากสิ่งเหล่านั้นทำงานในรูปทรงไฟล์เท่านั้นและไม่ได้รับอนุญาตในฐานข้อมูลทางภูมิศาสตร์ ฐานข้อมูลภูมิศาสตร์จะเปลี่ยนชื่อเป็น Year_1, Month_1, Day_1 หากคุณพยายามที่จะเพิ่มลงในรายการเขตข้อมูลในคุณสมบัติของตาราง

หากวัตถุประสงค์ของตารางนี้เกี่ยวข้องกับตาราง / ฟีเจอร์คลาสอื่นบนคีย์แบบหลายฟิลด์ให้พิจารณาใช้เครื่องมือที่ฉันสร้างขึ้นในบล็อกของฉันชื่อคีย์ฟิลด์หลายฟิลด์กับเครื่องมือคีย์ฟิลด์เดียว - สัมพันธ์สองเลเยอร์มากกว่าหนึ่ง สนาม


มันจัดการกับรายการซ้ำได้อย่างไร
FelixIP

เพิ่ม OID ไปยังรายการเขตข้อมูล ฉันได้เพิ่ม OID ไปยังรายการเขตข้อมูลเพื่อให้แน่ใจว่าไม่ซ้ำกัน
Richard Fairhurst

อีกทางเลือกหนึ่งหากมีการทำซ้ำและผู้ใช้ต้องการให้รายการที่ซ้ำกันทั้งหมดมีค่า SEQ ที่เหมือนกันจากนั้นปล่อย ObjectID ออกมาและใช้ set () ในรายการก่อนเรียกใช้ลูป for และเพิ่มลงในพจนานุกรม
Richard Fairhurst

+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!)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.