2014-11-11 3 views
0

nMSLINK 필드와 DIAMETER 필드가있는 ESRI Point Shape 파일이 있습니다. MSLINK는 공간 조인으로 인해 고유하지 않습니다. 달성하고 싶은 것은 셰이프 파일에서 유일한 MSLINK와 가장 작은 DIAMETER 값을 가진 피처 만 다른 필드의 해당 값과 함께 유지하는 것입니다. 나는 이것을 달성하기 위해 searchcursor를 사용할 수있다. (모든 피쳐를 반복하고 따르지 않는 각 피쳐를 제거하지만 이것은 오래 걸린다 (> 75000 피쳐). numpy가 ArcMap/arcpy에서 더 빠르게 트릭을 수행 할 수 있는지 궁금하다.arcpy/numpy로 각 고유 ID에 대해 가장 작은 값 유지

+1

최소한의 예를 위해 코드를 추가 할 수 있습니까? – atomh33ls

+0

'# 선택한 각 MSLINK' '행 arcpy.SearchCursor = ('Afsluiters_Leidingen '' '' '' ','MSLINK a 및 MIDDELLIJN_INWENDIG D ')에 대한 최소 MIDDELLIJN_INWENDIG 행 행' '' \t'DIAM = row.MIDDELLIJN_INWENDIG' \t'딕셔너리 [row.MSLINK = diam' '딕셔너리에 대한 키'' \t arcpy.SelectLayerByAttribute_management ('Afsluiters_Leidingen', 'NEW_SELECTION', 'MSLINK ='+ STR (key) + 'AND NOT MIDDELLIJN_INWENDIG ='+ str (dict [key]))' \t'arcpy.DeleteFeatures_management ('Afsluiters_Leidingen') ' –

+0

이 함수는 작동하지만 큰 쉐이프 파일의 경우 수십 년이 걸린다. –

답변

0

arcgis와 상호 작용하는 대신 메모리에서 작업하는 경우, 이런 종류의 처리가 확실히 빠를 것이라고 생각합니다. 예를 들어, 모든 행을 먼저 파이썬 개체에 넣으면 (아마도 namedtuple이 좋은 옵션이 될 것입니다. (MSLINK)가 반복되는 행이 많은 경우 가장 빠른 방법은 다음 중 하나 일 것입니다. 가장 빠른 방법은 다음과 같습니다. 새로운 레이어에서 필요합니다. 또는 b) 삭제할 행이 전체 행과 비교할 때 몇 개이면 삭제가 더 빠릅니다.

a) 포인트 좌표를 포함하여 모든 필드를 튜플에 페치해야 새로운 피쳐 클래스를 만들고 새 행을 삽입 할 수 있습니다.

# Example of Variant a: 

from collections import namedtuple 

# assuming the following: 
source_fC# contains name of the fclass 
the_path # contains path to the shape 
cleaned_fC# the name of the cleaned fclass 


# use all fields of source_fc plus the shape token to get a touple with xy 
# coordinates (using 'mslink' and 'diam' here to simplify the example) 
fields = ['mslink', 'diam', 'field3', ... ] 
all_fields = fields + ['[email protected]'] 

# define a namedtuple to hold and work with the rows, use the name 'point' to 
# hold the coordinates-tuple 
Row = namedtuple('Row', fields + ['point']) 
data = [] 
with arcpy.da.SearchCursor(source_fc, fields) as sc: 
    for r in sc: 
     # unzip the values from each row into a new Row (namedtuple) and append 
     # to data 
     data.append(Row(*r)) 

# now just delete the rows we don't want, for this, the easiest way, is probably 
# to order the tuple first after MSLINK and then after the diamater... 
data = sorted(data, key = lambda x : (x.mslink, x.diam)) 

# ... now just keep the first ones for each mslink 
to_keep = [] 
last_mslink = None 
for d in data: 
    if last_mslink != d.mslink: 
     last_mslink = d.mslink 
     to_keep.append(d) 

# create a new feature class with the same fields as the source_fc 
arcpy.CreateFeatureclass_management(
     out_path=the_path, out_name=cleaned_fc, template=source_fc) 
with arcpy.da.InsertCursor(cleaned_fc, all_fields) as ic: 
    for r in to_keep: 
     ic.insertRow(*r) 

그리고 b) 대신에 3 개의 필드, 고유 ID, MSLINK 및 직경을 가져옵니다. 그런 다음 삭제 목록을 만듭니다 (여기서는 고유 한 ID 만 필요합니다). 그런 다음 피쳐 클래스를 다시 반복하고 삭제 목록에서 ID가있는 행을 삭제합니다. 확실하게 필자는 먼저 피쳐 클래스를 복제하고 복사본을 만들 것입니다.

