Estou tentando fazer uma junção espacial muito parecida com o exemplo aqui: Existe uma opção python para "juntar atributos por local"? . No entanto, essa abordagem parece realmente ineficiente / lenta. Mesmo executando isso com 250 pontos modestos leva quase 2 minutos e falha totalmente em arquivos de forma com mais de 1.000 pontos. Existe uma abordagem melhor? Eu gostaria de fazer isso inteiramente em Python sem usar ArcGIS, QGIS, etc.
Também gostaria de saber se é possível adicionar atributos SUM (ou seja, população) de todos os pontos que se enquadram em um polígono e associar essa quantidade ao shapefile do polígono.
Aqui está o código que estou tentando converter. Eu recebo um erro na linha 9:
poly['properties']['score'] += point['properties']['score']
que diz:
TypeError: tipo (s) de operando não suportado para + =: 'NoneType' e 'float'.
Se eu substituir o "+ =" por "=", ele funciona bem, mas isso não soma os campos. Eu também tentei fazer isso como números inteiros, mas isso também falha.
with fiona.open(poly_shp, 'r') as n:
with fiona.open(point_shp,'r') as s:
outSchema = {'geometry': 'Polygon','properties':{'region':'str','score':'float'}}
with fiona.open (out_shp, 'w', 'ESRI Shapefile', outSchema, crs) as output:
for point in s:
for poly in n:
if shape(point['geometry']).within(shape(poly['geometry'])):
poly['properties']['score']) += point['properties']['score'])
output.write({
'properties':{
'region':poly['properties']['NAME'],
'score':poly['properties']['score']},
'geometry':poly['geometry']})
fonte
Respostas:
Fiona retorna dicionários Python e você não pode usar
poly['properties']['score']) += point['properties']['score'])
com um dicionário.Exemplo de soma de atributos usando as referências fornecidas por Mike T:
Agora, podemos usar dois métodos, com ou sem um índice espacial:
1) sem
2) com um índice R-tree (você pode usar pyrtree ou rtree )
Resultado com as duas soluções:
Qual é a diferença ?
Depois de:
Para ir além, consulte Usando a indexação espacial da Rtree com OGR, Shapely, Fiona
fonte
Além disso - as geopandas agora incluem opcionalmente
rtree
como dependência, consulte o repositório do githubEntão, em vez de seguir todo o código (muito bom) acima, você pode simplesmente fazer algo como:
Para obter essa funcionalidade sofisticada, instale primeiro a biblioteca C libspatialindex
EDIT: importação de pacotes corrigidos
fonte
rtree
era opcional. Isso não significa que você precisa instalarrtree
, assim como alibspatialindex
biblioteca C?rtree
quando eu o instaleilibspatialindex
... eles fizeram uma versão bastante importante desde então, então eu tenho certeza que as coisas mudaram um poucoUse Rtree como um índice para executar as junções muito mais rápidas e, em seguida, Shapely para executar os predicados espaciais para determinar se um ponto está realmente dentro de um polígono. Se feito corretamente, isso pode ser mais rápido do que a maioria dos outros GIS.
Veja exemplos aqui ou aqui .
A segunda parte da sua pergunta sobre 'SUM', use um
dict
objeto para acumular populações usando um ID de polígono como chave. Embora, esse tipo de coisa seja feito muito mais bem com o PostGIS.fonte
Esta página da web mostra como usar uma pesquisa de ponto no polígono da caixa delimitadora antes da consulta espacial Within mais cara da Shapely.
http://rexdouglass.com/fast-spatial-joins-in-python-with-a-spatial-index/
fonte