我正在尝试使用自定义函数来使用管道变异语句。我看起来有点相似SO post但徒劳。
假设我有一个像这样的数据框(其中 blob
是一些与特定任务无关的变量,但它是整个数据的一部分):
df <-
data.frame(exclude=c('B','B','D'),
B=c(1,0,0),
C=c(3,4,9),
D=c(1,1,0),
blob=c('fd', 'fs', 'sa'),
stringsAsFactors = F)
我有一个使用变量名称的函数,因此请根据排除
列中的值选择一些变量名称,例如计算排除中未指定的变量的总和(始终为单个字符)。
FUN <- function(df){
sum(df[c('B', 'C', 'D')] [!names(df[c('B', 'C', 'D')]) %in% df['exclude']] )
}
当我向 FUN
提供单行(第 1 行)时,我得到了 C
和 D
的预期总和(那些未提及的通过排除
),即4:
FUN(df[1,])
如何在具有 mutate 的管道中执行类似操作(将结果添加到变量 s
)。这两次尝试不起作用:
df %>% mutate(s=FUN(.))
df %>% group_by(1:n()) %>% mutate(s=FUN(.))
更新 这也无法按预期工作:
df %>% rowwise(.) %>% mutate(s=FUN(.))
这是有原因的,但不在 dplyr 的 mutate(和管道)内:
df$s <- sapply(1:nrow(df), function(x) FUN(df[x,]))
最佳答案
如果您想使用dplyr
您可以使用 rowwise
来执行此操作和你的功能FUN
.
df %>%
rowwise %>%
do({
result = as_data_frame(.)
result$s = FUN(result)
result
})
使用 group_by
也可以实现同样的效果而不是rowwise
(就像你已经尝试过的那样)但是使用 do
而不是mutate
df %>%
group_by(1:n()) %>%
do({
result = as_data_frame(.)
result$s = FUN(result)
result
})
原因mutate
在这种情况下不起作用,是您将整个 tibble 传递给它,所以这就像调用 FUN(df)
.
执行相同操作的更有效方法是仅创建要包含的列矩阵,然后使用 rowSums
.
cols <- c('B', 'C', 'D')
include_mat <- outer(function(x, y) x != y, X = df$exclude, Y = cols)
# or outer(`!=`, X = df$exclude, Y = cols) if it's more readable to you
df$s <- rowSums(df[cols] * include_mat)
关于R:逐行 dplyr::mutate 使用接受数据帧行并返回整数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44264450/