กำลังคำนวณคุณลักษณะใหม่โดยอิงตามการเปลี่ยนแปลงในแอตทริบิวต์อื่นโดยใช้ ArcGIS Desktop กับ Python หรือไม่


11

ฉันกำลังพยายามจำแนกชุดข้อมูล gps ที่เข้ารหัสเวลาเป็นพฤติกรรมตามคุณลักษณะที่แตกต่างกัน

ฉันสร้างคุณลักษณะที่เป็น 0 สำหรับบ้านและ 1 สำหรับออกไปตามสถานที่และตอนนี้ต้องการกำหนดจำนวนการเดินทางออกจากบ้าน (ชุดของคะแนน01111111111110จะเป็นการเดินทางหนึ่งครั้งเพราะเริ่มต้นและสิ้นสุดที่บ้าน) ฉันได้เพิ่มฟิลด์แอททริบิวที่จะมีหมายเลขการเดินทาง แต่ไม่ทราบวิธีการคำนวณฟิลด์ดังนั้นจึงเป็นไปตามฟิลด์บ้าน / ออกไป

นี่คือตัวอย่างของข้อมูล GPS (ใช้ "*" เพื่อระบุข้อมูลที่ไม่เกี่ยวข้องและเพียงทำดัชนีครั้งที่ 1, 2 ฯลฯ ) ตัวบ่งชี้ "บ้าน / ออกไป" ที่อธิบายไว้ข้างต้นและตัวบ่งชี้การเดินทางที่ต้องการ "การเดินทาง" ซึ่งฉันต้องคำนวณ:

Time Lat Lon Home/Away Trip
   1   *   *         0    0
   2   *   *         1    1
   3   *   *         1    1
....
  12   *   *         1    1
  13   *   *         0    0
  14   *   *         0    0
  15   *   *         1    2
  16   *   *         1    2
.... 
  34   *   *         1    2
  35   *   *         0    0
  36   *   *         0    0
  37   *   *         1    3
....

ชุดข้อมูลของฉันมีขนาดใหญ่เกินไปที่จะผ่านไปด้วยตนเองและกำหนดจำนวนการเดินทางแต่ละครั้งในตารางแอตทริบิวต์ดังนั้นจึงมีวิธีใดในการคำนวณเขตข้อมูลตามวิธีการสั่งซื้อแอตทริบิวต์ home / Away และกำหนด "ก้อน" ของจุดเก็บแต่ละจุดเป็น เดินทาง?

นี่คือส่วนที่เปลือยเปล่าของรหัส Python ที่อาจดูเหมือน (ฉันไม่เคยมีประสบการณ์กับโค้ด)

นิพจน์:

trip = Reclass(!home!)

Codeblock:

def Reclass(home):  
  if (home = 0):  
    return 0   
  elif (home = 1 and lastValue = 0):  
    return _(incremental numbering?)_  
  elif (home = 1 and lastValue = 1):  
    return lastValue  

หลังจากใช้สคริปต์ที่แนะนำของ matt wilkie ฉันได้ทำการเปลี่ยนแปลงบางอย่างเพื่อให้การเดินทางครั้งแรกของฉันคือหมายเลข 1 ครั้งที่สองคือ 2 ฯลฯ

นี่คือรหัสที่แก้ไขจากด้านของ:

import arcpy
rows = arcpy.UpdateCursor("test2")

trip = 0
for row in rows:
    if row.home == 0:
        prev = row.home
        row.TRIP = trip
        rows.updateRow(row)

    elif row.home == 1 and prev == 0:
        trip += 1
        prev = row.home
        row.TRIP = trip
        rows.updateRow(row)
        rows.next()

    elif row.home == 1 and prev == 1:
        prev = row.home
        row.TRIP = trip
        rows.updateRow(row)
        rows.next()

    row.TRIP = trip
    rows.updateRow(row)


del row, rows

จากนั้นฉันก็เลือกบ้าน = 0 และคำนวณเขตข้อมูลการเดินทางของฉันกลับเป็น 0 ทริปที่สั่งอย่างเรียบร้อย

คำตอบ:


12

สำหรับสิ่งนี้คุณสามารถใช้UpdateCursorซึ่งจะเปิดคลาสหรือตารางคุณลักษณะและขั้นตอนผ่านแต่ละระเบียน (แถว) แบบเพิ่มหน่วย

สคริปต์ด้านล่างใช้งานได้กับข้อมูลการทดสอบนี้

