Stand alone คำนวณฟิลด์สคริปต์โดยใช้ Code Block สำหรับ IMG Raster ใน Python
ฉันค่อนข้างคุ้นเคยกับการใช้ภาษา python ในเครื่องมือคำนวณฟิลด์ใน ArcGIS Pro แต่สงสัยว่าจะทำอย่างไรในสคริปต์ Python แบบสแตนด์อโลนพร้อมไฟล์ raster .img (Combine20012004FltPths.img)
ฉันกำลังพยายามจัดประเภทฟิลด์ใหม่ที่ฉันสร้างขึ้นโดยใช้ค่าจำนวนเต็มจากฟิลด์อื่น อย่างไรก็ตามเมื่อฉันพยายามเรียกใช้โค้ดใน IDLE ฉันได้รับ "SyntaxError: invalid syntax"
นี่คือสคริปต์ python ของฉันสำหรับ Code Block และการจัดการ arcpy Calculate Field tool:
# Code Block for Calculate Field
codeBlock = def reclass(FlightPat1):
if (FlightPat1 == 0):
return "Unclassified"
elif (FlightPat1 == 11):
return "Open Water"
elif (FlightPat1 == 12):
return "Perennial Snow/Ice"
elif (FlightPat1 == 21):
return "Developed, Open Space"
elif (FlightPat1 == 22):
return "Developed, Low Intensity"
elif (FlightPat1 == 23):
return "Developed, Medium Intensity"
elif (FlightPat1 == 24):
return "Developed, High Intensity"
elif (FlightPat1 == 31):
return "Barren Land"
elif (FlightPat1 == 41):
return "Deciduous Forest"
elif (FlightPat1 == 42):
return "Evergreen Forest"
elif (FlightPat1 == 43):
return "Mixed Forest"
elif (FlightPat1 == 52):
return "Shrub/Scrub"
elif (FlightPat1 == 71):
return "Herbaceuous"
elif (FlightPat1 == 81):
return "Hay/Pasture"
elif (FlightPat1 == 82):
return "Cultivated Crops"
elif (FlightPat1 == 90):
return "Woody Wetlands"
elif (FlightPat1 == 95):
return "Emergent Herbaceuous Wetlands"
#Reclassify field based off another field
arcpy.CalculateField_management("Combine20012004FltPths.img", "NLCD01Clss",
"Reclass(!FlightPat1!)", expression_type = "PYTHON3",
code_block = codeBlock, field_type = "TEXT")
ฉันจะต้องแปลงตารางแอตทริบิวต์ของไฟล์. img (Combine20012004FltPths.img) ของฉันเป็น dBASE หรือตารางฐานข้อมูลทางภูมิศาสตร์หรือรูปแบบตารางอื่น ๆ จากนั้นเรียกใช้เครื่องมือ Code Block และ Calculate Field เพื่อให้ทำงานได้หรือไม่
คำตอบ
กุญแจสำคัญในการจัดเตรียมบล็อกรหัสให้CalculateFieldคือการทำความเข้าใจว่ามีการใช้ตัวแยกวิเคราะห์ Python แยกต่างหากภายในยูทิลิตี้ code_blockต้องจึงจะเป็นสตริงที่มีรหัสที่ทำงานได้ คุณสามารถทำสิ่งนี้ให้สำเร็จได้โดยใช้เครื่องหมายอัญประกาศสามรอบข้อความเพื่อให้ Python จัดการความต่อเนื่องของบรรทัดได้อย่างถูกต้อง:
# Code Block for Calculate Field
codeBlock = """
def reclass(flightPat1): # Note lowercase variable name -- upcase is for Classes
{rest of function}
"""
แต่นั่นเป็นเพียงการปรับปรุงครั้งแรกเท่านั้น มีสองวิธีพื้นฐานในการเข้ารหัสฟังก์ชันสวิตช์ยาร์ด แบบแรกใช้การทดสอบตามเงื่อนไขแบบเรียงซ้อนและมีสองรูปแบบใหญ่ ๆ : มีและไม่มีทางออกก่อน ก่อนอื่นโดยไม่ต้อง:
# Code Block for Calculate Field
codeBlock = """
def reclass(flightPat1):
result = None #! Initialize so that it always returns a default value
if (flightPat1 == 0):
result = "Unclassified"
elif (flightPat1 == 11):
result = "Open Water"
...
return result
"""
แบบฟอร์มการออกก่อนกำหนดควรคุ้นเคย แต่เมื่อreturnใช้แล้วไม่elseจำเป็น:
# Code Block for Calculate Field
codeBlock = """
def reclass(flightPat1):
if (flightPat1 == 0):
return "Unclassified"
if (flightPat1 == 11):
return "Open Water"
...
return None #! Suffices for final else
"""
แนวทางที่สองใช้ประโยชน์จากประเภทข้อมูลพจนานุกรม เร็วกว่าและ pythonic มากขึ้น:
# Code Block for Calculate Field
codeBlock = """
lookup = {
0 : "Unclassified",
11 : "Open Water",
...
}
def reclass(flightPat1):
return lookup[flightPat1] if flightPat1 in lookup else None
"""
ส่วนที่เซ็กซี่เกี่ยวกับการใช้พจนานุกรมคือคุณสามารถรวมสิ่งนี้เข้ากับข้อเท็จจริงที่ว่าคุณกำลังรวบรวมสตริงที่นี่เพื่อให้คุณสามารถรวบรวมได้แบบไดนามิก (ในกรณีนี้จากตารางฐานข้อมูลของไฟล์):
# Code Block for Calculate Field
lookupSrc = r"C:\Temp\gis_se.gdb\answer_lookup"
codeBlock = """
def reclass(flightPat1):
lookup = {
@TERMS
}
return lookup[flightPat1] if flightPat1 in lookup else None
""".replace('@TERMS',',\n'.join(
["{:10d} : '{:s}'".format(rec[0],rec[1].replace("'","\\'"))
for rec in arcpy.da.SearchCursor(lookupSrc,['ival','sval'])]))
โอเคใช่แล้วมันค่อนข้างร้อนแรง แต่คุณจะทำความเข้าใจรายการบนเคอร์เซอร์รูปแบบและการแทนที่สองครั้งในบรรทัดเดียวได้กี่ครั้ง? และมันใช้งานได้:
>>> print(codeBlock)
def reclass(flightPat1):
lookup = {
0 : 'Unclassified',
11 : 'Open Water',
12 : 'Perennial Snow/Ice',
21 : 'Developed, Open Space',
22 : 'Developed, Low Intensity',
23 : 'Developed, Medium Intensity',
24 : 'Developed, High Intensity',
31 : 'Barren Land',
41 : 'Deciduous Forest',
42 : 'Evergreen Forest',
43 : 'Mixed Forest',
52 : 'Shrub/Scrub',
71 : 'Herbaceuous',
81 : 'Hay/Pasture',
82 : 'Cultivated Crops',
90 : 'Woody Wetlands',
94 : 'Apostrophe\'s Example',
95 : 'Emergent Herbaceuous Wetlands'
}
return lookup[flightPat1] if flightPat1 in lookup else None
ส่วนที่เป็นป้านอาจไม่เข้ากับเอกสารในตัว:
# Code Block for Calculate Field
lookupSrc = r"C:\Temp\gis_se.gdb\answer_lookup"
codeFormat = """
def reclass(flightPat1):
lookup = {
@TERMS
}
return lookup[flightPat1] if flightPat1 in lookup else None
"""
termList = []
with arcpy.da.SearchCursor(lookupSrc,['ival','sval']) as cursor:
for row in cursor:
ival = row[0]
sval = row[1].replace("'","\\'") #! Handle case where sval contains apostrophe
term = "{:10d} : '{:s}'".format(ival,sval)
termList.append(term)
termString = ',\n'.join(termList) #! str.join() adds text between list elements
codeBlock = codeFormat.replace('@TERMS',termString)