Mam dość dużą klasę obiektów punktowych w geobazie pliku (~ 4 000 000 rekordów). Jest to regularna siatka punktów o rozdzielczości 100 m.
Muszę wykonać rodzaj uogólnienia na tej warstwie. W tym celu tworzę nową siatkę, w której każdy punkt znajduje się w środku 4 „starych” punktów:
* * * *
o o o
* * * *
o o o
* * * *
[*] = punkt oryginalnej siatki - [o] = punkt nowej siatki
Wartość atrybutu każdego nowego punktu jest obliczana na podstawie ważonych wartości 4 sąsiadów w starej siatce. Zapętlam więc wszystkie punkty mojej nowej siatki i dla każdego z nich zapętlam wszystkie punkty mojej starej siatki, aby znaleźć sąsiadów (porównując wartości X i Y w tabeli atrybutów). Po znalezieniu 4 sąsiadów wychodzimy z pętli.
Nie ma tu złożoności metodologicznej, ale moim problemem jest to, że na podstawie moich pierwszych testów skrypt ten będzie trwał kilka tygodni, aby ukończyć ...
Czy widzisz jakąś możliwość zwiększenia wydajności? Kilka pomysłów na czubku głowy:
- Zindeksuj pola X i Y => Zrobiłem to, ale nie zauważyłem żadnej znaczącej zmiany wydajności
- Wykonaj zapytanie przestrzenne, aby znaleźć sąsiadów, a nie oparte na atrybutach. Czy to naprawdę pomogłoby? Jaka funkcja przestrzenna w ArcGIS powinna działać? Wątpię, aby np. Buforowanie każdego nowego punktu okazało się bardziej wydajne
- Przekształć klasę obiektów w tablicę NumPy. Czy to pomogłoby? Do tej pory nie pracowałem dużo z NumPy i nie chciałbym się w to zanurzyć, chyba że ktoś mi powie, że może to naprawdę pomóc w skróceniu czasu przetwarzania
- Coś jeszcze?
źródło
Odpowiedzi:
Co jeśli nakarmisz punkty tablicą liczb liczbowych i użyjesz zwięzłego cKDTree do szukania sąsiadów. Przetwarzam chmury punktów LiDAR z dużą liczbą punktów (> 20 milionów) w kilka MINUT za pomocą tej techniki. Jest dokumentacja tutaj dla kdtree i tutaj dla numpy nawrócenia. Zasadniczo odczytujesz x, y do tablicy i iterujesz po każdym punkcie tablicy, znajdując wskaźniki punktów w pewnej odległości (sąsiedztwie) każdego punktu. Możesz użyć tych wskaźników, aby następnie obliczyć inne atrybuty.
źródło
Jestem z Barbarossą ... arkadowe kursory są niesamowicie kulawe, więc używam ich tylko do przemierzania tabeli lub klasy obiektów dokładnie raz. Jeśli nie mogę wykonać pracy w jednym cyklu, używam kursora, aby wypełnić inną strukturę danych i pracuję z tym.
Jeśli nie chcesz mieć kłopotów z numpy, po prostu stwórz prosty słownik python, w którym używasz swoich współrzędnych jako prostego klucza tekstowego i wypełnij atrybuty potrzebne do obliczeń na liście jako wartość elementu słownika.
W drugim kroku możesz łatwo uzyskać wartości potrzebne do obliczenia punktu, po prostu pobierając je ze słownika (który jest niesamowicie szybki, ze względu na hashindeks słowników pozycji).
źródło
W przypadku zwykłej siatki praca w formacie rastrowym powinna być zdecydowanie bardziej wydajna. Przekształć pierwszą siatkę w raster, możesz ponownie próbkować w tej samej rozdzielczości za pomocą interpolatora dwuliniowego, ale przesuwając obraz wyjściowy o 1/2 piksela w X i Y, i ponownie z powrotem do punktów, jeśli nadal potrzebujesz punktów.
EDYCJA: w przypadku złożonych reguł decyzyjnych możesz przekonwertować każde z pól, które potrzebujesz jako nowe pasmo rastrowe, następnie tworzysz cztery kopie tych pasm i przesuwasz raster w 4 kierunkach o 1/2 piksela (+50, - 50), (+ 50, + 50), (-50, -50) i (-50, + 50). Następnie możesz użyć zwykłej algebry map
źródło
Dziękujemy wszystkim za pomoc!
W końcu znalazłem bardzo nie-pytonowy sposób rozwiązania tego problemu ... To, co faktycznie zajmowało najwięcej czasu, to znalezienie 4 sąsiadów z każdego punktu. Zamiast używać atrybutów X i Y (z łukowatym kursorem lub w innej strukturze danych, takiej jak słownik python), skończyłem na użyciu narzędzia ArcGIS Generuj przy stole . Zakładam, że wykorzystuje to indeksy przestrzenne, a wydajność jest oczywiście znacznie wyższa, bez mojej implementacji indeksu.
źródło
Problem z kursorami polega na tym, że możesz je przełączać tylko w jeden sposób i nie możesz wrócić. Chociaż nie jest to zalecane, możesz wypełnić feautres w strukturze, jeśli planujesz je ponownie odwiedzić.
Jeśli udało Ci się przetworzyć swoje funkcje w jednej pętli, sugeruję włączenie recyklingu. Jest to parametr funkcji wyszukiwania funkcji klasy, który pozwala Pythonowi ponownie wykorzystać pamięć przydzieloną przez stare funkcje i znacznie przyspieszyć przeglądanie funkcji kursorem. Możesz przetwarzać swoją siatkę 80% szybciej.
Problem polega na tym, że nie można włączyć recyklingu, jeśli planujesz przechowywać odzyskane funkcje z kursorem.
źródło