Processing math: 100%

5 votos

ArcPy - Obtener el número de puntos intersectados basados ​​en el atributo

Estoy tratando de conseguir un número de puntos en polígonos basándose en los valores de fila, y escríbelos en la tabla de atributos de los polígonos. He polígono (Zonas), y los puntos (Objetos con campos tales como escuelas, mercados, hoteles, tiendas) que se encuentran en los polígonos. Quiero seleccionar los puntos en función de sus atributos (por ejemplo yo quiero saber cuántas escuelas hay en mi polígono, y escribir en un campo. y repita el proceso para otros atributos de cómo muchos de los hoteles/mercados/tiendas hay en el polígono de las zonas, etc).

No era una pregunta similar, y esta respuesta fue buena para Contar el número de atributos únicos valores de campo, pero sólo para la selección de la ubicación. El script devuelve el recuento de todos los número de objetos en el polígono de las zonas, y no estaba basada en atributos, justo en el lugar.

Me las arreglé para modificar la secuencia de comandos, desde el enlace. Este es el código, y me da resultado, la suma de todos los puntos, y fue escrita en fila:

import arcpy
Objects = r'D:\GIS_Temp\Points.shp'
Zones = r'D:\GIS_Temp\Zones.shp'
Objects_lyr = arcpy.MakeFeatureLayer_management(Objects,r'in_memory\Objects_lyr')
Zones_lyr = arcpy.MakeFeatureLayer_management(Zones,r'in_memory\Zones_lyr')
fields = ['Descrip','Point_Sum']
with arcpy.da.UpdateCursor(Zones_lyr,fields) as cur:
    for row in cur:
        Zones = row[0]
        where = '"Descrip" = \'{}\''.format(Zones)
        arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',where)
        arcpy.SelectLayerByLocation_management(Objects_lyr,'INTERSECT',Zones_lyr)        
        Point_Sum = int(arcpy.GetCount_management(Objects_lyr).getOutput(0)) 
        row[1] = Point_Sum
        cur.updateRow(row)
print('Operation complete.')

Y este es el resultado:

enter image description here

Pero quiero actualizar Zonas, basado en la intersección de los Objetos, sino que se basa en los atributos, y la actualización de las filas en las Zonas, con número de intersección de objetos (Hoteles, Tiendas, Mercados, Escuelas).

Lo que me estoy perdiendo en mi código. Supongo que tiene algo que ver con la selección por atributos, o con bucle, como se sugiere en los comentarios, debo crear bucle dentro de un bucle, pero no estoy seguro de donde ponerlo, y cómo. Entiendo por qué, pero no sé cómo.

EDITAR:

Traté de modificar el código, como este, por lo que la selección hecha por el atributo de forma individual y tratar de ponerlas en su propia fila, pero no hubo suerte. Código ok, no hay ningún error, pero no actualiza nada.

Es allí cualquier modificación a este, lo que podría acelerar mi flujo de trabajo, en caso de tener más de cuatro valores (como en este ejemplo, escuelas, etc)? Este es el código:

