【问题标题】:dplyr summarise() and summarise_each() make extra calls to the provided functionsdplyr summarise() 和 summarise_each() 对提供的函数进行额外调用
【发布时间】:2017-01-07 06:51:19
【问题描述】:

似乎summarisesummarise_each 对它们提供的回调函数进行了不必要的额外调用。假设我们有以下

X <- data.frame( Group = rep(c("G1","G2"),2:3), Var1 = 1:5, Var2 = 11:15 )

看起来像这样:

   Group Var1 Var2
 1    G1    1   11
 2    G1    2   12
 3    G2    3   13
 4    G2    4   14
 5    G2    5   15

进一步假设我们有一个(可能很昂贵的)函数

f <- function(v)
{
   cat( "Calling f with vector", v, "\n" )
   ## ...additional bookkeeping and processing...
   mean(v)
}

我们希望将其应用于每个组中的每个变量。使用dplyr,我们可以通过以下方式进行:

X %>% group_by( Group ) %>% summarise_each( funs(f) )

但是,输出显示 f 为 G1 中的每个变量额外调用了一次:

Calling f with vector 1 2 
Calling f with vector 1 2 
Calling f with vector 3 4 5 
Calling f with vector 11 12 
Calling f with vector 11 12 
Calling f with vector 13 14 15 
# A tibble: 2 x 3
   Group  Var1  Var2
  <fctr> <dbl> <dbl> 
1     G1   1.5  11.5
2     G2   4.0  14.0

使用summarize时也会出现同样的问题:

> X %>% group_by( Group ) %>% summarise( test = f(Var1) )
Calling f with vector 1 2
Calling f with vector 1 2
Calling f with vector 3 4 5
# A tibble: 2 × 2
   Group  test
  <fctr> <dbl>
1     G1   1.5
2     G2   4.0

为什么会发生这种情况?如何防止summarisesummarise_each 拨打这些额外电话?

(这是使用R 3.3.0 版和dplyr 0.5.0 版)

编辑:看来问题与group_bysummarise/summarise_each 之间的相互作用有关。没有分组,就不会进行额外的调用。此外,mutatemutate_each 不会遇到此问题。 (信用:eddieipi10 这些发现)

【问题讨论】:

  • 您可以进一步缩小范围 - 问题在于 summarise(和 group_by
  • mutatemutate_each 不会出现此错误(与 group_by 一起使用时)
  • 但是如果你先group_by然后mutate或者mutate_each,就没有额外的函数调用了,所以看起来和summarise/summarise_each有关,但是只有在使用group_by的时候才可以
  • 代码是here,但我无法完全解析发生了什么。我认为每个变量的额外调用可能是它试图弄清楚它是否可以在 C/C++ 中做更多的结果,但这是一个猜测。
  • 还有一个解决方法:purrr::dmap 没有这个问题并且尊重分组:X %&gt;% group_by(Group) %&gt;% purrr::dmap(f)

标签: r dplyr


【解决方案1】:

虽然这个问题在 dplyr 0.5.0(2016-06-24 发布)中仍然存在,但它已在 dplyr GitHub repro 中修复。它已在 2016 年 9 月 24 日用this commit 修复。我已经确认,当我在上一次提交中签出并构建版本时,我可以重现该问题,但在从该版本或后续版本构建时不能重现。

(是的,我在找到之前尝试了一大堆其他方法。为什么我要花这么多时间来获得想象中的互联网积分,我留给我的治疗师一个问题。:)

特别是在inst/include/dplyr/Result/CallbackProcessor.h 中的函数SEXP process_data(const Data&amp; gdf) 中,请注意以下更改:

  CLASS* obj = static_cast<CLASS*>(this);
  typename Data::group_iterator git = gdf.group_begin();

  RObject first_result = obj->process_chunk(*git);
  ++git; // This line was added

  for (int i = 1; i < ngroups; ++git, ++i) { // changed from starting at i = 0
    RObject chunk = obj->process_chunk(*git);

[评论由我添加,不是实际来源的一部分]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 2016-08-07
    相关资源
    最近更新 更多