如何在targets工作流静态分支中程序化指定group_by变量?
解决方案:在tar_map中动态传递tar_group_select的分组变量
问题原因
你遇到的问题是因为tar_group_select的by参数是在targets的元编程上下文里解析的,无法直接捕获tar_map传递的by变量。直接写by = by时,targets会把第二个by当成数据框里的列名,而不是tar_map参数中的分组变量值。
方法1:使用rlang注入动态指定分组变量
可以用rlang::sym()把字符型的分组变量名转换成符号,再用!!注入到tar_group_select的by参数中,让targets正确识别每个分支的分组变量:
library(targets) targets::tar_dir({ targets::tar_script({ library(targets) library(tarchetypes) library(tidyverse) library(rlang) df1 <- data.frame( g1 = rep(LETTERS[1:3], 2), x = 1:6, y = 1:6 ) df2 <- data.frame( g1 = rep(LETTERS[1:3], 2), g2 = rep(LETTERS[4:6], 2), x = 1:6, y = 1:6 ) list( label = c("group1", "group2"), source = c("df1", "df2") |> syms(), by = c("g1", "g2") ) |> tar_map( names = "label", tar_group_select( result, identity(source), by = !!sym(by) # 注入动态分组变量 ) ) }) tar_manifest() tar_make() })
方法2:先动态分组再用tar_group_by
如果觉得元编程注入不够直观,可以先在tar_map里对数据源完成动态分组,再用tar_group_by处理分组后的数据集,这样更符合常规的dplyr操作逻辑:
library(targets) targets::tar_dir({ targets::tar_script({ library(targets) library(tarchetypes) library(tidyverse) df1 <- data.frame( g1 = rep(LETTERS[1:3], 2), x = 1:6, y = 1:6 ) df2 <- data.frame( g1 = rep(LETTERS[1:3], 2), g2 = rep(LETTERS[4:6], 2), x = 1:6, y = 1:6 ) list( label = c("group1", "group2"), source = c("df1", "df2") |> syms(), by = c("g1", "g2") ) |> tar_map( names = "label", # 先根据动态参数分组 tar_target( grouped_data, dplyr::group_by({{source}}, .data[[by]]) ), # 对分组后的数据集应用动态分支 tar_group_by( result, grouped_data ) ) }) tar_manifest() tar_make() })
这两种方法都能实现你想要的:在tar_map的静态分支中,为每个数据源指定不同的分组变量,无需手动编写重复的tar_group_*语句。
内容的提问来源于stack exchange,提问作者Melissa Key
相关产品推荐
相关产品推荐

