ArcGIS for Desktop에서 특정 열만 CSV 파일로 내보내시겠습니까?


15

다각형 피처 클래스를 파일 지오 데이터베이스로 출력하는 arcpy를 사용하여 파이썬 스크립트를 작성했습니다. 속성을 별도의 CSV 파일로 내보내는 기능을 추가했습니다. 이 게시물 에서 찾은 코드를 사용하여 완벽하게 작동합니다. 그러나이 코드는 기능 클래스의 모든 열을 내 보냅니다. : 난 단지 다음과 같은 이름이없는 필드를 내보낼 OBJECTID, Shape또는 Shape_Length.

CSV 파일이 성공적으로 생성 되며 또는 필드 올바르게 포함 되지 않습니다 . 그러나 필드 파일에 기록됩니다. 해당 필드에 기록 된 값의 예는 다음과 같습니다.OBJECTIDShape_LengthShape

<geoprocessing describe geometry object object at 0x28CB90A0>

필드 이름을 반복하면서 놀랍게도 Shape인쇄되지 않는 필드 이름을 인쇄하는 행을 추가했습니다 . ArcGIS가 숨기거나 다른 이름을 지정하는 것과 같습니다.

내 기능의 코드는 다음과 같습니다.

def exportToTable():
    """ 
        Exports the final outputs to a CSV File.
    """

    # Create path to CSV File (note the varialbe outputPath is declared elsewhere).
    CSVFile = outputPath+'\\FinalOutput.csv'
    arcpy.AddMessage("Created CSV File: %s" %CSVFile)

    # Get all fields in FinalOutput feature class and remove unwanted fields.
    fields = arcpy.ListFields('FinalOutput')
    for field in fields:
        arcpy.AddMessage("Field.name is:"+field.name) #not printing 'Shape' field name
        if field.name in (['OBJECTID', 'Shape', 'Shape_Length']):
            fields.remove(field)

    i = 1
    f=open(CSVFile, 'w')
    for field in fields:
        #--write the wanted field names to the output file
        if i < len(fields):
            f.write('%s,' % field.name)
            i += 1
        else:
            f.write('%s\n' % field.name)

    # Use a search cursor to iterate through the rows of the table and write them to the CSV file.
    rows = arcpy.SearchCursor('FinalOutput')
    for row in rows:
        i = 1
        for field in fields:
            if i < len(fields):
                f.write('%s,' % row.getValue(field.name))
                i += 1
            else:
                f.write('%s\n' % row.getValue(field.name))
    del rows
    f.close()

아무도 여기서 무슨 일이 일어나고 있는지 알고 있습니까?


@sgrieve의 조언을 따르도록 코드를 수정했지만 여전히 Shape필드를 작성하고 있었습니다. 그들을 통해 반복 할 때마다 내가 필드 이름을 인쇄 할 수있는 라인을 추가하면 모든 필드가 나열 제외Shape 필드를 아직 여전히 CSV에 기록합니다. 또한 다각형의 X 및 Y 좌표를 두 개의 새 열로 추가했으며 열이 더 이상 열 이름과 정렬되지 않았습니다.

@sgrieve가 필드를 다음과 같이 선언하는 줄을 수정했습니다.

fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry']

새 코드는 정상적으로 작동하지만 문제가 무엇인지 여전히 확신하지 못합니다. 아무도 무슨 일이 있었는지 알고 있습니까? Shape현장 과의 거래는 무엇입니까 ?


여기서 파이썬을 사용해야합니까? 레이어 속성의 필드 탭을 사용하여 원하지 않는 필드를 숨기는 것은 매우 쉽습니다. 그런 다음 열린 속성 테이블에서 데이터를 텍스트 파일 (CSV) 형식으로 내 보내서 원하는 필드 만 가져옵니다.
PolyGeo

예, 스크립트에 추가하고 싶습니다. 클라이언트 요구 사항입니다.
Fezter

다른 사람이 여기서 무슨 일이 일어나고 있는지 알고 있습니까? Shape필드가 파일에 기록 된 이유를 아는 사람이 있습니까? @sgrieve의 코드가 내 코드를 개선했을 수도 있지만 문제를 해결하지 못했습니다.
Fezter

1
이에 대한 나의 접근 방식은 MakeTableView 다음에 TableToTable 을 사용 하는 입니다. 접근 방식이 없으면 셰이프 필드를 "손실"하는 다른 방법 일 수 있습니다.
PolyGeo

