У меня есть растровые данные, которые я классифицировал на 3 класса. Затем я хочу добавить значения для каждого класса. Я использую следующий код
library(terra)
f <- system.file("ex/elev.tif", package = "terra")
r <- rast(f)
# classify the values into three groups
m <- c(min(global(r, "min", na.rm=TRUE)), 275, 1,
275, 410, 2,
410, max(global(r, "max", na.rm=TRUE)), 3)
#Reclassify the raster stack
rclmat <- matrix(m, ncol=3, byrow=TRUE)
rc <- classify(r, rclmat, include.lowest=TRUE)
plot(rc)
#Add some values to raster attribute table
rc$code <- c(0.002, 0.0056, 0.0124)
#Generate raster using the new column
y <- as.numeric(rc, 2)
plot(y)
Как видите, второй сюжет странный. Как я могу это исправить?
Проблема, похоже, в том, что классы в таблице атрибутов не соответствуют диапазону значений в растре (после добавления новых значений). Мы могли бы сохранить совпадение, сначала вычислив интервалы классов для непрерывных числовых переменных с помощью функции classIntervals()
из пакета classInt
, а затем присвоив значения каждому классу.
library(terra)
library(classInt)
f <- system.file("ex/elev.tif", package = "terra")
r <- rast(f)
# classify the values into three groups
m <- c(min(global(r, "min", na.rm=TRUE)), 275, 1,
275, 410, 2,
410, max(global(r, "max", na.rm=TRUE)), 3)
#Reclassify the raster stack
rclmat <- matrix(m, ncol=3, byrow=TRUE)
rc <- classify(r, rclmat, include.lowest=TRUE)
plot(rc)
# calculate class breaks/intervals
brks <- classIntervals(values(rc), n=3, style = "jenks")$brks
# assign values to classes based on class breaks/intervals
rc$code <- ifelse(values(rc) <= brks[2], 0.002,
ifelse(values(rc) <= brks[3], 0.0056, 0.0124))
#Generate raster using the new column
y <- as.numeric(rc, 2)
plot(y)
Вот расширение, показывающее, как мы можем настроить изменение brks[]
:
library(terra)
library(classInt)
f <- system.file("ex/elev.tif", package = "terra")
r <- rast(f)
# classify the values into three groups
m <- c(min(global(r, "min", na.rm=TRUE)), 275, 1,
275, 410, 2,
410, max(global(r, "max", na.rm=TRUE)), 3)
#Reclassify the raster stack
rclmat <- matrix(m, ncol=3, byrow=TRUE)
rc <- classify(r, rclmat, include.lowest=TRUE)
plot(rc)
# calculate class breaks/intervals
brks <- classIntervals(values(rc), n=3, style = "jenks")$brks
# assign values to classes based on class breaks/intervals
rc$code <- ifelse(values(rc) <= brks[3], 0.002,
ifelse(values(rc) <= brks[1], 0.0056, 0.0124))
#Generate raster using the new column
y <- as.numeric(rc, 2)
plot(y)
Хорошо. Спасибо за ответ. Таким образом, возможно, что границы класса могут измениться в зависимости от конкретных правил реклассификации, которые вы используете. Но это явно выше моего понимания. Удачи!
Данные вашего примера
library(terra)
r <- rast(system.file("ex/elev.tif", package = "terra") )
m <- c(-Inf, 275, 1,
275, 410, 2,
410, Inf, 3)
rclmat <- matrix(m, ncol=3, byrow=TRUE)
rc <- classify(r, rclmat, include.lowest=TRUE)
Чтобы назначить атрибуты, вы должны использовать levels(x)<-
(см. ?levels
). Вы используете $<-
, но это создает новый слой.
levels(rc) <- data.frame(ID=1:3, code=c(0.002, 0.0056, 0.0124))
rc
#class : SpatRaster
#dimensions : 90, 95, 1 (nrow, ncol, nlyr)
#resolution : 0.008333333, 0.008333333 (x, y)
#extent : 5.741667, 6.533333, 49.44167, 50.19167 (xmin, xmax, ymin, ymax)
#coord. ref. : lon/lat WGS 84 (EPSG:4326)
#source(s) : memory
#categories : code
#name : code
#min value : 0.002
#max value : 0.0124
Если вы теперь хотите поместить значения «кода» в ячейки, вы можете продолжить
y <- as.numeric(rc, 1)
(это должно быть 1, а не 2, так как у вас есть только одна категория.)
Вы также можете сделать это с помощью
rc <- classify(r, rclmat, include.lowest=TRUE)
s <- subst(rc, 1:3, c(0.002, 0.0056, 0.0124))
но если это тот результат, который вам нужен, вы должны использовать эти значения в classify
, чтобы вы могли сделать это за один шаг.
m <- c(-Inf, 275, 0.002,
275, 410, 0.0056,
410, Inf, 0.0124)
rclmat <- matrix(m, ncol=3, byrow=TRUE)
rc <- classify(r, rclmat, include.lowest=TRUE)
Обратите внимание, что вы можете еще больше упростить исходный (не тот, что выше) вызов classify
:
rc <- classify(r, c(-Inf, 275, 410, Inf), include.lowest=TRUE)
Когда вы используете
classIntervals
на реклассифицированном растре, это меняет границы класса.