Возврат списка в dplyr mutate()

У меня есть функция в моей реальной проблеме, которая возвращает список. Есть ли способ использовать это с dplyr mutate()? Этот игрушечный пример не работает -:

it = data.table(c("a","a","b","b","c"),c(1,2,3,4,5), c(2,3,4,2,2))

myfun = function(arg1,arg2) {

temp1 = arg1 + arg2
temp2 = arg1 - arg2
list(temp1,temp2)

}

myfun(1,2)

it%.%mutate(new = myfun(V2,V3))

Я вижу, что он циклически перебирает выходные данные функции в первом "столбце" новой переменной, но не понимаю, почему.

Спасибо!

2 ответа

Решение

Идиоматический способ сделать это с помощью data.table будет использовать := (назначение по ссылке) оператор. Вот иллюстрация:

it[, c(paste0("V", 4:5)) := myfun(V2, V3)]

Если вы действительно хотите список, почему бы и нет:

as.list(it[, myfun(V2, V3)])

Или, может быть, это то, что вы хотите, но почему бы вам просто не использовать data.table функциональность:

it[, c(.SD, myfun(V2, V3))]
#    V1 V2 V3 V4 V5
# 1:  a  1  2  3 -1
# 2:  a  2  3  5 -1
# 3:  b  3  4  7 -1
# 4:  b  4  2  6  2
# 5:  c  5  2  7  3    

Обратите внимание, что если myfun должны были назвать его вывод, тогда имена будут отображаться в столбцах окончательного результата:

#    V1 V2 V3 new.1 new.2
# 1:  a  1  2     3    -1
# 2:  a  2  3     5    -1
# 3:  b  3  4     7    -1
# 4:  b  4  2     6     2
# 5:  c  5  2     7     3    

Учитывая название на этот вопрос, я думал, что выложу tidyverse решение, которое использует dplyr::mutate, Обратите внимание, что myfun необходимо вывести data.frame работать.

library(tidyverse)

it = data.frame(
  v1 = c("a","a","b","b","c"),
  v2 = c(1,2,3,4,5), 
  v3 = c(2,3,4,2,2))

myfun = function(arg1,arg2) {

  temp1 = arg1 + arg2
  temp2 = arg1 - arg2
  data.frame(temp1, temp2)

}

it %>% 
  nest(v2, v3) %>% 
  mutate(out = map(data, ~myfun(.$v2, .$v3))) %>% 
  unnest(data, out) 

Функция mutate() предназначена для добавления новых столбцов в существующий фрейм данных. Кадр данных представляет собой список векторов одинаковой длины. Таким образом, вы не можете добавить список в качестве нового столбца, потому что список не является вектором.

Вы можете переписать вашу функцию как две функции, каждая из которых возвращает вектор. Затем примените каждый из них отдельно, используя mutate(), и он должен работать.

Другие вопросы по тегам