4 votos

¿Cuál es la forma más eficiente de buscar registros de tipo NULL en una geodatabase?

El problema: tengo una geodatabase con varios conjuntos de datos y muchas más clases de entidad dentro. Los campos dentro de las clases de entidad se han poblado a través de combinaciones con los archivos de forma manual y ediciones. Muchas veces los campos de cadena se convertirá rellena con espacios en blanco (es decir,", '', '', etc) o la cadena "Null", y los campos numéricos se convertirá rellena con un cero (0). Me gustaría encontrar estos archivos y reemplazarlos con un verdadero valor NULL. Tengo el siguiente código, el cual se utiliza un UpdateCursor, pero todavía muy lento y no captura todos los NULL-como registros. ¿Alguien sabe de otras formas de realizar esta tarea?

GDB = arcpy.GetParameterAsText(0) #input geodatabase
arcpy.env.workspace = GDB
datasetList = arcpy.ListDatasets() #list datasets

for dataset in datasetList:
        arcpy.env.workspace = os.path.join(GDB, dataset)
        fcList = arcpy.ListFeatureClasses()
        for fc in fcList:
                arcpy.AddMessage("Processing %s..." % fc)
                #count features
                arcpy.MakeTableView_management(fc, "tempTableView")
                count = int(arcpy.GetCount_management("tempTableView").getOutput(0))
                if count > 0:
                        fieldList = arcpy.ListFields(fc)
                        for field in fieldList:
                                arcpy.AddMessage("...%s" % field.name)
                                rows = arcpy.UpdateCursor(fc)
                                for row in rows:
                                        count = 0
                                        if row.isNull(field.name):
                                                continue # if already null
                                        elif field.type == "Text":
                                                value = row.getValue(field.name)
                                                if value.lstrip(' ') == '' or value.lower() == '<null>': # looks for whitespace or '<null>'
                                                        row.setNull(field.name)
                                                        count += 1
                                        elif field.type == "ShortInteger" or field.type == "LongInteger" or field.type == "Float" or field.type == "Double":
                                                value = row.getValue(field.name)
                                                if value == 0:
                                                        row.setNull(field.name)
                                                        count += 1
                                        if count > 0: # update row if records have changed
                                                rows.updateRow(row)
                                del rows
                else:
                        arcpy.AddMessage("...NO RECORDS FOUND.")

5voto

Örjan Jämte Puntos 3127

Ya estoy más familiarizado con 10.1+, cursores y en general son mucho mejores en la da módulo, he aquí una posible solución. Actualmente, se está creando un cursor cada vez que cambie los campos, lo que significa que están teniendo un éxito allí. Además, se comprobar el tipo de campo para cada registro en lugar de usar el tipo de campo una vez para filtrar inicialmente.

He cambiado la forma de la Null valores son comprobados, pero no he probado a fondo, se compruebe que todos los valores posibles. Para el pequeño conjunto de datos de ejemplo que yo tenía, se trabajó @ 10.2.2.

#Return None if the value needs to be changed, else return the value
def nullify(value):
    x = value    
    if value is not None: #True null fields are read as None types
        if type(value) == str:
            if value.lstrip(' ') == '' or value.lower() == '<null>':
                x = None
        else: 
            if value == 0:
                x = None 

return x

#We're only interested in some fields
ftypes = ("String", "SmallInteger", "Integer", "Double")
fieldList = [f.name for f in arcpy.ListFields(fc) if f.type in ftypes]

with arcpy.da.UpdateCursor(fc, fieldList) as rows:
    for row in rows:            
        nulled = map(nullify, row)
        if row != nulled: #Only update if the row actually needs to be changed.
            rows.updateRow(nulled)

1voto

aditya Puntos 111

En lugar de utilizar un cursor para buscar en todos los campos para cada registro (uno a la vez utilizando el cursor), ¿qué acerca de la consulta de todos los registros de un solo campo (al por mayor) el uso de "Seleccionar Por Atributos" de la herramienta y, a continuación, calcular todos los registros seleccionados con "Calcular el Campo" herramienta? Después podría recorrer cada campo en Python?

Mediante el código como una base, yo se burló de esta (que funciona en un Archivo GDB. Usted tendrá que corregir la sintaxis del campo por tipo de base de datos basada en SQL referencia para la consulta de las expresiones que se utilizan en ArcGIS. He dejado algunas pruebas y declaraciones de la CalculateField declaración de comentarios así que usted puede probar antes de romper algo.

También me pidió prestado el código para obtener su featureclasses de @gotchula respuesta a Listado de todas las clases de entidad en la Geodatabase de Archivos, incluyendo dentro de la característica de los conjuntos de datos?

import arcpy
import os

GDB = arcpy.GetParameterAsText(0) #input geodatabase
arcpy.env.workspace = GDB

def listFcsInGDB():
    ''' set your arcpy.env.workspace to a gdb before calling '''
    #http://gis.stackexchange.com/questions/5893/listing-all-feature-classes-in-file-geodatabase-including-within-feature-datase
    for fds in arcpy.ListDatasets('','feature') + ['']:
        for fc in arcpy.ListFeatureClasses('','',fds):
            yield os.path.join(arcpy.env.workspace, fds, fc)

fcList = listFcsInGDB()

for fc in fcList:
    arcpy.AddMessage("Processing %s..." % fc)
    #count features
    tempTableView = arcpy.MakeTableView_management(fc, "tempTableView")
    count = int(arcpy.GetCount_management("tempTableView").getOutput(0))
    if count > 0:
        fieldList = arcpy.ListFields(fc)
        for field in fieldList:
            arcpy.AddMessage("...{0} ({1})".format(field.name, field.type) )
            if field.type == "Text" or field.type == "String":
                whereclause = "\"{0}\" = '' or \"{0}\" = ' ' or \"{0}\" = '  ' or \"{0}\" is NULL".format(field.name)
                #arcpy.AddMessage("Searching for " +field.name+ " where " +whereclause)
                arcpy.SelectLayerByAttribute_management("tempTableView", "NEW_SELECTION", whereclause)
                #featcount = str(arcpy.GetCount_management("tempTableView").getOutput(0))
                #arcpy.AddMessage(featcount)
                #arcpy.CalculateField_management(tempTableView,"{0}".format(field.name), "NULL")
                count += 1
            elif field.type == "Integer" or field.type == "ShortInteger" or field.type == "SmallInteger" or field.type == "LongInteger" or field.type == "Short" or field.type == "Long" or field.type == "Float" or field.type == "Single" or field.type == "Double" or field.type == "Numeric":
                whereclause = "\"{0}\" = 0 or \"{0}\" is NULL".format(field.name)
                #arcpy.AddMessage("Searching for " +field.name+ " where " +whereclause)
                arcpy.SelectLayerByAttribute_management("tempTableView", "NEW_SELECTION", whereclause)
                #featcount = str(arcpy.GetCount_management("tempTableView").getOutput(0))
                #arcpy.AddMessage(featcount)
                #arcpy.CalculateField_management(tempTableView,"{0}".format(field.name), "0")
                count += 1
            else:
                ##Not an editable field
                arcpy.AddMessage("Not an editable field type of: " + field.type)
                pass

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X