+-----------------------+
| Time| Home_Away|Trip  |
+-----|----------|------+
|  1  |  0       | <nul>|
|  2  |  1       | <nul>|
|  4  |  1       | <nul>|
|  5  |  0       | <nul>|
|  6  |  0       | <nul>|
|  7  |  1       | <nul>|
|  9  |  1       | <nul>|
| 12  |  1       | <nul>|
| 13  |  0       | <nul>|
+-----------------------+

.

import arcpy
fc = r'D:\s\py\pyscratch.gdb\gps_points'

# open the feature class and create the cursor
rows = arcpy.UpdateCursor(fc)

trip = 0
for row in rows:
    if row.HOME_AWAY == 0:
        trip += 1           # start of new trip, increment counter
        row.TRIP = trip     # calc the TRIP field to be current trip#
        rows.updateRow(row) # save
        print "Trip %s started at %s" % (trip, row.TIME)

    # keep cycling through records until HOME_AWAY is not 1
    while row.HOME_AWAY == 1:
        row.TRIP = trip
        rows.updateRow(row)
        rows.next() # move to next record

    # this is for the trailing end of a trip, the second 0
    # print "     %s ended at %s" % (trip, row.TIME)
    row.TRIP = trip
    rows.updateRow(row)

# remove programming objects and data locks
# the data itself is left alone
del row, rows

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

Python จะเพิ่มความหมายโดยอัตโนมัติrows.next()ที่ส่วนท้ายของfor row in rowsบล็อก

สิ่งนี้จะถือว่าความสมบูรณ์ของข้อมูล มันจะเลอะถ้ามีจำนวนคี่ของศูนย์บ้าน / เก็บบันทึกในแถว ( 000หรือ00000) การเดินทางที่ประกอบด้วยเพียงการเริ่มและหยุดเท่านั้นควรจะไม่เป็นไรเช่นลำดับการเดินทาง 3 ครั้ง01..10 00 01..10ซึ่งช่องว่างแสดงถึงช่องว่างระหว่างการเดินทาง กล่าวอีกนัยหนึ่งให้ตรวจสอบผลลัพธ์!


2
+1 คุณต้องทำสิ่งนี้ในเคอร์เซอร์อัปเดต เครื่องมือ CalculateField ไม่รับประกันว่าการบล็อกรหัสจะทำงานเพียงครั้งเดียวดังนั้นtripตัวแปรอาจเริ่มต้นใหม่อีกครั้งตามจำนวนที่กำหนด
Jason Scheirer

วิธีนี้ใช้งานได้ดีในทุกทริปของฉันถูกกำหนดหมายเลขหนึ่งสำหรับทุกจุดในการเดินทางอย่างไรก็ตามทุกจุดที่บ้านจะได้รับหมายเลขใหม่ (เช่นข้อมูลของฉันเริ่มต้นด้วยจุดที่บ้านตอนนี้หมายเลข 1, 2, 3, .. ... 136 จากนั้นทริปแรกของฉันก็คือทั้งหมด 137) มันไม่ใช่เรื่องใหญ่เพราะฉันสามารถย้อนกลับทั้งหมด "บ้าน" ชี้ไปที่ 0 แต่มันจะดีถ้าการเดินทางของฉันเริ่มต้นที่ 1 และมีจำนวนเท่ากันหลังจากนั้น คำแนะนำใด ๆ?
AlmaThom

@ อลิซฉันไม่ได้ทดสอบ แต่สิ่งที่คุณต้องทำคือใส่ความคิดเห็นหรือลบrow.TRIP = tripบรรทัดในแต่ละบล็อกสองบล็อกที่จัดการจุดเริ่มต้นและจุดสิ้นสุดการเดินทาง (และลองคิดดูrows.updateRow(row)สิ่งต่อไปนี้เพราะไม่มีอะไรจะช่วยให้มันรอดได้อีกต่อไป)
matt wilkie

คัดออกความผิดพลาด! สคริปต์ของฉันตอนนี้มีสามส่วน:
AlmaThom

5

วิธีใช้ ArcGIS 10 ภายใต้ "คำนวณฟิลด์ตัวอย่าง" แสดงวิธีการ "คำนวณมูลค่าสะสมของฟิลด์ตัวเลข" นี่จะเป็นการหลอกลวงโดย มีข้อมูลอยู่ในร่างกายตามลำดับเวลาที่ตั้งใจไว้

หากต้องการนำไปใช้โดยตรงให้สลับตัวบ่งชี้ [บ้าน / ออกไป] (ลบออกจาก 1) เพื่อให้ "0" หมายถึง "ไม่อยู่" และ "1" หมายถึง "บ้าน" ฉันเรียกสิ่งนี้ว่า [ไม่อยู่ / บ้าน] ในตัวอย่างด้านล่าง

