-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrandom_stratified_sampling.R
107 lines (91 loc) · 3.67 KB
/
random_stratified_sampling.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# ---
# title: "Random Stratified Sampling"
# author: "Brendan Casey"
# created: "2024-02-27"
# description: >
# Use random stratified sampling on the PIWO predictive map
# to determine where to do field work to validate the model.
# ---
# 1. Setup ----
## 1.1 Load packages ----
library(terra) # rasters
library(sf) # polygons and points
library(tidyverse) # data manipulation
## 1.2 Import data ----
r <- rast(paste0("3_output/predict_rasters/",
"brt_ls_hlc_terrain_canopy_29_2_p_piwo.tif"))
path <- st_read(paste0("0_data/external/Spatial/CanadianNatural/",
"17324_Pathways_GlobalRaymac/Shapefiles/",
"17324_ProjectBoundary_nad83_csrs_z12.shp"))
# 2. Classify raster ----
## 2.1 Define breaks and labels for reclassification ----
reclass_matrix <- matrix(c(0, .05, 0,
.05, .4, 1, # .05-20 mapped to 1 (poor)
.4, .7, 2, # 20-70 mapped to 2 (moderate)
.7, 1, 3), # 70-100 mapped to 3 (good)
byrow=TRUE, ncol=3)
## 2.2 Reclassify the raster ----
reclassified_raster <- classify(r, rcl=reclass_matrix, right=TRUE)
# 3. Crop raster to pipeline path ----
## 3.1 Transform pipeline path CRS ----
path_1 <- st_zm(path)
path_2 <- st_transform(path, crs=st_crs(r))
## 3.2 Crop raster ----
cropped_raster <- crop(reclassified_raster, path_2)
## 3.3 Mask raster ----
r_path <- mask(cropped_raster, path_2)
## 3.4 Inspect values ----
### 3.4.1 Extract and plot values ----
vals <- values(r_path)
non_na_values <- na.omit(vals)
hist(non_na_values, main="Histogram of Non-NA Raster Values",
xlab="Value", ylab="Frequency")
# 4. Random sampling cells ----
## 4.1 Create separate masks for each class ----
mask1 <- ifel(r_path == 1, 1, NA)
mask2 <- ifel(r_path == 2, 2, NA)
mask3 <- ifel(r_path == 3, 3, NA)
## 4.2 Sample separately for each class ----
samples1 <- spatSample(mask1, size=6, method="random",
as.points=TRUE, values=TRUE, na.rm=TRUE)
samples2 <- spatSample(mask2, size=10, method="random",
as.points=TRUE, values=TRUE, na.rm=TRUE)
samples3 <- spatSample(mask3, size=4, method="random",
as.points=TRUE, values=TRUE, na.rm=TRUE)
## 4.3 Combine samples into single dataframe ----
samples <- rbind(samples1, samples2, samples3)
names(samples) <- "class"
## 4.4 Convert to sf object and check distribution ----
samples_1 <- st_as_sf(samples) %>%
mutate(index=row_number()) %>%
select(index, class, geometry)
hist(samples_1$class)
# 5. Convert point locations to 1 ha squares ----
## 5.1 Function to create a square ----
create_square <- function(center, radius) {
half_side <- radius
x <- center[1]
y <- center[2]
vertices <- matrix(nrow = 5, ncol = 2,
data = c(x - half_side, y - half_side,
x + half_side, y - half_side,
x + half_side, y + half_side,
x - half_side, y + half_side,
x - half_side, y - half_side),
byrow = TRUE)
square <- st_polygon(list(vertices))
return(square)
}
## 5.2 Create squares for each point ----
squares <- lapply(1:nrow(samples_1), function(i) {
center <- st_coordinates(samples_1[i, ])
radius <- 50
square <- create_square(center, radius)
return(square)
})
## 5.3 Combine squares into a MULTIPOINT sf object and save ----
squares_sfc <- st_sfc(squares, crs = st_crs(samples_1))
samples_square <- samples_1
samples_square$geometry <- squares_sfc
st_write(samples_square, "3_output/data/samples_square.shp")
st_write(samples_1, "3_output/data/samples_1.shp")