14 votos

Eficiente de encontrar el 1er fin de vecinos de 200k de polígonos

Para cada uno de los 208,781 Censo de grupos de bloques, me gustaría recuperar el FIPS IDs de todos los de su 1er fin de vecinos. Tengo todos los de TIGRE límites descargado y se fusionaron en un solo 1GB shapefile.

He intentado un ArcPython secuencia de comandos que utiliza SelectLayerByLocation para BOUNDARY_TOUCHES en su núcleo, pero se tarda más de 1 segundo para cada grupo de bloques que es más lento de lo que me gustaría. Esto es, incluso después de que el límite de la SelectLayerByLocation de búsqueda para grupos de bloques en el mismo estado. He encontrado este script, pero también utiliza SelectLayerByLocation internamente por lo que no es más rápido.

La solución no tiene que ser de Arco, estoy abierto a otros paquetes, a pesar de que me siento más cómodo de codificación con Python.

8voto

Justin Walgran Puntos 552

Para una solución evitando ArcGIS, uso pysal. Usted puede obtener los pesos directamente de los shapefiles el uso de:

w = pysal.rook_from_shapefile("../pysal/examples/columbus.shp")

o

w = pysal.queen_from_shapefile("../pysal/examples/columbus.shp")

La cabeza de la documentación para más información.

3voto

Sólo una actualización. Después de seguir Whuber consejos, me encontré con que el Generar Matriz de Ponderaciones Espaciales simplemente utiliza Python bucles y diccionarios para determinar vecinos. Hice el proceso a continuación.

La primera parte de bucles a través de cada vértice de cada grupo de bloques. Crea un diccionario con el vértice de coordenadas como las llaves y una lista de bloque de la Id de grupo que tiene un vértice en el que coordinar como el valor. Tenga en cuenta que esto requiere de un topológicamente aseado conjunto de datos, ya que sólo es perfecto vértice/vértice se superponen registrará como un vecino de la relación. Afortunadamente la Oficina del Censo de los tigres grupo de bloques shapefiles están bien en este sentido.

La segunda parte de bucles a través de cada vértice de cada grupo de bloques de nuevo. Crea un diccionario con el bloque de Identificadores de grupo como las llaves y el bloque del grupo vecino identificación de los valores.

# Create dictionary of vertex coordinate : [...,IDs,...]
BlockGroupVertexDictionary = {}
BlockGroupCursor = arcpy.SearchCursor(BlockGroups.shp)
BlockGroupDescription = arcpy.Describe(BlockGroups.shp)
BlockGroupShapeFieldName = BlockGroupsDescription.ShapeFieldName
#For every block group...
for BlockGroupItem in BlockGroupCursor :
    BlockGroupID = BlockGroupItem.getValue("BKGPIDFP00")
    BlockGroupFeature = BlockGroupItem.getValue(BlockGroupShapeFieldName)
    for BlockGroupPart in BlockGroupFeature:
        #For every vertex...
        for BlockGroupPoint in BlockGroupPart:
            #If it exists (and isnt empty interior hole signifier)...
            if BlockGroupPoint:
                #Create string version of coordinate
                PointText = str(BlockGroupPoint.X)+str(BlockGroupPoint.Y)
                #If coordinate is already in dictionary, append this BG's ID
                if PointText in BlockGroupVertexDictionary:
                    BlockGroupVertexDictionary[PointText].append(BlockGroupID)
                #If coordinate is not already in dictionary, create new list with this BG's ID
                else:
                    BlockGroupVertexDictionary[PointText] = [BlockGroupID]
del BlockGroupItem
del BlockGroupCursor