import arcpy
Objects = r'D:\GIS_Temp\Points.shp'
Zones = r'D:\GIS_Temp\Zones.shp'
ObjectsSCHOOLS_lyr = arcpy.MakeFeatureLayer_management(Objects,r'SCHOOLS', "\"Name\" = 'Schools'")
ObjectsMARKETS_lyr = arcpy.MakeFeatureLayer_management(Objects,r'MARKETS', "\"Name\" = 'Markets'")
ObjectsHOTELS_lyr = arcpy.MakeFeatureLayer_management(Objects,r'HOTELS', "\"Name\" = 'Hotels'")
ObjectsSHOPS_lyr = arcpy.MakeFeatureLayer_management(Objects,r'SHOPS', "\"Name\" = 'Shops'")
Zones_lyr = arcpy.MakeFeatureLayer_management(Zones,r'in_memory\Zones_lyr')
fields = ['Descrip','Schools_Nr', 'Markets_Nr', 'Hotels_Nr', 'Shops_Nr']
with arcpy.da.UpdateCursor(Zones_lyr,fields) as cur:
    for row in cur:
        state = row[0]
        where = '"Descrip" = \'{}\''.format(Zones)
        arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',where)
        arcpy.SelectLayerByLocation_management(ObjectsSCHOOLS_lyr,'INTERSECT',Zones_lyr)        
        Schools_Nr = int(arcpy.GetCount_management(ObjectsSCHOOLS_lyr).getOutput(0)) 
        row[1] = Schools_Nr
        cur.updateRow(row)
    for row in cur:
        state = row[0]
        where = '"Descrip" = \'{}\''.format(Zones)
        arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',where)
        arcpy.SelectLayerByLocation_management(ObjectsMARKETS_lyr,'INTERSECT',Zones_lyr)        
        Markets_Nr = int(arcpy.GetCount_management(ObjectsMARKETS_lyr).getOutput(0)) 
        row[1] = Markets_Nr
        cur.updateRow(row)
    for row in cur:
        state = row[0]
        where = '"Descrip" = \'{}\''.format(Zones)
        arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',where)
        arcpy.SelectLayerByLocation_management(ObjectsHOTELS_lyr,'INTERSECT',Zones_lyr)        
        Hotels_Nr = int(arcpy.GetCount_management(ObjectsHOTELS_lyr).getOutput(0)) 
        row[1] = Hotels_Nr
        cur.updateRow(row)
    for row in cur:
        state = row[0]
        where = '"Descrip" = \'{}\''.format(Zones)
        arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',where)
        arcpy.SelectLayerByLocation_management(ObjectsSHOPS_lyr,'INTERSECT',Zones_lyr)        
        Shops_Nr = int(arcpy.GetCount_management(ObjectsSHOPS_lyr).getOutput(0)) 
        row[1] = Shops_Nr
        cur.updateRow(row)         
print('Operation complete.')

3voto

Julie Puntos 36

Puede consultar el código siguiente, lo probé. Espero que te ayude.

 import arcpy

arcpy.env.overwriteOutput = True

Objects = r'H:\Input\Points.shp'
Zones = r'H:\Input\Zones.shp'

# Get unique field values (Define a function)
def getUniqueValues(fc,field_name):
    unique_Values = set()
    rows = arcpy.SearchCursor(fc)
    for row in rows:
        unique_Values.add(row.getValue(field_name))
    del row,rows
    return unique_Values

# Get values count by dictionary
def getValuesCount(lyr,fieldName,lst_Values):
    dic_Values_Count = {}
    for value in lst_Values:
        dic_Values_Count[value] = 0
    rows = arcpy.SearchCursor(lyr)
    for row in rows:
        value = row.getValue(fieldName)
        dic_Values_Count[value] += 1
    del row,rows
    return dic_Values_Count

# Get Names list
set_obj_Names = getUniqueValues(Objects,'Name')
# Get Unique Zone_Name
set_zone_Names = getUniqueValues(Zones,'Zone_Name') # If you want to use Descrip, you can replace 'Zone_Name to 'Descrip'

# Delete exists names
obj_Names = list(set_obj_Names)
obj_Names.append('Point_Sum')
arcpy.DeleteField_management(Zones,obj_Names)

# Add need fields
for field_Name in obj_Names:
    field_Type = "TEXT"
    if field_Name == 'Point_Name':
        field_Type = 'SHORT'
    arcpy.AddField_management(Zones,field_Name,field_Type)

# Main

Objects_lyr = arcpy.MakeFeatureLayer_management(Objects,r'Objects_lyr')
Zones_lyr = arcpy.MakeFeatureLayer_management(Zones,r'Zones_lyr')
# Get Count and save it into temp dictionary
whereField = arcpy.AddFieldDelimiters(Zones,'Zone_Name')
dic_ZoneInfo = {}
for zone_Name in set_zone_Names:
    whereClause = whereField + " = '" + zone_Name + "'"
    arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',whereClause)
    arcpy.SelectLayerByLocation_management(Objects_lyr,'INTERSECT',Zones_lyr)
    Point_Sum  =  int(arcpy.GetCount_management(Objects_lyr).getOutput(0))
    dicTemp = getValuesCount(Objects_lyr,'Name',obj_Names)
    dicTemp['Point_Sum'] = Point_Sum
    dic_ZoneInfo[zone_Name] = dicTemp
