在R的terra包中,循环处理后如何堆叠多变量气候栅格?
问题
我写了一个for循环读取系列栅格的气候数据,每个变量包含4个月的数据,每个月对应30年的栅格。循环会找出同一变量下同一月份的所有栅格,计算多年平均值,最终把4个月份的平均栅格堆叠到以变量名命名的对象中。
我的clim.vars包含的变量远多于示例数量,希望只修改clim.vars向量就能运行任意变量组合。循环能正常遍历变量,但最终目标是创建一个包含所有变量及所有月份的堆叠栅格,每个图层命名为"variable_month",这一步卡壳了。我尝试过多种循环后合并变量的方法都失败了,觉得问题出在clim.vars是字符向量而非对象向量,也试过as.name()和mget()转换,但都没用。
原代码如下:
clim.vars <- c("max_Tmean", "mean_RH", "min_RH", "mean_Tmax") for(var in clim.vars){ June <- rast(list.files(paste0("./Data/", var, "/Rasters"), full.names = TRUE, pattern = glob2rx(paste0(var, "_June_*.tif$")))) %>% crop(vect(SA)) %>% mask(vect(SA)) %>% mean() July <- rast(list.files(paste0("./Data/", var, "/Rasters"), full.names = TRUE, pattern = glob2rx(paste0(var, "_July_*.tif$")))) %>% crop(vect(SA)) %>% mask(vect(SA)) %>% mean() August <- rast(list.files(paste0("./Data/", var, "/Rasters"), full.names = TRUE, pattern = glob2rx(paste0(var, "_August_*.tif$")))) %>% crop(vect(SA)) %>% mask(vect(SA)) %>% mean() September <- rast(list.files(paste0("./Data/", var, "/Rasters"), full.names = TRUE, pattern = glob2rx(paste0(var, "_September_*.tif$")))) %>% crop(vect(SA)) %>% mask(vect(SA)) %>% mean() assign(var, c(June, July, August, September)) %>% set.names(c(paste0(var, "_June"), paste0(var, "_July"), paste0(var, "_August"), paste0(var, "_September"))) } ## 合并所有栅格(这些是我失败的尝试,要么完全失败,要么仅保留变量名作为图层名)... bioclim <- c(clim.vars) bioclim <- rast(mget(clim.vars)) bioclim <- c(as.name(clim.vars)) bioclim <- c(lapply(clim.vars, as.name)) bioclim <- rast(lapply(clim.vars, as.name)) ## 这种方法能得到我想要的结果... # `clim.rast`在脚本开头与`clim.vars`一同定义 clim.rast <- c(max_Tmean, mean_RH, min_RH, mean_Tmax) # `bioclim`在运行上述循环后定义 bioclim <- clim.rast
请问如何通过修改clim.vars实现自动合并所有指定变量的栅格?
解决方案
核心问题是你用assign()创建了单个变量对象,但合并时需要把这些对象正确组合成堆叠栅格。以下两种方法可以解决:
方法一:循环中直接收集结果(推荐)
无需使用assign(),提前创建列表存储每个变量的堆叠栅格,最后一次性合并,代码更简洁易维护:
clim.vars <- c("max_Tmean", "mean_RH", "min_RH", "mean_Tmax") # 定义月份向量,避免重复代码 months <- c("June", "July", "August", "September") # 初始化空列表存储每个变量的栅格 clim_list <- list() for(var in clim.vars){ # 批量处理每个月份的栅格 month_rasts <- lapply(months, function(m){ rast(list.files(paste0("./Data/", var, "/Rasters"), full.names = TRUE, pattern = glob2rx(paste0(var, "_", m, "_*.tif$")))) %>% crop(vect(SA)) %>% mask(vect(SA)) %>% mean() }) # 堆叠当前变量的4个月栅格并命名 var_stack <- c(month_rasts[[1]], month_rasts[[2]], month_rasts[[3]], month_rasts[[4]]) names(var_stack) <- paste0(var, "_", months) # 将堆叠结果存入列表 clim_list[[var]] <- var_stack } # 合并列表中所有栅格 bioclim <- do.call(c, clim_list)
方法二:修复原循环后的合并逻辑
如果保留原assign()的写法,用mget()提取字符向量对应的对象,再用do.call(c, ...)合并:
# 原循环代码保持不变... # 正确合并所有变量的栅格 bioclim <- do.call(c, mget(clim.vars))
关键说明
- 方法一:新增变量只需修改
clim.vars,新增月份只需修改months向量,无需重复编写每个月份的处理代码,可维护性更强。 - 方法二:
mget(clim.vars)会把字符向量对应的栅格对象提取为列表,do.call(c, ...)会将列表中的所有堆叠栅格合并成一个完整的堆叠栅格,自动保留每个图层的命名。
内容的提问来源于stack exchange,提问作者apple
相关产品推荐
相关产品推荐

