Tính toán thuộc tính mới dựa trên những thay đổi trong thuộc tính khác bằng ArcGIS Desktop với Python?


11

Tôi đang cố gắng phân loại một tập hợp dữ liệu điểm được mã hóa theo thời gian gps thành các hành vi dựa trên các thuộc tính khác nhau.

Tôi đã tạo một thuộc tính là 0 cho nhà và 1 cho đi dựa trên vị trí và bây giờ muốn đánh số các chuyến đi xa nhà (một tập hợp các điểm 01111111111110sẽ là một chuyến vì nó bắt đầu và kết thúc tại nhà). Tôi đã thêm trường thuộc tính sẽ có số chuyến đi, nhưng không biết cách tính toán trường để nó dựa trên trường nhà / sân khách.

Dưới đây là ví dụ về dữ liệu GPS (sử dụng "*" để chỉ ra thông tin không liên quan và chỉ đơn giản là lập chỉ mục thời gian là 1, 2, v.v.), chỉ báo "Nhà / Đi" được mô tả ở trên và chỉ báo chuyến đi mong muốn, "Chuyến đi", mà tôi cần tính toán:

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
....

Tập dữ liệu của tôi quá lớn để tự đi qua và đánh số mỗi chuyến đi trong bảng thuộc tính, vì vậy có cách nào để tính toán trường dựa trên cách đặt thuộc tính home / Away và mỗi "cụm" điểm đi được chỉ định là một chuyến đi?

Đây là những cốt lõi của mã Python có thể trông như thế nào (Tôi không có kinh nghiệm với mã).

Biểu hiện:

trip = Reclass(!home!)

Cơ sở mã hóa:

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  

Sau khi sử dụng kịch bản được đề xuất của matt wilk, tôi đã thực hiện một số thay đổi để chuyến đi đầu tiên của tôi là số 1, lần thứ hai là 2, v.v.

Đây là mã được sửa đổi từ matt:

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

Sau đó, tôi chỉ cần chọn cho nhà = 0 và tính toán trường chuyến đi của tôi trở về 0. Các chuyến đi được sắp xếp gọn gàng.

Câu trả lời:


12

Để làm điều này, bạn có thể sử dụng UpdateCthon , mở lớp tính năng hoặc bảng và từng bước qua từng bản ghi (hàng).

Kịch bản dưới đây hoạt động trên dữ liệu thử nghiệm này

+-----------------------+
| 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

Phần cuối của chuyến đi cũng thực sự được chạy cho phần đầu của chuyến đi, nhưng vì bộ đếm chuyến đi chính xác là calc kép trên hàng bắt đầu chuyến đi không thành vấn đề. Bỏ ghi chú in trong khối đó để xem tôi muốn nói gì.

Python tự động thêm một ẩn rows.next()ở cuối cho for row in rowskhối.

Điều này giả định tính toàn vẹn dữ liệu. Nó sẽ gây rối nếu có một số lượng nhỏ các bản ghi Home / Away bằng 0 liên tiếp ( 000hoặc 00000). Một chuyến đi chỉ bao gồm bắt đầu và dừng lại sẽ ổn, ví dụ: chuỗi 3 chuyến đi 01..10 00 01..10, trong đó các khoảng trống biểu thị khoảng cách giữa các chuyến đi. Nói cách khác, xác nhận kết quả!


2
+1, Bạn PHẢI làm điều này trong một con trỏ cập nhật. Công cụ Tính toán không đảm bảo rằng khối mã sẽ chỉ được chạy một lần, do đó tripbiến có thể được khởi tạo lại bất kỳ số lần tùy ý.
Jason Scheirer

Điều này hoạt động rất tốt ở chỗ tất cả các chuyến đi của tôi đều được gán một số cho tất cả các điểm trong chuyến đi, tuy nhiên tất cả các điểm tại nhà đều được cấp một số mới (tức là dữ liệu của tôi bắt đầu bằng các điểm tại nhà được đánh số 1, 2, 3, .. ... 136 và sau đó chuyến đi đầu tiên của tôi được dán nhãn 137). Đó không phải là một vấn đề lớn vì tôi có thể hoàn nguyên tất cả các điểm "nhà" về 0, nhưng sẽ rất tuyệt nếu các chuyến đi của tôi bắt đầu từ 1 và số lượng đều sau đó. Có lời khuyên nào không?
AlmaThom

