根据图层部分名称匹配,在栈中选择光栅图。

7

我有一堆栅格图像(每个物种一个),然后我有一个数据框,其中包含纬度/经度列和物种名称。

fls = list.files(pattern="median")
s <- stack(fls)
df<-c("x","y","species name")

我希望能够一次只选择一个光栅图层并将其用于提取函数。我希望选择基于物种名称列的部分匹配。我之所以要这样做,是因为光栅图层的名称可能与物种列表中的名称不完全匹配,可能存在大小写不匹配或光栅图层名称可能更长,例如“species_name_median”,也可能有“_”代替空格。

for(i:length(df.species name))
{
  result<-extract(s[[partial match to "species name[i]" ]],df.xy)
}

我希望这个想法是有道理的,我只想一次使用一个栅格图层进行提取。使用s[[i]]可以轻松选择单个栅格图层,但不能保证列表中的每个物种都有相应的栅格图层。


这个问题如果没有一些模糊匹配的具体例子,就很难有任何有意义的回答。 - Simon O'Hanlon
@SimonO101 一个例子是:有一个名为“Lion_median”的光栅图像,其中物种名称列为“lion”。在这种情况下,我需要将“lion”与“Lion”匹配。这有帮助吗? - Herman Toothrot
是的,它可以。我已经添加了一个答案,只要物种名称实际上被正确拼写(即匹配忽略标点符号、大小写和物种名称在图层名称中的位置),它就可以工作。希望对你有所帮助。 - Simon O'Hanlon
如果您需要更多帮助,请随时发布任何遇到的后续问题... :-) - Simon O'Hanlon
@SimonO101 我对你使用的一些函数不熟悉,所以需要一些时间来理解你的答案到底是做什么的。但还是谢谢你。 - Herman Toothrot
显示剩余3条评论
2个回答

4

如果你需要查询的点的数据是一个包含x和y坐标以及相应物种名称的数据框,那么你可以使用以下两个命令完成全部操作:

#  Find the layer to match on using 'grepl' and 'which' converting all names to lowercase for consistency
df$layer <- lapply( df$species , function(x) which( grepl( tolower(x) , tolower(names(s)) ) ) )


# Extract each value from the appropriate layer in the stack
df$Value <- sapply( seq_len(nrow(df)) , function(x) extract( s[[ df$layer[x] ]] , df[ x , 1:2 ] ) )

工作原理

从第一行开始:

  • 首先,我们定义一个新的列向量df$layer,它将是我们需要在该行中使用的rasterLayer在堆栈中的索引。
  • lapply沿着列df$species中的所有元素迭代,并使用每个df$species中的项依次作为输入变量x应用匿名函数。尽管它看起来不像,但lapply是一个循环结构。
  • 在第一次迭代中,我们取df$species的第一个元素,即现在的x,并在s的名称中使用grepl(意思是“全局正则模式匹配逻辑”)查找包含我们物种模式的元素。我们对要匹配的模式(x)和要匹配的元素(names(s))都使用tolower()以确保即使大小写不匹配时也能匹配,例如"Tiger"将无法找到"tiger"
  • grepl返回一个逻辑向量,其中包含它找到模式匹配的元素,例如grepl("abc", c("xyz", "wxy", "acb", "zxabcty"))返回F, F, T, T。我们使用which来获取这些元素的索引。
  • 我们的想法是为每一行获取一个且仅一个堆栈中与物种名称匹配的层,因此唯一的TRUE索引将是我们想要的堆栈中的层的索引。

在第二行,sapply

  • sapply是一个迭代器,与lapply非常相似,但它返回一个向量而不是值列表。在这个用例中,你可以使用任何一个。
  • 现在,我们沿着从1nrow(df)的数字序列进行迭代。
  • 我们在另一个匿名函数中使用行号作为输入变量x
  • 我们想提取数据框的当前行(由x给出)的"x""y"坐标(分别为第1列和第2列),使用我们在上一行得到的层。
  • 我们将所有这些操作的结果分配给数据框中的另一列,该列包含适当层的x/y坐标的提取值

我希望这有所帮助!

以下是一些数据的示例:

require( raster )
#  Sample rasters - note the scale of values in each layer  
# Tens
r1 <- raster( matrix( sample(1:10,100,repl=TRUE) , ncol = 10 ) )    
# Hundreds
r2 <- raster( matrix( sample(1e2:1.1e2,100,repl=TRUE) , ncol = 10 ) )   
# Thousands
r3 <- raster( matrix( sample(1e3:1.1e3,100,repl=TRUE) , ncol = 10 ) )

#  Stack the rasters
s <- stack( r1,r2,r3 )
#  Name the layers in the stack
names(s) <- c("LIon_medIan" , "PANTHeR_MEAN_AVG" , "tiger.Mean.JULY_2012")


#  Data of points to query on
df <- data.frame( x = runif(10) , y = runif(10) , species = sample( c("lion" , "panther" , "Tiger" ) , 10 , repl = TRUE ) )

#  Run the previous code
df$layer <- lapply( df$species , function(x) which( grepl( tolower(x) , tolower(names(s)) ) ) )
df$Value <- sapply( seq_len(nrow(df)) , function(x) extract( s[[ df$layer[x] ]] , df[ x , 1:2 ] ) )

#  And the result (note the scale of Values is consistent with the scale of values in each rasterLayer in the stack)
df
#          x         y species layer Value
#1  0.4827577 0.7517476    lion     1     1
#2  0.8590993 0.9929104    lion     1     3
#3  0.8987446 0.4465397   tiger     3  1084
#4  0.5935572 0.6591223 panther     2   107
#5  0.6382287 0.1579990 panther     2   103
#6  0.7957626 0.7931233    lion     1     4
#7  0.2836228 0.3689158   tiger     3  1076
#8  0.5213569 0.7156062    lion     1     3
#9  0.6828245 0.1352709 panther     2   103
#10 0.7030304 0.8049597 panther     2   105

1

您尝试过对 RasterStack 进行子集操作吗?

类似于这样:

for(i in 1: length(df.species.name)) #assuming it is the 'partial species name'
{
  result <- subset(s, grep(df.species.name[i], ignore.case = TRUE, value = TRUE)
}

了解不同栅格和物种名称可能有多么不同是很有趣的。这将允许更好的方法,如有必要,调整正则表达式。您会在这里找到许多关于grep的参考资料。也可以尝试?grep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接