Usando o arcgis desktop 10.3.1 Eu tenho um script que usa um cursor de pesquisa para acrescentar valores a uma lista e, em seguida, use min () para encontrar o menor número inteiro. A variável é então usada em um script. A classe Feature tem 200.000 linhas e o script leva muito tempo para ser concluído. Existe uma maneira de fazer isso mais rápido? No momento, acho que faria apenas à mão, em vez de escrever um script devido ao tempo que leva.
import arcpy
fc = arcpy.env.workspace = arcpy.GetParameterAsText(0)
Xfield = "XKoordInt"
cursor = arcpy.SearchCursor(fc)
ListVal = []
for row in cursor:
ListVal.append(row.getValue(Xfield))
value = min(ListVal)-20
print value
expression = "(!XKoordInt!-{0})/20".format(value)
arcpy.CalculateField_management (fc, "Matrix_Z" ,expression, "PYTHON")
arcpy.Statistics_analysis
? desktop.arcgis.com/en/arcmap/10.3/tools/analysis-toolbox/...min_val = min([i[0] for i in arcpy.da.SearchCursor(fc,Xfield)])
Respostas:
Eu posso ver várias coisas que podem estar causando um atraso no seu script. O que provavelmente está sendo muito lento é a
arcpy.CalculateField_management()
função. Você deve usar um cursor, por várias magnitudes mais rápido. Além disso, você disse que está usando o ArcGIS Desktop 10.3.1, mas está usando os cursores antigos do estilo ArcGIS 10.0, que também são muito mais lentos.A operação min (), mesmo em uma lista de 200K, será bastante rápida. Você pode verificar isso executando este pequeno trecho; isso acontece em um piscar de olhos:
Veja se isso é mais rápido:
EDITAR:
Fiz alguns testes de tempo e, como suspeitava, a calculadora de campo demorou quase o dobro do tempo do cursor do novo estilo. Curiosamente, o cursor do estilo antigo era ~ 3x mais lento que a calculadora de campo. Criei 200.000 pontos aleatórios e usei os mesmos nomes de campo.
Uma função decoradora foi usada para cronometrar cada função (pode haver uma pequena sobrecarga na configuração e desmontagem das funções, portanto, talvez o módulo timeit seja um pouco mais preciso para testar trechos).
Aqui estão os resultados:
E aqui está o código que eu usei (dividi tudo em funções individuais para usar o
timeit
decorador):E, finalmente, é isso que foi a impressão real do meu console.
Edit 2: Acabei de publicar alguns testes atualizados, encontrei uma pequena falha na minha
timeit
função.fonte
"XKoordInt"
. Veja minha edição, tudo que você precisa fazer é pular nulos.range
. O ArcGIS ainda usa Python 2.7, então retorna alist
. Mas no 3.x,range
é seu próprio tipo especial de objeto que pode ter otimizações. Um teste mais confiável seriamin(list(range(200000)))
, o que garantiria que você estivesse trabalhando com uma lista simples. Considere também usar otimeit
módulo para teste de desempenho.Como aponta @crmackey, a parte lenta provavelmente se deve ao método de cálculo do campo. Como alternativa às outras soluções adequadas, e supondo que você esteja usando um geodatabase para armazenar seus dados, você pode usar o comando Order By sql para classificar em ordem crescente antes de executar o cursor de atualização.
Nesse caso, a cláusula where remove os nulos antes de fazer a consulta ou você pode usar o outro exemplo que verifica Nenhum antes da atualização.
fonte
min()
. Também incluirei isso em meus testes de velocidade para mostrar o ganho de desempenho.0.56
segundos, o que não é tanto um ganho de desempenho como eu esperava.Você também pode usar numpy em casos como esse, embora consuma mais memória.
Você ainda terá um gargalo ao carregar os dados em uma matriz numpy e depois novamente na fonte de dados, mas eu descobri que a diferença de desempenho é melhor (a favor da numpy) com fontes de dados maiores, especialmente se você precisar de vários estatísticas / cálculos .:
fonte
Por que não classificar a tabela em ascensão e usar um cursor de pesquisa para obter o valor da primeira linha? http://pro.arcgis.com/en/pro-app/tool-reference/data-management/sort.htm
fonte
Eu colocaria a expressão
SearchCursor
em um gerador (iemin()
), tanto para velocidade quanto para sucessão. Em seguida, incorpore o valor mínimo da expressão do gerador em umda
tipoUpdateCursor
. Algo como o seguinte:fonte
SearchCursor
ser fechado quando você terminar com isso?No seu loop, você tem duas referências de função que são reavaliadas para cada iteração.
for row in cursor: ListVal.append(row.getValue(Xfield))
Deve ser mais rápido (mas um pouco mais complexo) ter as referências fora do loop:
fonte
append()
método interno dolist
tipo de dados. Eu não acho que é aí que o gargalo dele está acontecendo. Aposto que a função de campo de cálculo é a culpada. Isso pode ser verificado cronometrando a calculadora de campo contra um novo cursor de estilo.