import random
999) # ziarno losowości
random.seed(
= list(range(0, 100 + 1, 10))
x_coords # losowanie ze zwracaniem
= random.choices(x_coords, k = 5)
x_coords print(x_coords)
[80, 0, 90, 60, 50]
Algorytmy danych geoprzestrzennych
Próbkowanie
Krzysztof Dyba
Próbkowanie (sampling) to proces wybierania (selekcji) podzbioru lokalizacji danych przestrzennych z większego obszaru geograficznego w celu analizy cech całego obszaru. Stworzona reprezentatywna próba danych, może zostać wykorzystana do wyciągnięcia wniosków na temat populacji, przy jednoczesnym zminimalizowaniu czasu, kosztów i wysiłku wymaganego do zebrania i przetworzenia tych danych.
Rodzaje próbkowania:
Istnieje wiele sposobów losowego doboru próbek używając różnych rozkładów prawdopodobieństwa (np. jednostajnego, normalnego, dwumianowego czy Poissona) w zależności od charakterystyki danych i konkretnych wymagań analizy. W przypadku danych przestrzennych wykorzystywane są specjalistyczne rozkłady przestrzenne, które są bardziej złożone od tradycyjnych ze względu na uwzględnienie relacji przestrzennych (patrz pakiet spatstat.random w R).
W najprostszym przypadku należy wykorzystać losowanie ze zwracaniem, gdzie jako obiekt wejściowy definiujemy listę, która reprezentuje minimalny oraz maksymalny zasięg przestrzenny danej osi, np. x_coords = list(range(xMinimum, xMaximum + 1))
. Z racji, iż dane rastrowe są reprezentacją dyskretną obszarów badań, trzeba zdefiniować interwał próbkowania, np. co 10 m, aby uniknąć sytuacji, w której próbki pochodzą z identycznej lokalizacji (komórki). Zakres przestrzenny możemy zdefiniować na dwa sposoby – dla całego rastra lub dla określonego obszaru. Jeśli korzystamy z QGIS, to dodatkowo możemy, pobrać aktualnie wyświetlany zasięg warstwy w aplikacji.
Uwaga! Generowanie liczb losowych jest procesem losowym, to znaczy że za każdym razem, gdy kod zostanie wykonany, to otrzymamy inną sekwencję liczb. Aby uzyskać tę samą sekwencję liczb, należy ustawić ziarno losowości (random.seed()
) najlepiej na początku skryptu, dzięki czemu wyniki będą powtarzalne.
import random
999) # ziarno losowości
random.seed(
= list(range(0, 100 + 1, 10))
x_coords # losowanie ze zwracaniem
= random.choices(x_coords, k = 5)
x_coords print(x_coords)
[80, 0, 90, 60, 50]
Do stworzenia punktu wymagana jest para współrzędnych X (długość geograficzna) i Y (szerokość geograficzna) oraz klasa QgsPointXY
. Wygenerowane punkty możemy przechowywać w liście (co jest prostszym rozwiązaniem) lub stworzyć nową warstwę wektorową (patrz temat “Przetwarzanie danych wektorowych: Tworzenie nowej warstwy”).
from qgis.core import QgsPointXY
= list(range(0, 100 + 1, 10))
x_coords = random.choices(x_coords, k = 5)
x_coords = list(range(0, 100 + 1, 10))
y_coords = random.choices(y_coords, k = 5)
y_coords
= []
points for x, y in zip(x_coords, y_coords):
points.append(QgsPointXY(x, y))
print(points)
[<QgsPointXY: POINT(10 10)>, <QgsPointXY: POINT(80 100)>, <QgsPointXY: POINT(30 20)>, <QgsPointXY: POINT(80 20)>, <QgsPointXY: POINT(90 60)>]
Procedura wygenerowania losowego punkty w poligonie składa się z dwóch etapów:
from qgis.core import QgsGeometry
# przykładowe dane
= "POLYGON((0 0, 20 0, 5 10, 0 0))"
wkt = QgsGeometry.fromWkt(wkt)
polygon = polygon.boundingBox()
bbox print(bbox) # xmin, ymin, xmax, ymax
<QgsRectangle: 0 0, 20 10>
# (1) losowanie punktu z zakresu
= random.uniform(bbox.xMinimum(), bbox.xMaximum())
x = random.uniform(bbox.yMinimum(), bbox.yMaximum())
y = QgsPointXY(x, y)
pt print(pt)
<QgsPointXY: POINT(14.04204171589216621 2.53705020234383216)>
# (2) sprawdzenie czy poligon zawiera punkt
print(polygon.contains(pt))
True
Naturalnie, jeśli chcemy wygenerować punkty dla obiektów, to musimy zastosować pętlę. W przypadku “dziwnych” geometrii, które trudno opróbkować, należy pamiętać żeby pętla była skończona.
from qgis.core import QgsLineString
= QgsPointXY(10, 20)
pt1 = QgsPointXY(50, 70)
pt2 = QgsGeometry(QgsLineString([pt1, pt2])) # QgsGeometry.fromPolylineXY()
line print(line)
= line.length()
line_length print("Długość linii:", line_length)
<QgsGeometry: LineString (10 20, 50 70)>
Długość linii: 64.03124237432849
= 10
interval = []
points = 0
distance while distance <= line_length:
= line.interpolate(distance)
point
points.append(point.asPoint())= distance + interval
distance print("Liczba punktów:", len(points))
Liczba punktów: 7
W przypadku próbkowania wzdłuż linii istotne jest sprawdzenie kierunku przebiegu linii, np. czy jest to kierunek wschód-zachód czy na odwrót. Jeśli błędnie przyjmiemy kierunek, to wartości na krzywej będą odwrócone. Do weryfikacji można napisać prostą funkcję, która porówna współrzędne punktu początkowego i końcowego linii.
def line_direction(line):
# pobierz wierzchołki
= line.asPolyline()
vertices
# wybierz pierwszy i ostatni wierzchołek
= vertices[0]
start_point = vertices[-1]
end_point
# sprawdzenie osi X
if start_point.x() < end_point.x():
= "ZACH-WSCH"
x_direction elif start_point.x() > end_point.x():
= "WSCH-ZACH"
x_direction else:
= "" # kierunek stały
x_direction
# sprawdzenie osi Y
if start_point.y() < end_point.y():
= "PŁD-PŁN"
y_direction elif start_point.y() > end_point.y():
= "PŁN-PŁD"
y_direction else:
= ""
y_direction
return x_direction, y_direction
print("Kierunek linii:", line_direction(line))
Kierunek linii: ('ZACH-WSCH', 'PŁD-PŁN')
Analiza geomorfometryczna. Dokonaj analizy ukształtowania terenu (plik DEM.tif
) używając dwóch transektów północ-południe oraz wschód-zachód. Wynik zaprezentuj na rycinie (na osi X powinna znajdować się odległość wyrażona w metrach). Zastanów się również, co zrobić w przypadku, gdy komórki nie posiadają wartości (nan).
Analiza teledetekcyjna. Wygeneruj losową próbę i następnie dla dwóch wybranych kanałów spektralnych z Landsat 8/9:
wykonaj wykres rozrzutu uwzględniając przezroczystość punktów oraz zaznacz linię x = y
,
oblicz statystyki opisowe z wartości różnic między tymi kanałami.
Dodatkowo można obliczyć współczynnik korelacji Pearsona (numpy.corrcoef()
).
sample_strata(wektor, n)
, która zagwarantuje, że dla każdego poligonu zostanie zwrócona dokładna liczba punktów wskazana przez użytkownika, a wynik zostanie zapisany jako warstwa wektorowa. Do analizy wykorzystaj dane z pliku powiaty.gpkg
.