当自定义函数返回向量时 dplyr::mutate

Buo*_* Xu 1 r dplyr

我正在尝试使用返回向量的自定义函数dplyr::mutategroup_by数据和创建新列,并且该函数需要很长时间才能引导。

\n

我知道这可以在基础 R 中实现,但是 dplyr 中有更优雅的方法吗?

\n

示例(已废弃):

\n
iris %>% \n  group_by(Species) %>% \n  mutate(t1 = f(iris$Sepal.Length)[1], t2 = f(iris$Sepal.Length)[2])\n\nf <- function(x) {\n  return(c(2*x, x+1))\n}\n
Run Code Online (Sandbox Code Playgroud)\n

是否可以创建两列,每组中只调用一次该函数?

\n
\n

我在前面的示例中犯了一个错误。请检查这个示例:

\n

例子:

\n
f <- function(x) {\n  return(c(x*2, x+1))\n}\n\niris %>% \n  group_by(Species) %>% \n  \n  group_modify(~ {\n    .x %>% \n      mutate(t1 := f(mean(.x$Sepal.Length))[1], t2 := f(mean(.x$Sepal.Length))[2])\n  })\n
Run Code Online (Sandbox Code Playgroud)\n
\n

方法一:

\n

感谢蔡达伦的回答!unnest_wider使用新示例解决了该问题:

\n
library(dplyr)\nlibrary(tidyr)\n\niris %>% \n  group_by(Species) %>% \n  group_modify(~ {\n    .x %>% \n      mutate(t = list(f(mean(.x$Sepal.Length)))) %>% \n      unnest_wider(t, names_sep = "")\n  })\n\n# A tibble: 150 \xc3\x97 7\n# Groups:   Species [3]\n   Species Sepal.Length Sepal.Width Petal.Length Petal.Width    t1    t2\n   <fct>          <dbl>       <dbl>        <dbl>       <dbl> <dbl> <dbl>\n 1 setosa           5.1         3.5          1.4         0.2  10.0  6.01\n 2 setosa           4.9         3            1.4         0.2  10.0  6.01\n 3 setosa           4.7         3.2          1.3         0.2  10.0  6.01\n 4 setosa           4.6         3.1          1.5         0.2  10.0  6.01\n 5 setosa           5           3.6          1.4         0.2  10.0  6.01\n 6 setosa           5.4         3.9          1.7         0.4  10.0  6.01\n 7 setosa           4.6         3.4          1.4         0.3  10.0  6.01\n 8 setosa           5           3.4          1.5         0.2  10.0  6.01\n 9 setosa           4.4         2.9          1.4         0.2  10.0  6.01\n10 setosa           4.9         3.1          1.5         0.1  10.0  6.01\n# \xe2\x80\xa6 with 140 more rows\n# \xe2\x84\xb9 Use `print(n = ...)` to see more rows\n
Run Code Online (Sandbox Code Playgroud)\n

方法二:

\n

感谢康拉德·鲁道夫的建议!更灵活的方式来回答这个问题!

\n
to_tibble <- function (x, colnames) {\n  x %>%\n    matrix(ncol = length(colnames), dimnames = list(NULL, colnames)) %>%\n    as_tibble()\n}\niris %>%\n  group_by(Species) %>%\n  mutate(to_tibble(f(mean(Sepal.Length)), c("t1", "t2")))\n
Run Code Online (Sandbox Code Playgroud)\n

Kon*_*lph 6

您的代码的问题在于它将向量传递给f,因此结果可能不是您所期望的\xe2\x80\x99:

\n
f(1 : 5)\n# [1]  2  4  6  8 10  2  3  4  5  6                                        \n
Run Code Online (Sandbox Code Playgroud)\n

您的调用代码必须解决这个问题。

\n

可以这样做,例如使用以下助手:

\n
to_tibble <- function (x, colnames) {\n    x %>%\n        matrix(ncol = length(colnames), dimnames = list(NULL, colnames)) %>%\n        as_tibble()\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这样,您现在可以调用f内部mutate并提供目标列名称:

\n
iris %>%\n    group_by(Species) %>%\n    mutate(to_tibble(f(Sepal.Length), c("t1", "t2"))\n
Run Code Online (Sandbox Code Playgroud)\n

这种方法的优点是它简化了调用代码,并mutate利用 \xe2\x80\x99s 的内置支持来生成多个列 \xe2\x80\x94 ,无需手动取消嵌套。

\n
\n

关于更新的代码/要求,您也可以使用辅助函数来简化:

\n
iris %>%\n    group_by(Species) %>%\n    mutate(to_tibble(f(Sepal.Length), c("t1", "t2"))\n
Run Code Online (Sandbox Code Playgroud)\n