คำนวณค่าสะสมของมัน - [สะสม] ในตัวอย่าง

เพิ่มหนึ่งและหารสอง - [การเดินทาง] ในตัวอย่าง (เกือบ)

สุดท้ายตั้งค่า [การเดินทาง] เป็นศูนย์สำหรับบันทึก "บ้าน" ทั้งหมด ตอนนี้ผลลัพธ์เห็นด้วยกับตัวอย่าง:

Time Lat Lon Home/Away Trip Away/Home Cumulative 
   1   *   *         0    0         1          1
   2   *   *         1    1         0          1
   3   *   *         1    1         0          1
.... 
  12   *   *         1    1         0          1
  13   *   *         0    0         1          2
  14   *   *         0    0         1          3
  15   *   *         1    2         0          3
  16   *   *         1    2         0          3
.... 
  34   *   *         1    2         0          3
  35   *   *         0    0         1          4
  36   *   *         0    0         1          5
  37   *   *         1    3         0          5
....

สำหรับบันทึกนี่คือรหัสที่นำมาจากความช่วยเหลือ ArcGIS 10 ฉันแก้ไขมันเล็กน้อยดังนั้นมันจะทำทุกขั้นตอนพร้อมกัน: ตอนนี้คุณเพียงแค่เรียกใช้ ควรมีความชัดเจนเมื่อมีการกลับด้าน [Home / Away] และขั้นตอน "เพิ่ม 1 หารด้วย 2"

นิพจน์:

acc(!Home/Away!)

ประเภทนิพจน์:

PYTHON_9.3

บล็อครหัส:

t=0
def acc(i):
  global t
  if t:
    t += (1-i)
  else:
    t = 1
  if i:
    return (t+1)/2
  else:
    return 0

3
สำหรับบันทึกจำนวนมากสิ่งนี้จะไม่ทำงาน codeblock จะรันใหม่ทุกๆสองแสนแถว (พร้อมกับวงจรการรวบรวมขยะเต็ม) ดังนั้นtจะได้รับการรีเซ็ตเป็น 0 ในสถานที่สุ่มที่ดูเหมือนว่า
Jason Scheirer

2
ขอบคุณ @Jason: ฉันไม่ได้ตระหนักถึงข้อผิดพลาดนั้น นั่นเป็นตัวแสดงที่แท้จริง <rant> ฉันคิดว่า ArcGIS ควรจะขยายตัวเพื่อให้ดีขึ้นสำหรับปัญหาของเล่นมากกว่าเล็กน้อย </rant>
whuber

1
ไม่ใช่ข้อผิดพลาดจริงๆแล้วมันเป็นรายละเอียดการใช้งานที่สืบทอดมาจากการใช้งาน VBScript เพื่อพยายามลดการรั่วไหลของหน่วยความจำให้น้อยที่สุด (ผู้ใช้ต่อท้ายรายการสำหรับทุกเร็กคอร์ด แต่ไม่เคยใช้รายการเพื่ออะไรเลย ฉันค่อนข้างแน่ใจว่าฉันได้กำจัดการรีเฟรชใน 11 เพราะมันเป็นพฤติกรรมที่ไม่ชัดเจน แต่ฉันจำไม่ได้
Jason Scheirer

1
@ Jason นั่นคือถ้อยคำใหม่สำหรับฉัน: "รายละเอียดการใช้งาน" คำสละสลวยอื่น ๆ คือ "คุณสมบัติ" และ "พฤติกรรมที่ไม่มีเอกสาร" กุหลาบโดยชื่ออื่น ๆ ...
whuber

2
นี่คือวิธีที่ฉันเห็น @Jason: หน้าช่วยเหลือมีรหัสที่ฉันแสดง ดังนั้นจึงมีการยืนยันโดยนัยในส่วนของ ESRI ที่รหัสทำงาน ตามที่คุณไม่ได้; ภายใต้ลักษณะของคุณสามารถล้มเหลวอย่างมีนัยสำคัญเงียบ ๆ โดยไม่มีการเตือนล่วงหน้าและคาดเดาไม่ได้ นั่นไม่ได้เป็นเพียงข้อบกพร่อง แต่เป็นรูปแบบของข้อผิดพลาดที่เป็นไปได้มากที่สุด "การรีเซ็ตเป็นระยะ" ไม่ใช่ "การแก้ไข" เป็น kluge ที่ทำให้สถานการณ์ IMHO แย่ลงเท่านั้น
whuber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.