Korzystanie z Arcgis Desktop 10.3.1 Mam skrypt, który używa kursora wyszukiwania, aby dołączyć wartości do listy, a następnie użyj min (), aby znaleźć najmniejszą liczbę całkowitą. Zmienna jest następnie używana w skrypcie. Klasa Feature ma 200 000 wierszy, a wykonanie skryptu zajmuje bardzo dużo czasu. Czy istnieje sposób, aby to zrobić szybciej? W tej chwili myślę, że po prostu zrobiłbym to ręcznie, zamiast pisać scenariusz ze względu na czas, jaki zajmuje.
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)])
Odpowiedzi:
Widzę kilka rzeczy, które mogą powodować spowolnienie skryptu. To, co prawdopodobnie jest bardzo wolne, to
arcpy.CalculateField_management()
funkcja. Powinieneś użyć kursora, będzie on o kilka wielkości szybszy. Powiedziałeś także, że używasz ArcGIS Desktop 10.3.1, ale używasz starych kursorów ArcGIS 10.0, które również są znacznie wolniejsze.Operacja min () nawet na liście 200K będzie dość szybka. Możesz to sprawdzić, uruchamiając ten mały fragment kodu; dzieje się to w mgnieniu oka:
Sprawdź, czy jest to szybsze:
EDYTOWAĆ:
Przeprowadziłem testy czasowe i, jak podejrzewałem, kalkulator pola zajął prawie dwa razy więcej czasu niż kursor nowego stylu. Co ciekawe, kursor w starym stylu był ~ 3 razy wolniejszy niż kalkulator polowy. Utworzyłem 200 000 losowych punktów i użyłem tych samych nazw pól.
Do odmierzania czasu każdej funkcji użyto funkcji dekoratora (może to być niewielki narzut w konfiguracji i zrywaniu funkcji, więc może moduł timeit byłby nieco bardziej dokładny do testowania fragmentów).
Oto wyniki:
A oto kod, którego użyłem (rozbiłem wszystko na poszczególne funkcje, aby użyć
timeit
dekoratora):I wreszcie taki właśnie był wydruk z mojej konsoli.
Edycja 2: Właśnie opublikowałem kilka zaktualizowanych testów, zauważyłem niewielką wadę mojej
timeit
funkcji.źródło
"XKoordInt"
. Zobacz moją edycję, wszystko, co musisz zrobić, to pominąć wartości null.range
. ArcGIS nadal używa Python 2.7, więc zwraca alist
. Ale w wersji 3.xrange
jest to własny specjalny obiekt, który może być zoptymalizowany. Byłby bardziej wiarygodny testmin(list(range(200000)))
, który zapewniłby pracę z prostą listą. Rozważ także użycietimeit
modułu do testowania wydajności.Jak wskazuje @crmackey, wolna część jest prawdopodobnie spowodowana metodą obliczania pola. Jako alternatywę dla innych odpowiednich rozwiązań i zakładając, że używasz geobazy do przechowywania danych, możesz użyć polecenia Sortuj według sql, aby posortować w porządku rosnącym przed wykonaniem kursora aktualizacji.
W takim przypadku klauzula where usuwa wartości zerowe przed wykonaniem zapytania lub możesz użyć innego przykładu, który sprawdza przed aktualizacją brak.
źródło
min()
. Uwzględnię to również w moich testach prędkości, aby pokazać wzrost wydajności.0.56
kilka sekund, co nie jest tak dużym wzrostem wydajności, jak bym się spodziewał.Możesz także użyć numpy w takich przypadkach, chociaż będzie to wymagało więcej pamięci.
Nadal dostaniesz przewagę podczas ładowania danych do tablicy numpy, a następnie z powrotem do źródła danych, ale zauważyłem, że różnica wydajności jest lepsza (na korzyść numpy) przy większych źródłach danych, szczególnie jeśli potrzebujesz wielu statystyki / obliczenia .:
źródło
Dlaczego nie posortować tabeli rosnąco, a następnie użyć kursora wyszukiwania, aby pobrać wartość dla pierwszego wiersza? http://pro.arcgis.com/en/pro-app/tool-reference/data-management/sort.htm
źródło
Chciałbym zawrzeć
SearchCursor
w wyrażeniu generatora (tj.min()
) Zarówno szybkość, jak i zwięzłość. Następnie włącz minimalną wartość z wyrażenia generatora doda
typuUpdateCursor
. Coś w stylu:źródło
SearchCursor
się zamykać, kiedy z tym skończysz?W swojej pętli masz dwa odwołania do funkcji, które są przeszacowane dla każdej iteracji.
for row in cursor: ListVal.append(row.getValue(Xfield))
Powinno być szybsze (ale nieco bardziej złożone), aby mieć odwołania poza pętlą:
źródło
append()
metodylist
typu danych. Nie sądzę, że tutaj właśnie dzieje się jego wąskie gardło, postawiłbym pieniądze, że winowajcą jest funkcja obliczania pola. Można to zweryfikować, mierząc czas kalkulatora pola względem nowego kursora stylu.