R dplyr :: mutate - 在返回的列表中添加所有元素

时间:2018-04-23 15:47:42

标签: r dplyr

我有一个返回列表的函数。我使用mutate在与输出对应的数据框中添加列。计算相当复杂,所以我宁愿只调用一次函数。我对R和dplry很新,并且无法找到一种更有效的方法。

这是我现在正在做的一个非常简单的例子。

library(dplyr)

testFun <- function(x,z)
{
  list(x2=x*x + z, x3=x*x*x + z)
}

have <- data.frame(x=seq(1:10),y=1,z=0)

want <- have %>%
        dplyr::mutate(x2=testFun(x,z)$x2,
                      x3=testFun(x,z)$x3)

如何更有效地完成这项工作?

4 个答案:

答案 0 :(得分:6)

使用purrr - 包可以解决此问题,例如:

library(purrr)
library(dplyr)

testFun <- function(x,z) {
  tibble(x2=x*x + z, x3=x*x*x + z)
}

have %>%
  mutate(new_x = map2(x, z, testFun)) %>% 
  unnest(new_x)

#     x y z  x2   x3
# 1   1 1 0   1    1
# 2   2 1 0   4    8
# 3   3 1 0   9   27
# 4   4 1 0  16   64
# 5   5 1 0  25  125
# 6   6 1 0  36  216
# 7   7 1 0  49  343
# 8   8 1 0  64  512
# 9   9 1 0  81  729
# 10 10 1 0 100 1000

请注意,我将函数的输出从列表更改为tibble。

答案 1 :(得分:5)

我们可以使用pmap

library(purrr)
library(dplyr)
pmap_dfr(have %>% 
              select(x, z), testFun) %>%
   bind_cols(have, .)
#    x y z  x2   x3
#1   1 1 0   1    1
#2   2 1 0   4    8
#3   3 1 0   9   27
#4   4 1 0  16   64
#5   5 1 0  25  125
#6   6 1 0  36  216
#7   7 1 0  49  343
#8   8 1 0  64  512
#9   9 1 0  81  729
#10 10 1 0 100 1000

或者如果我们可以通过引用(quotequo)来更改功能,那么这就变得更容易了

testFun <- function(x,z){
  list(x2= quo(x*x + z), x3= quo(x*x*x + z))
 }

have %>% 
   mutate(!!! testFun(x, z))
#    x y z  x2   x3
#1   1 1 0   1    1
#2   2 1 0   4    8
#3   3 1 0   9   27
#4   4 1 0  16   64
#5   5 1 0  25  125
#6   6 1 0  36  216
#7   7 1 0  49  343
#8   8 1 0  64  512
#9   9 1 0  81  729
#10 10 1 0 100 1000

答案 2 :(得分:2)

我可能在这里错过了一些非常明显的东西,但是你似乎两次运行该函数来产生两个答案。为了让事情变得非常简单,请尝试:

library(dplyr)

have <- data.frame(x=seq(1:10),y=1,z=0)

want <- have %>%
        dplyr::mutate(x2 = (x * 2 + z),
                      x3 = (x * 3 + z))

这有帮助吗?或者你的例子简化了你想要实现的目标?

答案 3 :(得分:1)

对mutate使用不同的函数,你应该能够:

library(dplyr)

createMultiX <- function(inputX, inputZ, multiplier) {
  inputX * multiplier + inputZ
}


have <- data.frame(x=seq(1:10),y=1,z=0)

want <- have %>%
        dplyr::mutate(x2 = createMultiX(x, z, 2),
                      x3 = createMultiX(x, z, 3))

(事先道歉,因为我在没有访问R终端的情况下盲目地写这个,所以希望它第一次没有错别字!)