R targets动态分支:如何为矩阵逐迭代添加列?
问题描述
在R的targets流程中,通过tar_files()加载多个栅格数据后,计划在下一个target中迭代处理,为矩阵的每个文件对应添加一列,但最终仅生成第一列。以下是无需文件的可复现代码:
library(targets) tar_script( { add_column <- function(letter) { matrix(rep(letter, 10), ncol = 1) } list( tar_target(letters, letters), tar_target( added_columns, add_column(letters), pattern = map(letters) ) ) }, ask = FALSE ) tar_make()
使用tar_load(add_columns)加载结果时仅显示第一列;在栅格数据场景中,使用terra::extract每次迭代生成一个向量,但加载结果除第一列外其余均为NA。
问题原因
使用pattern = map(letters)后,added_columns本质是一个列表对象,列表中的每个元素是单独的单列矩阵(或向量)。直接tar_load后,R会默认显示列表的第一个元素,或是被意外简化,导致看起来只有第一列;栅格场景出现NA,大概率是合并时未正确处理列表结构,或是每次extract返回的向量长度不一致。
解决方案
方案1:在target流程中直接合并为矩阵
调整target结构,先生成单列数据的列表,再新增一个target合并所有列:
library(targets) tar_script( { # 修改函数,返回向量而非单列矩阵,简化合并步骤 add_column <- function(letter) { rep(letter, 10) } list( tar_target(letters_vec, letters), # 迭代生成每一列的向量,存储为列表 tar_target( column_list, add_column(letters_vec), pattern = map(letters_vec) ), # 合并列表中的所有向量为矩阵 tar_target( combined_matrix, do.call(cbind, column_list) ) ) }, ask = FALSE ) tar_make()
执行后,tar_load(combined_matrix)即可得到每列对应一个字母的完整矩阵。
方案2:加载列表后手动合并
如果希望保留迭代生成的added_columns列表,加载后可以手动合并:
tar_load(added_columns) # 将列表中的所有单列矩阵合并为完整矩阵 full_matrix <- do.call(cbind, added_columns)
栅格数据场景适配
针对terra::extract的情况,确保每次提取的向量长度一致,再用相同逻辑合并:
library(targets) library(terra) tar_script( { # 加载栅格文件路径 tar_target(raster_files, list.files(path = "your_raster_dir", pattern = "\\.tif$", full.names = TRUE)), # 假设points是预处理好的点对象,可单独作为target tar_target(points, vect("your_points.shp")), # 迭代提取每个栅格的数值,生成向量列表 tar_target( extract_list, { r <- rast(raster_files) terra::extract(r, points)[,2] # 取提取结果的数值列 }, pattern = map(raster_files) ), # 合并所有提取向量为矩阵 tar_target( extract_matrix, do.call(cbind, extract_list) ) }, ask = FALSE )
注意:如果不同栅格提取的向量长度不一致,需要先统一长度(比如补全NA或筛选匹配的点),否则合并后会出现NA。
内容的提问来源于stack exchange,提问作者Josep Pueyo
相关产品推荐
相关产品推荐

