使用此示例数据:
library(tidyverse)
set.seed(123)
df <- data_frame(X1 = rep(LETTERS[1:4], 6),
X2 = sort(rep(1:6, 4)),
ref = sample(1:50, 24),
sampl1 = sample(1:50, 24),
var2 = sample(1:50, 24),
meas3 = sample(1:50, 24))
我可以使用summarise_at()
来计算列子集中的值的数量:
df %>% summarise_at(vars(contains("2")), funs(sd_expr = n() ))
这不是很令人兴奋,因为它与行数相同。但是,在具有嵌套列的表中,每个单元格包含一个在每个单元格中具有不同行数的数据框,这将非常有用。
例如,
df %>%
mutate_at(vars(-one_of(c("X1", "X2", "ref"))), funs(first = . - ref)) %>%
mutate_at(vars(contains("first")), funs(second = . *2 )) %>%
nest(-X1) %>%
mutate(mean = map(data,
~ summarise_at(.x, vars(contains("second")),
funs(mean_second = mean(.) ))),
n = map(data,
~ summarise_at(.x, vars(contains("second")),
funs(n_second = n() ))) ) %>%
unnest(mean, n)
然而我收到错误:
mutate_impl(.data,dots)出错:评估错误:无法创建 调用不可调用的对象。
为什么mean()
函数在此上下文中起作用而n()
不起作用?
现在可以做一些工作:
n = map(data, ~ summarise_at(.x, vars(contains("second")),
funs(n_second = length(unique(.)) )))
但是当在不同的行上存在相同的值或者可选地:
时,这不是很强大n = map(data, ~ nrow(.x) )
但这不允许我构建更复杂的summarise_at()
函数,这正是我真正的目标。最后,我想做这样的事情来计算标准误差:
se = map(data, ~ summarise_at(.x, vars(contains("second")),
funs(se_second = sd(.)/sqrt(n()) )))
为什么n()
没有做我认为在这种情况下应该做的事情?
答案 0 :(得分:0)
我相信aosmith的评论是正确的,这是此问题的一个示例:
#2080: Using n() in nested mutate()/summarize() calls gives unexpected results
原因是由于dplyr的混合评估,它可以将某些R函数识别为它知道如何在C ++代码中进行处理的事物,并将其替换。在这种情况下,更换过于激进。特别是mutate
用数字4代替了n()
(因为嵌套后外部数据框中有4行,尽管嵌套的数据帧本身每个都有6行)。您可以通过运行以下命令查看此信息:
library(tidyverse)
set.seed(123)
df <- data_frame(X1 = rep(LETTERS[1:4], 6),
X2 = sort(rep(1:6, 4)),
ref = sample(1:50, 24),
sampl1 = sample(1:50, 24),
var2 = sample(1:50, 24),
meas3 = sample(1:50, 24))
df1 <- df %>%
mutate_at(vars(-one_of(c("X1", "X2", "ref"))), funs(first = . - ref)) %>%
mutate_at(vars(contains("first")), funs(second = . *2 )) %>% print %>%
nest(-X1)
debugonce(map)
df1 %>% mutate(n = map(data,
~ summarize_at(.x,
vars(contains("second")),
funs(n_second = n()))))
在dplyr 0.7.8中,这将产生消息:
debugging in: map(data, ~summarize_at(.x, vars(contains("second")), funs(n_second = 4L)))
当然funs(4)
不起作用,因为4
不可调用,所以您会得到错误。
也许更有害的是您是否尝试通过执行以下操作来修复它:
df1 %>% mutate(n = map(data,
~ summarize_at(.x,
vars(contains("second")),
. %>% { n() }))) %>%
unnest(n)
在dplyr 0.7.8中运行时没有错误,但是给出了错误的答案:4而不是6,因为它使用的是外部数据框中的行数,而不是嵌套的行数。
幸运的是,由于此更改,所有这些都应在dplyr 0.8.0中修复:
有了这一更改,对mutate
的调用将不会替换n()
,因为它不知道如何替换包含该n()
的完整表达式(而且正如我们已经看到,周围的表达式可以改变n()
的含义。
对于在以前的dplyr版本中有效的替代方法,在我看来,可以通过使用group_by
来实现您感兴趣的计算而无需嵌套:
df %>%
mutate_at(vars(-one_of(c("X1", "X2", "ref"))), funs(first = . - ref)) %>%
mutate_at(vars(contains("first")), funs(second = . *2 )) %>%
group_by(X1) %>%
summarise_at(vars(contains("second")),
funs(mean_second = mean(.),
n_second = n(),
se_second = sd(.)/sqrt(n()) ))