del Objects_lyr,Zones_lyr

# Update Counts and Point_Sum
updateRows = arcpy.UpdateCursor(Zones)
for row in updateRows:
    zone_Name = row.getValue('Zone_Name')
    dic_Values_Count = dic_ZoneInfo[zone_Name]
    new_Fields = obj_Names
    new_Fields.append('Point_Sum')
    for field_Name in new_Fields:
        row.setValue(field_Name,dic_Values_Count[field_Name])
    updateRows.updateRow(row)
del row,updateRows
 

Introduzca aquí la descripción de la imagen

0voto

Dean7 Puntos 69

Como tuve unos errores en el código, he quitado el

del fila, filas

a partir de la línea 20, que es la parte del código para obtener los valores de recuento. Ahora parece estar funcionando. Si yo no eliminar esta parte, me sale este error:

Error en tiempo de ejecución Traceback (la mayoría de llamada reciente pasado): Archivo "", línea 41, en File "", line 20, en getValuesCount UnboundLocalError: variable local 'fila' hace referencia a antes de la asignación de

Pero, todo lo demás se aceptan respuesta está trabajando. Tal vez esto es algo que en mi código, pero esto es de trabajo, al menos para mí:

import arcpy
arcpy.env.overwriteOutput = True
Objects = r'D:\GIS_Temp\Points.shp'
Zones = r'D:\GIS_Temp\Zones.shp'
def getUniqueValues(fc,field_name):
    unique_Values = set()
    rows = arcpy.SearchCursor(fc)
    for row in rows:
        unique_Values.add(row.getValue(field_name))
    del row,rows
    return unique_Values
def getValuesCount(lyr,fieldName,lst_Values):
    dic_Values_Count = {}
    for value in lst_Values:
        dic_Values_Count[value] = 0
    rows = arcpy.SearchCursor(lyr)
    for row in rows:
        value = row.getValue(fieldName)
        dic_Values_Count[value] += 1
    # here was delete row rows part, and it was deleted and now it works
    return dic_Values_Count
set_obj_Names = getUniqueValues(Objects,'Name')
set_zone_Names = getUniqueValues(Zones,'Zone_Name')
obj_Names = list(set_obj_Names)
obj_Names.append('Point_Sum')
arcpy.DeleteField_management(Zones,obj_Names)
for field_Name in obj_Names:
    field_Type = "TEXT"
    if field_Name == 'Point_Name':
        field_Type = 'SHORT'
    arcpy.AddField_management(Zones,field_Name,field_Type)
Objects_lyr = arcpy.MakeFeatureLayer_management(Objects,r'Objects_lyr')
Zones_lyr = arcpy.MakeFeatureLayer_management(Zones,r'Zones_lyr')
whereField = arcpy.AddFieldDelimiters(Zones,'Zone_Name')
dic_ZoneInfo = {}
for zone_Name in set_zone_Names:
    whereClause = whereField + " = '" + zone_Name + "'"
    arcpy.SelectLayerByAttribute_management(Zones_lyr,'NEW_SELECTION',whereClause)
    arcpy.SelectLayerByLocation_management(Objects_lyr,'INTERSECT',Zones_lyr)
    Point_Sum  =  int(arcpy.GetCount_management(Objects_lyr).getOutput(0))
    dicTemp = getValuesCount(Objects_lyr,'Name',obj_Names)
    dicTemp['Point_Sum'] = Point_Sum
    dic_ZoneInfo[zone_Name] = dicTemp
del Objects_lyr,Zones_lyr
updateRows = arcpy.UpdateCursor(Zones)
for row in updateRows:
    zone_Name = row.getValue('Zone_Name')
    dic_Values_Count = dic_ZoneInfo[zone_Name]
    new_Fields = obj_Names
    new_Fields.append('Point_Sum')
    for field_Name in new_Fields:
        row.setValue(field_Name,dic_Values_Count[field_Name])
    updateRows.updateRow(row)
del row,updateRows

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