Цели R: при итерации = "список" разветвление НЕ происходит с [[]]

Вопрос или проблема

Документация гласит:

итерация.
Символ длиной 1, название режима итерации цели. Выборы:

  • “vector”: ветвление происходит с помощью vctrs::vec_slice() и агрегация происходит с помощью vctrs::vec_c().
  • “list”, ветвление происходит с помощью [[]] и агрегация происходит с помощью list().

Но ниже у меня есть цель df_list, которая является списком из двух датафреймов. Затем я определяю целевую задачу tar_target(dfproc1, proc1(df_list), pattern = map(df_list), iteration = "list"). Из вывода видно, что proc1 получил каждый df_list[i] (а не каждый df_list[[i]]). Я что-то делаю не так?

library(targets)
library(tarchetypes)

# функции
init <- function() {
  data.frame(
    g = rep(c(0,1), c(10,2)),
    x = 1:12
  )
}
filt <- function(df) {
  df <- df[df$g==0, ]
  df
}
proc1 <- function(df) {
  # df <- df[[1]] с этим работает
  df$y <- 10
  df
}


# цели
list(
  tar_target(df, init()),
  tar_target(df0, filt(df)),
  tar_target(df_list, list(df, df0)),
  tar_target(
    dfproc1, 
    proc1(df_list),
    pattern = map(df_list),
    iteration = "list"
  )
)

targets::tar_read(dfproc1)
# $dfproc1_ae5e6cb0c537abdc
# $dfproc1_ae5e6cb0c537abdc[[1]]
#    g  x
# 1  0  1
# 2  0  2
# 3  0  3
# 4  0  4
# 5  0  5
# 6  0  6
# 7  0  7
# 8  0  8
# 9  0  9
# 10 0 10
# 11 1 11
# 12 1 12

# $dfproc1_ae5e6cb0c537abdc$y
# [1] 10


# $dfproc1_ac8961e3c84c4878
# $dfproc1_ac8961e3c84c4878[[1]]
#    g  x
# 1  0  1
# 2  0  2
# 3  0  3
# 4  0  4
# 5  0  5
# 6  0  6
# 7  0  7
# 8  0  8
# 9  0  9
# 10 0 10

# $dfproc1_ac8961e3c84c4878$y
# [1] 10

Ожидал список из двух датафреймов, каждый с колонкой y.

Ответ или решение

Ваша проблема связана с тем, как работает механизм итерации в targets, особенно когда используется итерация типа "list".

Согласно документации, когда вы указываете iteration = "list", то разделение (branching) происходит с использованием двойных квадратных скобок [[]] и агрегация с помощью функции list(). Однако, в вашем случае код вызывает функцию proc1(df_list), что приводит к обработке всего списка df_list, а не отдельного элемента списка.

Когда вы вызываете proc1(df_list), функция получает весь список, и внутри нее не происходит распределения по элементам списка. Вместо этого вам нужно использовать map для итерации по отдельным элементам списка.

Вам понадобится немного изменить код следующим образом:

library(targets)
library(tarchetypes)

# Функции
init <- function() {
  data.frame(
    g = rep(c(0, 1), c(10, 2)),
    x = 1:12
  )
}
filt <- function(df) {
  df[df$g == 0, ]
}
proc1 <- function(df) {
  df$y <- 10
  df
}

# Цели
list(
  tar_target(df, init()),
  tar_target(df0, filt(df)),
  tar_target(df_list, list(df, df0)),
  tar_target(
    dfproc1, 
    map(df_list, proc1),  # Используйте map здесь
    iteration = "list"
  )
)

# Чтение результатов
targets::tar_read(dfproc1)

Попробуйте выполнить этот код. Используя map(df_list, proc1), вы преобразуете каждый элемент списка df_list с помощью функции proc1, тем самым создавая новый список, где каждая таблица будет содержать новый столбец y.

Такой подход должен создать список из двух фреймов данных, каждый из которых будет содержать столбец y. После выполнения этой версии кода результат должен быть таким, как вы ожидаете.

Оцените материал
Добавить комментарий

Капча загружается...