Python과 함께 ArcGIS Desktop을 사용하여 다른 속성의 변경 사항을 기반으로 새 속성을 계산합니까?


11

GPS로 인코딩 된 포인트 데이터 세트를 다른 속성을 기반으로 동작으로 분류하려고합니다.

집에 0, 위치에 따라 1에 대한 속성을 작성했으며 이제 집에서 멀리 떨어진 여행의 번호를 매기 01111111111110려고합니다 (집에서 시작하여 끝났기 때문에 한 세트의 여행이됩니다). 여행 번호가 표시되는 속성 필드를 추가했지만 필드를 계산하는 방법을 모르므로 홈 / 어웨이 필드를 기반으로합니다.

다음은 GPS 데이터 ( 예 : 관련없는 정보를 나타 내기 위해 "*"를 사용하고 단순히 1, 2 등의 인덱싱 시간 등), 위에서 설명한 "Home / Away"표시기 및 원하는 트립 표시기, "Trip", 계산해야합니다 :

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

내 데이터 세트가 너무 커서 속성 테이블에서 수동으로 이동하고 각 여행에 번호를 매길 수 없으므로 홈 / 어웨이 속성이 정렬되는 방식에 따라 필드를 계산할 수있는 방법이 있습니까? 여행?

이것들은 파이썬 코드가 어떻게 생겼는지의 핵심입니다 (코드에 대해서는 경험이 없습니다).

표현:

trip = Reclass(!home!)

코드 블록 :

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 등으로 변경되었습니다.

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

그런 다음 home = 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

트립 블록의 마지막 끝은 실제로 트립의 시작을 위해 실행되지만 트립 카운터가 정확하기 때문에 시작-행의 이중 계산은 중요하지 않습니다. 해당 블록에서 print 문의 주석을 해제하여 의미하는 바를 확인하십시오.

파이썬 rows.next()for row in rows블록 끝에 자동으로 암시 적을 추가합니다 .

이것은 데이터 무결성을 가정합니다. 행 ( 000또는 00000)에 홀수의 홈 / 어웨이 기록이 홀수이면 엉망이됩니다 . 단지 시작과 중지로 구성되어 여행은 해야한다 , 알았지 예를 들어의 3 여행 순서가 될 01..10 00 01..10공간이 여행 사이의 간격을 나타낸다. 즉, 결과를 검증하십시오!


2
+1, 업데이트 커서에서이 작업을 수행해야합니다. CalculateField 도구는 코드 블록이 한 번만 실행되도록 보장하지 않으므로 trip임의의 횟수로 변수를 다시 초기화 할 수 있습니다.
Jason Scheirer 2016 년

이것은 내 모든 여행에 여행의 모든 ​​포인트에 대해 하나의 번호가 할당되어 있다는 점에서 효과적입니다. 그러나 집의 모든 포인트에는 새로운 번호가 부여됩니다 (즉, 데이터는 현재 1, 2, 3,.로 번호가 지정된 집의 포인트로 시작합니다 .. ... 136 그리고 첫 여행은 모두 137로 표시되어 있습니다. 모든 "홈"포인트를 0으로 되돌릴 수 있기 때문에 큰 문제는 아니지만 내 여행이 1에서 시작하여 그 이후로 균등하게 번호를 매기는 것이 좋을 것입니다. 어떤 충고?
AlmaThom

@Alice, 테스트하지는 않았지만 row.TRIP = trip여행 시작과 끝을 처리하는 두 블록 각각 에서 줄을 주석 처리하거나 삭제하기 만하면 됩니다. (그리고 rows.updateRow(row)더 이상 거기에 저장할 것이 없기 때문에 다음 에 생각하십시오 .)
matt wilkie

결함을 정리했습니다! 내 스크립트는 세 부분으로 구성되어 있습니다 :
AlmaThom

5

"필드 예제 계산"의 ArcGIS 10 도움말은 "숫자 필드의 누적 값을 계산하는 방법"을 보여줍니다. 이 트릭을 할 것, 데이터가 시간적 순서를위한 물리적에 제공했다.

직접 적용하려면 "0"은 "멀리"를, "1"은 "홈"을 나타내도록 [Home / Away] 표시기를 뒤집습니다 (1에서 빼기). 아래 예에서 이것을 [Away / Home]이라고합니다.

예제에서 누적 값-[누적]을 계산합니다.

예를 하나 더하고 두 개로 나눕니다 (거의).

마지막으로 모든 "홈"레코드에 대해 [Trip]을 0으로 설정하십시오. 이제 결과는 예제와 일치합니다.

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 도움말에서 가져온 코드는 다음과 같습니다. 한 번에 모든 단계를 수행하도록 약간 수정했습니다. 이제 실행하기 만하면됩니다. [홈 / 어웨이]가 반전되는 위치와 "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
많은 수의 레코드에 대해서는 작동하지 않습니다. 코드 블록은 전체 가비지 수집주기와 함께 수십만 행마다 다시 실행되므로 t임의로 임의의 위치에서 0으로 다시 설정됩니다.
Jason Scheirer 2016 년

2
감사합니다, @Jason : 나는 그 버그를 몰랐습니다. 그것은 진정한 쇼 스토퍼입니다. <rant> 난 작은 장난감 문제 이상을 위해 ArcGIS가 확장되어야한다고 생각 했습니까? </ rant>
whuber

1
버그가 아니라 실제로 메모리 누수를 최소화하기 위해 VBScript 구현에서 상속 된 구현 세부 사항입니다 (사용자는 모든 레코드의 목록에 추가하지만 실제로는 아무것도 목록을 사용하지 않습니다). 분명하지 않은 동작이기 때문에 11에서 새로 고침을 제거했다고 확신하지만 기억하지 못합니다.
Jason Scheirer 2016 년

1
@Jason 저에게있어 새로운 표현법입니다. "구현 세부 사항" 다른 형태는 "기능"과 "언급되지 않은 행동"입니다. 다른 이름으로 장미 ...
whuber

2
@Jason : 도움말 페이지 자체 에서 내가 제시 한 코드를 제공합니다. 따라서 코드가 작동 한다는 ESRI 부분에 대한 암시 적 주장이 있습니다. 당신에 따르면 그렇지 않습니다. 실제로, 당신의 특성화 하에서 그것은 경고없이, 그리고 예측할 수 없이 상당히, 조용히 실패 할 수 있습니다 . 그것은 단지 버그가 아니라 가능한 가장 초기 형태의 버그입니다. "정기 재설정"은 "수정"이 아니며 상황을 IMHO 만 악화시키는 주요 요인입니다.
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.