【发布时间】:2017-12-19 20:34:09
【问题描述】:
在 dplyr 管道中调用任意函数时,将当前组中的所有列作为 tibble 或 data.frame 发送到函数的首选方法是什么?
在下面的例子中,mean_B 是一个简单的例子,我知道在调用函数之前需要什么。 mean_B_fun 给出了错误的答案(与我想要的相比——我想要组内的意思),mean_B_fun_ugly 给出了我想要的答案,但这似乎既是一种低效(而且丑陋)的方式来获得我想要的效果想要。
我想对任意列进行操作的原因是,在实践中,我在下面的示例中从用户那里获取my_fun,并且我不知道用户需要先验操作的列.
library(dplyr)
my_fun <- function(x) mean(x$B)
my_data <-
expand.grid(A=1:3, B=1:2) %>%
mutate(B=A*B) %>%
group_by(A) %>%
mutate(mean_B=mean(B),
mean_B_fun=my_fun(.),
mean_B_fun_ugly=my_fun(as.data.frame(.)[.$A == unique(A),,drop=FALSE]))
【问题讨论】:
-
mutate_all将按组将函数应用于除分组列之外的所有列。对于my_fun,参数x应该是一个向量,函数中的操作应该是mean(x),因为mutate 将传递来自给定列的值向量。 -
tidyverse中基本上有两种类型的函数:1) 将数据帧作为第一个参数的函数(用于管道,例如 tidyr::separate 或 dplyr::top_n)和 2)那些采用向量的(例如stringr中的所有函数或许多base函数,例如mean、max、sum)——这些通常用于mutate语句中。有些可以采用 df 或矢量(如purrr::map),但行为会有所不同。您的用户函数应该是类型 2 - 它应该采用向量,而不是数据框。假设用户没有在函数内设置子集,group_by将被接受。 -
@eipi10 用户可能需要将一个函数应用于多个列以获取其函数的输出。一般来说,写成
mean(x$B)也可以写成mean(x$B) + mean(x$A),我不知道他们需要哪些列。 -
@dmi3kno,“您的用户函数应该...采用向量,而不是数据帧。”我不能对我的用户做出这种限制。在一个函数调用中,他们可能需要列
A,在下一个函数调用中,他们可能需要列B,在下一个函数调用中,他们可能同时需要A和B。更一般地说,我不知道用户数据集中的所有列名,它们对用户意味着什么,以及哪些是重要的。