답변:


14

10.1에서 소개 된 da 모듈 을 사용하여 코드를 단순화하고 오류를 수정했습니다 . 커서를 사용하여 데이터 읽기를 크게 간소화하고 with명령과 함께이 코드는 이전 파일 액세스 방법을 사용하는 것보다 더 안정적이어야합니다.

모든 필드의 목록을 만든 다음 목록에서 원하지 않는 필드를 제거하여 작동합니다. 이것은 목록 이해 내에서 수행 될 수 있지만 꽤 지저분하고 비 파이썬 적 일 것입니다. 원하는 필드 목록이 작성되면 da 모듈과 함께 사용되어 해당 필드의 모든 데이터를 커서로 읽습니다. 그런 다음 다른 목록 이해를 사용하여 모든 필드를 결합하여 파일을 반복하여 파일에 쓸 수 있습니다. 이것은 0보다 큰 수의 필드에서 작업 할 수 있다는 이점이 있습니다.

import arcpy

fc = 'C:\\antenna_shp\\cables.shp'
CSVFile = 'C:\\antenna_shp\\FinalOutput.csv'

fields = [f.name for f in arcpy.ListFields(fc)]

for i,f in enumerate(fields):
    if f == 'Shape' or f == 'Shape_Length' or f == 'OBJECTID':
        del fields[i]

with open(CSVFile, 'w') as f:
    f.write(','.join(fields)+'\n') #csv headers
    with arcpy.da.SearchCursor(fc, fields) as cursor:
        for row in cursor:
            f.write(','.join([str(r) for r in row])+'\n')

감사합니다 @sgrieve. 게시 한 코드를 복사하면 거의 원하는 CSV 파일을 얻습니다. 그러나 몇 가지 문제가 있습니다. 1. Shape필드 이름은 여전히 ​​기록되지만 모양 값은 기록되지 않습니다. 2. 이제 테이블의 시작 부분에 열을 오른쪽으로 효과적으로 이동시키는 두 개의 새로운 열이 추가되었습니다. 이 열은 다각형의 X 및 Y 좌표 인 것으로 보입니다.
Fezter

3
좋아, 나는 그것을 해결했다고 생각한다. Shape필드 와 관련하여 무언가 가 발생했습니다. 아마도 기하학 유형일 수 있습니다. 그래서 fields다음과 같이 선언하는 줄을 수정했습니다 fields = [f.name for f in arcpy.ListFields('FinalCadastre') if f.type <> 'Geometry'] . 그래도 작동하지 않는 이유는 확실하지 않습니다.
Fezter

2

같은 문제가 발생하여 "모양"필드가 제거되지 않은 이유를 발견했습니다. 이 루프를 사용할 때 :

if field.name in (['OBJECTID', 'Shape', 'Shape_Length']):
    fields.remove(field)

실제로 다른 모든 필드 만 제거한다는 것을 알았습니다. 따라서 먼저 루프를 통과하고 'OBJECTID'를 제거한 다음 'Shape'필드가 목록에서 'OBJECTID'가 이전에 보유한 위치로 이동하므로 다음 필드로 이동하여 'Shape_Length'가됩니다.

따라서 Shape 지오메트리가 제거되지 못하게하는 것이 아니라이 스크립트를 사용할 때 다른 모든 필드를 제거한다는 사실이었습니다.


이 경우에는 elifs가 아닌 여러 if 문을 작성하면 문제가 해결 될 수 있습니다.
Sleep6

루프에서 목록을 변경하는 것은 좋지 않습니다. 예기치 않은 결과가 발생할 수 있습니다. 내가 가진 비슷한 문제에 대한 이 게시물 을 참조하십시오 .
Fezter

0

이것의 한 측면의 핵심은 사용자가 정의하지 않은 객체 ID 및 지오메트리 필드의 적절한 이름을 결정하는 것입니다. 지오메트리 필드의 유형은 Double이며,이 경우에는 도움이되지 않습니다. describe 함수를 사용하면 파일 유형에 따라 이러한 필드의 적절한 이름을 결정할 수 있습니다 (예 : shapefile v 파일 gdb 등).

fc = 'path to my featureclass'
desc = arcpy.Describe(fc)
fields = [f.name for f in arcpy.ListFields(fc) if f.name not in (desc.OIDFieldName, desc.areaFieldName, desc.lengthFieldName), desc.shapeFieldName)]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.