0

이 작업을보다 효율적으로 수행하려면 몇 가지 단계를 수행 할 수 있습니다. 무엇보다도 커서의 이전 버전과 달리 데이터 분석가 커서를 사용하면 프로세스 속도가 빨라집니다. 이것은 당신이 10.1 또는 그 이상에서 일하고 있다고 가정합니다. 그런 다음 요약 통계, 즉 사례 필드를 기반으로 최소값을 찾는 기능을 사용할 수 있습니다. 귀하의 경우 사례 입력란은 nMSLINK가됩니다.

아래의 코드는 모든 고유 'nMSLINK'값과 해당 최소 'DIAMETER'값이있는 통계표를 만듭니다. 그런 다음 테이블 선택을 사용하여 'FREQUENCY'필드가 1이 아닌 테이블의 행만 선택합니다. 여기에서 새 테이블을 반복하여 최종 sql 문을 구성하는 문자열 목록을 작성하기 시작합니다.

("nMSLINK" = 'value1' AND "DIAMETER" <> 624.0) OR ("nMSLINK" = 'value2' AND "DIAMETER" <> 1302.0) OR ("nMSLINK" = 'value3' AND "DIAMETER" <> 1036.0) ... 

는 SQL 직경 값이 최소 수없는 경우 nMSLINK 값이 고유하지 않은 행을 선택이 반복 후, 나는 이런 식으로 뭔가를 보이는 SQL 문자열을 생성하는 기능을 결합 파이썬을 사용합니다. 이 SQL을 사용하여 속성별로 선택하고 선택된 행을 삭제합니다.

이 SQL 문은 피쳐 클래스가 파일 지오 데이터베이스에 있다고 가정하고 'nMSLINK'는 문자열 필드이고 'DIAMETER'는 숫자 필드입니다.

코드 다음 입력이 있습니다

기능 : 몇 중간 테이블을 일시적으로

TempTableName1를 저장할 폴더 :

작업 영역을 분석 할 수있는 기능을 하나 개의 임시 테이블의 이름을 .

TempTableName2는 :

: 제 2 임시 테이블

필드 1에 대한 이름은

필드 2는

코드의 가장 낮은 찾을하고자하는 숫자 값으로 필드를 = 고유하지 않은 필드 =

# Import modules 
from arcpy import * 
import os 
# Local variables 

#Feature to analyze 
Feature = r"C:\E1B8\ScriptTesting\Workspace\Workspace.gdb\testfeatureclass" 
#Workspace to export table of identicals 
Workspace = r"C:\E1B8\ScriptTesting\Workspace" 
#Name of temp DBF table file 
TempTableName1 = "Table1" 
TempTableName2 = "Table2" 

#Field names 
Field1 = "nMSLINK" #nonunique 
Field2 = "DIAMETER" #field with numeric values 

#Make layer to allow selection 
MakeFeatureLayer_management (Feature, "lyr") 

#Path for first temp table 
Table = os.path.join (Workspace, TempTableName1) 

#Create statistics table with min value 
Statistics_analysis (Feature, Table, [[Field2, "MIN"]], [Field1]) 

#SQL Select rows with frequency not equal to one 
sql = '"FREQUENCY" <> 1' 
# Path for second temp table 
Table2 = os.path.join (Workspace, TempTableName2) 
# Select rows with Frequency not equal to one 
TableSelect_analysis (Table, Table2, sql) 

#Empty list for sql bits 
li = [] 

# Iterate through second table 
cursor = da.SearchCursor (Table2, [Field1, "MIN_" + Field2]) 
for row in cursor: 
    # Add SQL bit to list 
    sqlbit = '("' + Field1 + '" = \'' + row[0] + '\' AND "' + Field2 + '" <> ' + str(row[1]) + ")" 
    li.append (sqlbit) 
del row 
del cursor 

#Create SQL for selection of unwanted features 
sql = " OR ".join (li) 
print sql 
#Select based on SQL 
SelectLayerByAttribute_management ("lyr", "", sql) 

#Delete selected features 
DeleteFeatures_management ("lyr") 

#delete temp files 
Delete_management ("lyr") 
Delete_management (Table) 
Delete_management (Table2) 

직선형 커서보다 빠릅니다. 이 말이 맞는다면 알려주십시오. 행운을 빕니다!

+0

매우 큰 데이터 세트로 메소드를 테스트했는데 신뢰할 수 없습니다. 특히 최종 SQL 문자열이 너무 커져 문제가 발생합니다. 나는 또한 andzep의 방법을 시험해 보았다. 나는 그의 방법을 추천한다. –