如何更改Terra中分类脾脏的水平排序的排序?

发布于 2025-02-10 04:31:00 字数 2198 浏览 2 评论 0原文

我有两个射手,我希望它们具有相同的水平和相同的顺序。但是,其中一个栅格没有另一个级别,但我设法在使用级别(rast)< - alll_labels中添加了这些级别。

我的问题是,现在两只老鼠具有相同的级别(即使其中一个级别在实际的栅栏中没有看到),但是这些级别的级别为不同,因此,相同的标签与不同的标签相关联整数:

例如

#Showing the first 5 of each to illustrate the issue
#original raster
[[1]]
   ID                                   label
1   0                                   Ocean
2   1                         Urban Ecosystem
3   2                             Bare Ground
4   3                       Coastal Ecosystem
5   4                        Alpine Ecosystem
...

#New raster
   ID                                   label
1   0                             Bare Ground
2   1                         Urban Ecosystem
3   2                       Coastal Ecosystem
4   3                                   Ocean
5   4                        Alpine Ecosystem
...

,我想做的是让标签与同一整数相对应。如果这是基本问题,我将使用因子(...,latve = c(...))简单地更改标签的排序,该标签将更新数据框中的基础整数因此。

例如,

#Creating a factor which has the levels in alphabetical order
incorrect_factor <- factor(c(one, two, three, four))
incorrect_factor

#Changing ordering
factor_reordered <- factor(my_factor, levels = c("one", "two", "three", "four"))
factor_reordered

有没有一种方法可以使用Terra做同样的事情?我想我可以看到一种使用terra ::分类更改实际整数的方法;本质上,在问题栅格中手动重新分类了基础整数以匹配我的目标栅格,但我不确定它是否有效,并且它会导致一个非常错误的代码

。创建一个分类的栅格来创建一个问题的小报道:

#Creating a raster (using the terra::cats example code)
set.seed(0)
r <- rast(nrows=10, ncols=10)
values(r) <- sample(3, ncell(r), replace=TRUE)

cls <- data.frame(id=1:3, cover=c("forest", "water", "urban"))
levels(r) <- cls

#Original
plot(r)
levels(r)

#Second raster with variables in a different order - this would be the one to change to match the above raster with the labels in the same order and the integers updated to reflect this.
r_2 <- rast(nrows=10, ncols=10)
values(r_2) <- sample(3, ncell(r), replace=TRUE)

cls <- data.frame(id=1:3, cover=c("water", "urban","forest"))
levels(r_2) <- cls
plot(r_2)
levels(r_2)

我已经搜索了很多谷歌搜索,但我还没有找到任何解决我遇到的问题的东西,但是如果我错过了任何问题,请让我知道!

先感谢您!

I have two rasters and I would like them to have the same levels and in the same order. However, one of the rasters does not have all the levels that the other does but I have managed to add these levels in using levels(rast) <- all_labels.

My issue is that now the two RATs have all the same levels (even though some of the levels are not seen in one of the actual rasters), but the levels are in different orders, and therefore, the same label is associated with a different integer:

E.g.

#Showing the first 5 of each to illustrate the issue
#original raster
[[1]]
   ID                                   label
1   0                                   Ocean
2   1                         Urban Ecosystem
3   2                             Bare Ground
4   3                       Coastal Ecosystem
5   4                        Alpine Ecosystem
...

#New raster
   ID                                   label
1   0                             Bare Ground
2   1                         Urban Ecosystem
3   2                       Coastal Ecosystem
4   3                                   Ocean
5   4                        Alpine Ecosystem
...

So, what I would like to do is have the labels correspond to the same integer. If this were a base R problem I would use factor(..., levels = c(...)) to simply change the ordering of the labels, which would update the underlying integers in the dataframe accordingly.

e.g.

#Creating a factor which has the levels in alphabetical order
incorrect_factor <- factor(c(one, two, three, four))
incorrect_factor

#Changing ordering
factor_reordered <- factor(my_factor, levels = c("one", "two", "three", "four"))
factor_reordered

Is there a way to do the same kind of thing with terra? I think I can see a way to do it with terra::classify to change the actual integers; essentially manually re-classifying the underlying integers in the problem raster to match my target raster but I am not certain it would work and it would make for a very error prone bit of code...

Below is some code that I pulled from examples to create a categorical raster to create a small reprex of the problem:

#Creating a raster (using the terra::cats example code)
set.seed(0)
r <- rast(nrows=10, ncols=10)
values(r) <- sample(3, ncell(r), replace=TRUE)

cls <- data.frame(id=1:3, cover=c("forest", "water", "urban"))
levels(r) <- cls

#Original
plot(r)
levels(r)

#Second raster with variables in a different order - this would be the one to change to match the above raster with the labels in the same order and the integers updated to reflect this.
r_2 <- rast(nrows=10, ncols=10)
values(r_2) <- sample(3, ncell(r), replace=TRUE)

cls <- data.frame(id=1:3, cover=c("water", "urban","forest"))
levels(r_2) <- cls
plot(r_2)
levels(r_2)

I have googled this quite a bit and I haven't found any thing that addresses the issue I am having but if I missed anything please let me know!

Thank you in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

