Jak mówi mój tytuł, chcę „wyhodować” skupiska komórek z nasion w rastrze. Mój podstawowy raster jest pełen 1 i 0, 1 oznacza ląd i 0 morze / obszary NA. Z 1-tych chciałbym wybrać 60 losowych pikseli / komórek jako swoje nasiona, a następnie losowo wyhodować połączoną kępę o wstępnie zdefiniowanym nr. limitu pikseli / komórek z tego materiału siewnego. Słyszałem, że tę technikę można nazwać „barwnikiem do smarowania”, ale nie miałem szczęścia znaleźć jej dużo. Komórka zaszczepiająca zostanie zamieniona na wartość 2, a następnie następna komórka wybrana z otaczających jedynek również zostanie przekonwertowana na 2. 2 są następnie niedostępne do konwersji w przyszłości.
Ten wątek trochę pomaga, ponieważ chętnie bym to zrobił w R, ponieważ znam się na czytaniu i manipulowaniu danymi GIS w R. Jednak wymagam zestawu reguł do losowego wybierania pikseli otaczających istniejącą grupę .
Jeśli ktoś zrobiłby tę bardziej podstawową formę automatów komórkowych w środowisku GIS, byłbym wdzięczny za wszelkie porady / wskazówki.
Przykład:
Mam cel 250 komórek. Losowo wybieram jedną komórkę, która ma wartość 1. To jest zamieniane na wartość 2. Następnie jeden z sąsiadów komórki zaszczepiającej, który = 1 jest zamieniany na 2. Następnie jeden z sąsiadów jednej z komórek z wartością 2 jest wybierana i zamieniana na 2. Trwało to do momentu osiągnięcia ciągłego kształtu liczącego 250 komórek.
Edycja: dalsze pytania
Na podstawie doskonałej odpowiedzi Whubera mam kilka pytań dotyczących kodu:
- Jak mogę przydzielić wartości hodowanych komórek do wartości „2” zamiast wartości zmiennych reprezentujących kolejność, w której zostały utworzone?
- Muszę utworzyć 60 skupisk komórek w moim obszarze „1”. Wymyśliłem sposoby wybierania losowych pozycji początkowych, ale staram się, aby wszystko działało w pętli za pomocą
expand
funkcji, którą uprzejmie napisałeś. Czy możesz zasugerować sposób utworzenia 60 grup, które nie kolidują ze sobą i są zawarte w tej samej ostatecznej matrycy?
Edycja: Dalsze wyjaśnienie problemu
Każde skupisko komórek będzie reprezentowało chroniony obszar o określonym rozmiarze, np. 250 komórek. Każdy obszar musi zacząć i rosnąć w komórki o wartości 1, ponieważ reprezentuje to ląd, i unikać komórek o wartości 0, ponieważ reprezentuje morze. Muszę iterować to 1000 razy z 60 chronionymi obszarami w każdej iteracji, aby stworzyć model zerowy, pokazujący, jakie rozkłady tych obszarów będą przypadkowe. Z tego powodu łączna liczba komórek we wszystkich 60 obszarach będzie musiała być identyczna w każdej z 1000 iteracji, aby były porównywalne. Dlatego jest ok, jeśli obszary się stykają, ale jeśli dojdzie do kolizji, idealnie kępa będzie rosła w innym dostępnym kierunku, aż do osiągnięcia celu 250.
Po utworzeniu każdej z tych 1000 sieci obszarów chronionych będą one używane jako maska w stosunku do innych danych rastrowych, takich jak miary różnorodności biologicznej, aby zobaczyć (a) czy przecinają one poszczególne zakresy gatunków oraz (b) jaki procent poszczególnych gatunków obejmuje te losowe sieci ochrony obszarów chronionych.
Dzięki @whuber za pomoc do tej pory, nie oczekuję, że poświęcisz mi więcej czasu, ale pomyślałem, że postaram się wyjaśnić moją sytuację, tak jak prosiłeś.
Odpowiedzi:
Oferuję
R
rozwiązanie, które jest nieco zakodowane wR
celu zilustrowania, jak można podejść do niego na innych platformach.Problemem
R
(podobnie jak niektórych innych platform, szczególnie tych, które preferują funkcjonalny styl programowania) jest to, że ciągła aktualizacja dużej tablicy może być bardzo droga. Zamiast tego algorytm zachowuje własną strukturę prywatnych danych, w której (a) wymienione są wszystkie komórki, które zostały dotychczas wypełnione, i (b) wszystkie komórki, które można wybrać (na obwodzie wypełnionych komórek) są wymienione. Mimo że manipulowanie tą strukturą danych jest mniej wydajne niż bezpośrednie indeksowanie do tablicy, utrzymując zmodyfikowane dane w małym rozmiarze, prawdopodobnie zajmie to znacznie mniej czasu obliczeniowego. (Nie podjęto również żadnych wysiłków, aby go zoptymalizowaćR
. Wstępna alokacja wektorów stanu powinna zaoszczędzić trochę czasu wykonania, jeśli wolisz nadal pracować wewnątrzR
).Kod jest komentowany i powinien być łatwy do odczytania. Aby algorytm był jak najbardziej kompletny, nie wykorzystuje żadnych dodatków poza końcem do wykreślenia wyniku. Jedyną trudną częścią jest to, że dla wydajności i prostoty woli indeksować do siatek 2D za pomocą indeksów 1D. Konwersja zachodzi w
neighbors
funkcji, która potrzebuje indeksowania 2D, aby dowiedzieć się, czym mogą być dostępni sąsiedzi komórki, a następnie przekształca je w indeks 1D. Ta konwersja jest standardowa, więc nie będę komentować jej dalej, poza zaznaczeniem, że na innych platformach GIS możesz chcieć odwrócić role indeksów kolumn i wierszy. (WR
indeksy wierszy zmieniają się przed indeksami kolumn).Aby to zilustrować, ten kod pobiera siatkę
x
przedstawiającą ląd i rzekę cechę niedostępnych punktów, rozpoczyna się w określonej lokalizacji (5, 21) na tej siatce (w pobliżu dolnego zakola rzeki) i rozwija ją losowo, aby objąć 250 punktów . Całkowity czas wynosi 0,03 sekundy. (Gdy rozmiar tablicy zostanie zwiększony o współczynnik od 10 000 do 3000 wierszy o 5000 kolumn, czas wzrośnie tylko do 0,09 sekundy - współczynnik tylko około 3 - co pokazuje skalowalność tego algorytmu.) Zamiast po prostu wyprowadzając siatkę zer, 1 i 2, wyświetla sekwencję, z którą przydzielono nowe komórki. Na rycinie najwcześniejsze komórki są zielone, przechodząc przez złoto do kolorów łososiowych.Powinno być oczywiste, że stosuje się ośmiopunktowe sąsiedztwo każdej komórki. W przypadku innych dzielnic wystarczy zmodyfikować
nbrhood
wartość na początkuexpand
: jest to lista przesunięć indeksu względem dowolnej komórki. Na przykład sąsiedztwo „D4” można określić jakomatrix(c(-1,0, 1,0, 0,-1, 0,1), nrow=2)
.Oczywiste jest również, że ta metoda rozprzestrzeniania ma swoje problemy: pozostawia dziury w tyle. Jeśli nie było to zamierzone, istnieją różne sposoby rozwiązania tego problemu. Na przykład trzymaj dostępne komórki w kolejce, aby najwcześniej znalezione komórki były również najwcześniej wypełnione. Nadal można zastosować pewną randomizację, ale dostępne komórki nie będą już wybierane z jednakowymi (równymi) prawdopodobieństwami. Innym, bardziej skomplikowanym sposobem byłby wybór dostępnych komórek z prawdopodobieństwem, które zależą od liczby ich wypełnionych sąsiadów. Gdy komórka zostanie otoczona, jej szansa na wybranie jest tak wysoka, że niewiele otworów pozostanie niewypełnionych.
Zakończę komentując, że nie jest to całkiem automat komórkowy (CA), który nie przechodziłby komórka po komórce, ale zamiast tego aktualizowałby całe warstwy komórek w każdym pokoleniu. Różnica jest subtelna: w przypadku CA prawdopodobieństwo wyboru komórek nie byłoby jednolite.
Przy niewielkich modyfikacjach możemy zapętlić się,
expand
aby utworzyć wiele klastrów. Wskazane jest rozróżnienie klastrów według identyfikatora, który tutaj będzie działał 2, 3, ... itd.Najpierw zmień,
expand
aby zwracać (a)NA
w pierwszym wierszu, jeśli wystąpił błąd, i (b) wartościindices
zamiast w macierzyy
. (Nie marnuj czasu na tworzenie nowej matrycyy
przy każdym wywołaniu.) Po wprowadzeniu tej zmiany zapętlenie jest łatwe: wybierz losowy początek, spróbuj rozszerzyć się wokół niego, akumuluj indeksy klastrów,indices
jeśli się powiedzie, i powtarzaj, aż się zakończy. Kluczową częścią pętli jest ograniczenie liczby iteracji w przypadku, gdy nie można znaleźć wielu sąsiadujących klastrów: odbywa się to za pomocącount.max
.Oto przykład, w którym 60 centrów skupień jest wybieranych losowo równomiernie.
Oto wynik po nałożeniu na siatkę 310 na 500 (wykonany wystarczająco mały i gruby, aby klastry były widoczne). Wykonanie zajmuje dwie sekundy; na siatce 3100 na 5000 (100 razy większa) zajmuje więcej czasu (24 sekundy), ale czas jest odpowiednio skalowany. (Na innych platformach, takich jak C ++, taktowanie nie powinno zależeć od rozmiaru siatki.)
źródło
y[indices] <- 1:length(indices)
nay[indices] <- 2
. Odpowiedź na # 2 jest prawie tak prosta: wystarczy zapętlić.size.clusters
. Jak mogę się upewnić, że kępa rośnie do właściwego rozmiaru, ponieważ w tej chwili zakładam, że próbuje urosnąć do istniejącej kępy, kończy się niepowodzeniem, ale nadal rejestruje się jako udane rozszerzenie. Następnie zamierzam również 1000 razy powtórzyć produkcję 60 grup, tworząc zestaw danych o średnim modelu modelu zerowego. Czy losowe pozycjonowanie będzie się zmieniać za każdym razem wfor
pętli?Nie wykonując żadnej operacji i nie tracąc czasu na grę, mogę dodać tylko te dwa linki do Twojej listy:
Znajdź najbliższą wartość komórki rastrowej na podstawie punktu wektorowego (zaintrygowała mnie pierwsza odpowiedź (4 głosy)).
Ponadto: czy Hawth's Gridspread pomoże?
źródło