R:使用管道 %>% 和占位符进一步子集选择

R: Further subset a selection using the pipe %>% and placeholder

我最近发现了管道运算符%>%,它可以使代码更具可读性。这是我的 MWE.

library(dplyr)                                          # for the pipe operator
library(lsr)                                            # for the cohensD function

set.seed(4)                                             # make it reproducible
dat <- data.frame(                                      # create data frame
    subj = c(1:6),
    pre  = sample(1:6, replace = TRUE),
    post = sample(1:6, replace = TRUE)
)

dat %>% select(pre, post) %>% sapply(., mean)           # works as expected

但是,在这种特殊情况下,我很难使用管道运算符

dat %>% select(pre, post) %>% cohensD(.$pre, .$post)    # piping returns an error
cohensD(dat$pre, dat$post)                              # classical way works fine

为什么不能将占位符 .$ 结合使用来对列进行子集化?使用管道运算符 %>% 来编写这一行是否值得,或者它是否会使语法复杂化?经典的写法看起来更简洁

它不起作用,因为 . 运算符必须直接用作参数,而不是在调用中的嵌套函数(如 $...)中使用。

如果你真的想使用管道,你可以用公式界面来做,但之前有一点整形(熔体来自reshape2包):

dat %>% select(pre, post) %>% melt %>% cohensD(value~variable, .)
#### [1] 0.8115027

这可行:

dat %>% select(pre, post) %>% {cohensD(.$pre, .$post)}

将最后一次调用用大括号括起来,使其被视为表达式而不是函数调用。当您将某些内容通过管道传递到表达式中时,.按预期被替换。我经常使用这个技巧来调用与管道接口不佳的函数。

大括号内的内容恰好是一个函数调用,但实际上可以是 . 的任何表达式。

由于您要将一堆数据转化为一个(行)值,因此您是在进行总结。在 dplyr 管道中,您可以使用 summarize 函数,在 summarize 函数中您不需要子集,只需调用 prepost

像这样:

dat %>% select(pre, post) %>% summarize(CD = cohensD(pre, post)) 

(在这种情况下 select 语句实际上不是必需的,但我将其保留以显示其在管道中的工作原理)