很糊涂小朋友 2025-02-17 04:31:01

可能有一种方法,但是“手动”执行此操作并不难。请注意,我正在使用Terra版本1.5.44,该版本当前是开发版本。您可以使用install.packages('Terra',repos ='https://rspatial.r-universe.dev')

示例数据

library(terra)
#terra 1.5.44
set.seed(0)
r <- rast(nrows=10, ncols=10)
values(r) <- sample(3, ncell(r), replace=TRUE)
levels(r) <- data.frame(id=1:3, cover=c("forest", "water", "urban"))
  
r_2 <- setValues(r, sample(3, ncell(r), replace=TRUE))
levels(r_2) <- data.frame(id=1:3, cover=c("water", "urban","forest"))
 
levels(r)[[1]]
#  id  cover
#1  1 forest
#2  2  water
#3  3  urban
levels(r_2)[[1]]
#  id  cover
#1  1  water
#2  2  urban
#3  3 forest

解决方案

首先合并标签及其代码

m <- merge(levels(r)[[1]], levels(r_2)[[1]], by=2, all=TRUE)
m
#   cover id.x id.y
#1 forest    1    3
#2  urban    3    2
#3  water    2    1

# for labels that do not occur in the first raster
# not relevant in this example
m <- m[!is.na(m[,2]), ] 

>替换并设置新级别

s <- subst(r_2, m[,3], m[,2])
levels(s) <- levels(r)
 
levels(s)[[1]]
#  id  cover
#1  1 forest
#2  2  water
#3  3  urban
 

There could be a method for this, but it is not that hard to do this "manually". Note that I am using terra version 1.5.44, which is currently the development version. You can install it with install.packages('terra', repos='https://rspatial.r-universe.dev')

Example data

library(terra)
#terra 1.5.44
set.seed(0)
r <- rast(nrows=10, ncols=10)
values(r) <- sample(3, ncell(r), replace=TRUE)
levels(r) <- data.frame(id=1:3, cover=c("forest", "water", "urban"))
  
r_2 <- setValues(r, sample(3, ncell(r), replace=TRUE))
levels(r_2) <- data.frame(id=1:3, cover=c("water", "urban","forest"))
 
levels(r)[[1]]
#  id  cover
#1  1 forest
#2  2  water
#3  3  urban
levels(r_2)[[1]]
#  id  cover
#1  1  water
#2  2  urban
#3  3 forest

Solution

First merge the labels and their codes

m <- merge(levels(r)[[1]], levels(r_2)[[1]], by=2, all=TRUE)
m
#   cover id.x id.y
#1 forest    1    3
#2  urban    3    2
#3  water    2    1

# for labels that do not occur in the first raster
# not relevant in this example
m <- m[!is.na(m[,2]), ] 

Use subst and set the new levels

s <- subst(r_2, m[,3], m[,2])
levels(s) <- levels(r)
 
levels(s)[[1]]
#  id  cover
#1  1 forest
#2  2  water
#3  3  urban
 
薔薇婲 2025-02-17 04:31:01

罗伯特·希曼(Robert Hijman)的示例中的原则对我有用,但是示例的代码却没有。这是我要工作的一个例子。

#sample data from the subst help file
z <- rast(ncols=5, nrows=5, xmin=0, xmax=1, ymin=0, ymax=1, crs="")
z <- init(z, 1:6)
x <- subst(z, 3, 7)
x <- subst(z, 2:3, NA)
x <- subst(x, NA, 10)

levels(x) <- data.frame(value = c(1,4,5,6,10),
                        lc_class = c("a", "b", "c", "d", "e"))



#idenfity what t0 want to change the values to 
new_levels <- data.frame(new_value = c(1,2,3,4,5,6,7,8,9,10),
                          old_value  = c(1,4,5,6,10, NA, NA, NA, NA, NA),
                         lc_class = c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"))

#substitute new values for old values
y <- subst(x, new_levels$old_value, new_levels$new_value)

#rename levels according to new values
levels(y) <- new_levels[,c(1,3)]

#add a cell from one of the new levels to test that it worked and plots properly
y[1,1] <- 10
plot(y)

The principles in Robert Hijman's example worked for me, but the code of the example didn't. Here's an example that I got to work.

#sample data from the subst help file
z <- rast(ncols=5, nrows=5, xmin=0, xmax=1, ymin=0, ymax=1, crs="")
z <- init(z, 1:6)
x <- subst(z, 3, 7)
x <- subst(z, 2:3, NA)
x <- subst(x, NA, 10)

levels(x) <- data.frame(value = c(1,4,5,6,10),
                        lc_class = c("a", "b", "c", "d", "e"))



#idenfity what t0 want to change the values to 
new_levels <- data.frame(new_value = c(1,2,3,4,5,6,7,8,9,10),
                          old_value  = c(1,4,5,6,10, NA, NA, NA, NA, NA),
                         lc_class = c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"))

#substitute new values for old values
y <- subst(x, new_levels$old_value, new_levels$new_value)

#rename levels according to new values
levels(y) <- new_levels[,c(1,3)]

#add a cell from one of the new levels to test that it worked and plots properly
y[1,1] <- 10
plot(y)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文