#Create dictionary of ID : [...,neighbors,...]
BlockGroupNeighborDictionary = {}
BlockGroupCursor = arcpy.SearchCursor(BlockGroups.shp)
BlockGroupDescription = arcpy.Describe(BlockGroups.shp)
BlockGroupShapeFieldName = BlockGroupDescription.ShapeFieldName
#For every block group
for BlockGroupItem in BlockGroupCursor:
    ListOfBlockGroupNeighbors = []
    BlockGroupID = BlockGroupItem.getValue("BKGPIDFP00")
    BlockGroupFeature = BlockGroupItem.getValue(BlockGroupShapeFieldName)
    for BlockGroupPart in BlockGroupFeature:
        #For every vertex
        for BlockGroupPoint in BlockGroupPart:
            #If it exists (and isnt interior hole signifier)...
            if BlockGroupPoint:
                #Create string version of coordinate
                PointText = str(BlockGroupPoint.X)+str(BlockGroupPoint.Y)
                if PointText in BlockGroupVertexDictionary:
                    #Get list of block groups that have this point as a vertex
                    NeighborIDList = BlockGroupVertexDictionary[PointText]
                    for NeighborID in NeighborIDList:
                        #Don't add if this BG already in list of neighbors
                        if NeighborID in ListOfBGNeighbors:
                            pass
                        #Add to list of neighbors (as long as its not itself)
                        elif NeighborID != BlockGroupID:
                            ListOfBGNeighbors.append(NeighborID)
    #Store list of neighbors in blockgroup object in dictionary
    BlockGroupNeighborDictionary[BlockGroupID] = ListOfBGNeighbors

del BlockGroupItem
del BlockGroupCursor
del BlockGroupVertexDictionary

En retrospectiva, me doy cuenta de que podría haber utilizado un método diferente para la segunda parte que no requieren de un bucle a través de la shapefile de nuevo. Pero esto es lo que he usado, y funciona bastante bien, incluso para 1000s de los grupos de bloques a la vez. No he intentado hacerlo con el conjunto de Estados Unidos, pero se puede realizar para todo el estado.

Saludos!

3voto

UnkwnTech Puntos 21942

Si usted tiene acceso a ArcGIS 10.2 para Escritorio, o posiblemente antes, entonces creo que el Polígono Vecinos (Análisis) de la herramienta que:

Crea una tabla con estadísticas basadas en el polígono de la contigüidad (se superpone, coincidente bordes, o nodos).

Polygon neighbors

puede hacer esta tarea mucho más fácil ahora.

2voto

djq Puntos 7670

Una alternativa podría ser el uso de PostgreSQL y PostGIS. Yo he pedido un par de preguntas sobre cómo realizar cálculos similares en este sitio:

He encontrado que hay una curva de aprendizaje empinada para averiguar cómo las diversas piezas de software de encajar, pero he encontrado que es maravilloso para hacer cálculos en grandes capas vectoriales. Me he encontrado con algún vecino más cercano cálculos en millones de polígonos y ha sido rápido en comparación con ArcGIS.

1voto

Abhinav Puntos 16

Sólo algunos comentarios... esri/ArcGIS método que actualmente se utiliza diccionarios para almacenar la información, pero el núcleo de los cálculos se hacen en C++ utilizando el Polígono Vecinos de la Herramienta. Esta herramienta genera una Tabla que contiene la contigüidad de la información así como opcionales attrs como la longitud de compartido límite. Usted puede utilizar el Generar Matriz de Ponderaciones Espaciales de la Herramienta si desea almacenar y, posteriormente, volver a usar la información una y otra vez. También puede utilizar esta función en WeightsUtilities para generar un diccionario [de acceso aleatorio] w/ la contigüidad de info:

contDict = polygonNeighborDict(inputFC, masterField, contiguityType = "ROOK")

donde inputFC = cualquier tipo de clase de entidad poligonal, masterField es el "IDENTIFICADOR único" campo de los números enteros y contiguityType en {"TORRE", "la REINA"}.

Hay esfuerzos en esri para omitir el aspecto tabular para los usuarios de Python e ir directamente a un iterador que haría que muchos de los casos de uso mucho más rápido. PySAL y la spdep paquete en R son fantásticas alternativas [ver radek la respuesta]. Creo que son necesarios para utilizar los shapefiles como el formato de datos en estos paquetes, que está en sintonía w/ hilos de este formato de entrada. No está seguro de cómo lidiar con la superposición de polígonos, así como polígonos dentro de los polígonos. Generar SWM así como la función que se describe a contar esas relaciones espaciales como "TORRE" Y "la REINA" de los Vecinos.

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