Mais

Como fazer um loop “aninhado” com sucesso em uma coleção Fiona


Eu escrevi um código que basicamente faz um loop sobre todos os recursos em um arquivo de forma com Fiona em Python, fazendo algumas coisas, calculando algumas coisas, etc.

Descobri que ele sairia do loop for prematuramente, dependendo do conjunto de dados que o alimentei. Descobri que funcionaria bem se eu removesse algum código que (para mim) não tem nada a ver com o loop em que estamos. Esta é minha primeira tentativa de GIS com Python, então posso estar fazendo alguma mistura de novato com estruturas de dados. acho?

Abaixo está um exemplo mínimo usando dados Natural Earth que você pode obter em http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_countries.zip

import fiona de shapely.geometry import shape, Point def find_containing_area (point, collection): para registro na coleção: geometry = shape (record ['geometry']) if point.within (geometry): retornar registro return Nenhum com fiona.open ('/tmp/ne_110m_admin_0_countries.shp', 'r') as source: for admin_record in source: properties = admin_record ['properties'] print (properties ['name']) # em meu código original, criei um ponto relacionado para o admin_record point = Point (0,0) # se a seguinte linha existir, o loop irá parar após o primeiro # admin_record neste exemplo. No meu código original, ele parou # após apenas alguns registros, mas não o primeiro. container_area = find_containing_area (ponto, fonte)

Se eu executá-lo, ele imprime "Afeganistão" em vez de toda a lista de aproximadamente 177 nomes. Se eu comentar a última linha, ele os imprimirá como pretendido.

Meu único palpite é que alguém um iterador é passado junto com a coleção? A única dica na documentação que encontrei é "A coleção de Fiona é como um arquivo Python, mas é iterável para registros em vez de linhas." o que me ajuda muito estúpido, não muito. http://toblerity.org/fiona/manual.html#data-model

editar: tentei copiar a coleção e passar a cópia para a função, obtive o mesmo bevahiour:

newsource = source [:] contain_area = find_containing_area (point, newsource)

De acordo com a documentação:

Buscar o início do arquivo não é suportado. Você deve reabrir a coleção para voltar ao início.

Abra o arquivo novamente para o segundo loop. Mudei sua última linha para a seguinte e fiz o loop percorrer todo o caminho.

com fiona.open ('ne_110m_admin_0_countries.shp', 'r') como source2: contain_area = find_containing_area (point, source2)

Repostando o comentário de Kersten como uma resposta para que eu possa aceitá-lo como solução:

fiona.open retorna um iterador, portanto, retornará apenas um elemento por vez na memória. A documentação tem alguns exemplos de armazenamento de resultados de iterador na memória, por exemplo, listas

Minha solução foi criar uma lista a partir da fonte:

newsource = list (source)