@ Alice, tôi đã không kiểm tra, nhưng tất cả những gì bạn cần làm là nhận xét hoặc xóa row.TRIP = tripdòng trong mỗi hai khối xử lý bắt đầu và kết thúc chuyến đi. (và, hãy nghĩ về nó, rows.updateRow(row)tiếp theo, vì không còn gì để cứu ở đó nữa.)
matt wilkie

Sắp xếp ra trục trặc! kịch bản của tôi bây giờ có ba phần:
AlmaThom

5

Trợ giúp ArcGIS 10 trong phần "tính toán ví dụ trường" chỉ cho bạn cách "Tính giá trị tích lũy của trường số". Điều này sẽ thực hiện các mẹo, với điều kiện dữ liệu là theo thứ tự thời gian dự định.

Để áp dụng trực tiếp, hãy đảo ngược chỉ báo [Nhà / Đi] của bạn (trừ đi 1) để "0" có nghĩa là "đi" và "1" có nghĩa là "nhà". Tôi gọi đây là [Sân khách / Nhà] trong ví dụ dưới đây.

Tính giá trị tích lũy của nó - [Tích lũy] trong ví dụ.

Thêm một và chia cho hai - [Chuyến đi] trong ví dụ (gần như).

Cuối cùng, đặt [Chuyến đi] về 0 cho tất cả các bản ghi "nhà". Bây giờ kết quả đồng ý với ví dụ:

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
....

Để ghi lại, đây là mã được lấy từ trợ giúp ArcGIS 10. Tôi đã sửa đổi nó một chút để nó sẽ thực hiện từng bước một: bây giờ bạn chỉ cần chạy nó. Cần phải rõ nơi [Home / Away] bị đảo ngược và nơi xảy ra bước "thêm 1, chia cho 2".

Biểu hiện:

acc(!Home/Away!)

Loại biểu thức:

PYTHON_9.3

Khối mã:

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
Đối với bất kỳ số lượng lớn các hồ sơ này sẽ không hoạt động. Codeblock chạy lại cứ sau vài trăm nghìn hàng (cùng với chu trình thu gom rác đầy đủ), do đó tsẽ được đặt lại về 0 ở những nơi dường như ngẫu nhiên.
Jason Scheirer

2
Cảm ơn, @Jason: Tôi không biết về lỗi đó. Đó là một điểm dừng chương trình thực sự. <rant> Tôi nghĩ ArcGIS có nghĩa vụ phải mở rộng quy mô sao cho nó tốt hơn cho các vấn đề nhỏ về đồ chơi? </ rant>
whuber

1
Không phải là lỗi, đây thực sự là một chi tiết triển khai được kế thừa từ triển khai VBScript để cố gắng giảm thiểu rò rỉ bộ nhớ (ví dụ người dùng thêm vào danh sách cho mỗi bản ghi nhưng không bao giờ thực sự sử dụng danh sách cho bất kỳ thứ gì). Tôi khá chắc chắn rằng tôi đã thoát khỏi việc làm mới vào năm 11 vì đó là hành vi không rõ ràng, nhưng tôi không nhớ.
Jason Scheirer

1
@Jason Đó là một uyển ngữ mới đối với tôi: "chi tiết thực hiện." Các uyển ngữ khác là "tính năng" và "hành vi không có giấy tờ." Một bông hồng bởi bất kỳ tên nào khác ...
whuber

2
Đây là cách tôi nhìn thấy nó, @Jason: chính trang trợ giúp cung cấp mã tôi đã trình bày. Do đó, có một khẳng định ngầm về phần ESRI rằng mã hoạt động. Theo bạn, nó không; thật vậy, dưới đặc tính của bạn, nó có thể thất bại đáng kể, âm thầm, mà không có cảnh báo,không thể đoán trước. Đó không chỉ là một lỗi, đây là dạng lỗi khó nhất có thể. "Thiết lập lại định kỳ" không phải là "sửa chữa", đó là một kluge chỉ làm cho tình hình tồi tệ hơn IMHO.
whuber
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.