2

I am learning how to use the R package collapse to process the data. The syntax in collapse is similar to dplyr, with similar function names. Below is an example. Both code chunks work well. But since both packages contain the function across. I want to know if the second code chunk is actually using the across function from dplyr.

library(dplyr)
library(collapse)

# Group by cyl, then calculate mean for each columns using dplyr
mtcars %>%
  group_by(cyl) %>%
  summarise(across(.fns = mean)) 
# # A tibble: 3 × 11
# cyl   mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     4  26.7  105.  82.6  4.07  2.29  19.1 0.909 0.727  4.09  1.55
# 2     6  19.7  183. 122.   3.59  3.12  18.0 0.571 0.429  3.86  3.43
# 3     8  15.1  353. 209.   3.23  4.00  16.8 0     0.143  3.29  3.5 

# Group by cyl, then calculate mean for each columns using collapse
mtcars %>%
  fgroup_by(cyl) %>%
  fsummarise(across(.fns = fmean)) 
# cyl      mpg     disp        hp     drat       wt     qsec        vs        am     gear     carb
# 1   4 26.66364 105.1364  82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
# 2   6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
# 3   8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000

I then tried the following code, specifying the across function from the collapse package, but it leads to an error.

mtcars %>%
  fgroup_by(cyl) %>%
  fsummarise(collapse::across(.fns = fmean)) 

Error in fsummarise(., collapse::across(.fns = fmean)) :
expressions need to be named or start with across(), or its shorthand acr().

It turns out collapse::across leads to an error showing that across is not in the collapse package.

collapse::across

Error: 'across' is not an exported object from 'namespace:collapse'

collapse:::across shows the functions as follows.

function (.cols = NULL, .fns, ..., .names = NULL, .apply = "auto", 
    .transpose = "auto") 
{
    stop("across() can only work inside fmutate() and fsummarise()")
}
<bytecode: 0x0000018a76156648>
<environment: namespace:collapse>

But the following still fails.

mtcars %>%
  fgroup_by(cyl) %>%
  fsummarise(collapse:::across(.fns = fmean)) 

Error in fsummarise(., collapse:::across(.fns = fmean)) :
expressions need to be named or start with across(), or its shorthand acr().

I want to know why collapse::across could not export the function, and if there are alternatives to specify a function in a specific package.

www
  • 38,575
  • 12
  • 48
  • 84
  • @RitchieSacramento Thanks. Are you using `R 4.2.2` and `collapse 1.8.9`? – www Jan 10 '23 at 04:03
  • The issue is caused by this line in `fsummarise()` where using anything but the bare function names `across`/`acr` causes the check to fail: `if (ei[[1L]] != quote(across) && ei[[1L]] != quote(acr))`. – Ritchie Sacramento Jan 10 '23 at 04:41
  • @RitchieSacramento Thanks. So `fsummarise` can only accept `across/acr` as the function inside. It would still be nice if there is a way to specify which `across` to use. – www Jan 10 '23 at 05:24
  • 1
    Can I ask what the goal is here? Given that `across()` whether it be for `dplyr` or `collapse` only work in the context of other functions in their respective package being able to specify which `across()` to use is redundant because you could only specify one - they're not interchangeable. Re the statement"I want to know if the second code chunk is actually using the across function from dplyr" - it is not, it shares the name and the functionality but is an entirely different function. – Ritchie Sacramento Jan 10 '23 at 07:59
  • 1
    @RitchieSacramento I am writing my own functions with my workspace both loaded with `dplyr` and `collapse`. I thought it is a good practice to specify which `across` function I am using. But based on your explanation, both `summarise` and `fsummarise` can load their associated `across` function correctly, then I will not need to worry about that. – www Jan 10 '23 at 08:38
  • @RitchieSacramento I can move on with my actual work now. The only thing left is why `collapse::across` does not work. I was taught that `package::function name` is the way to export a function from a package, but probably not for all of them, which is fine. If someone can provide some explanation on that, I will be grateful and accept his/her answer. – www Jan 10 '23 at 08:41
  • @RitchieSacramento By the way, I am also curious how `summarise` and `fsummarise` can load their associated `across` functions correctly without being confused. But if the explanations are beyond the scope of question in Stack Overflow, then it is fine. As I mentioned, I can continue my work now. – www Jan 10 '23 at 08:49
  • @RitchieSacramento Thanks. So you are saying some functions in a package are internal function and could not be exported? – www Jan 11 '23 at 02:48
  • 2
    This should be written up as an answer, but the package author is active and may post an authoritative response. What I believe is happening is 1) `across` does not exist as an exported function, although it is documented. 2) The internal function `across` exists just to error if called in an incorrect context. 3) Calling `across` in `fsummarise`/`fmutate` results in the call being captured and replaced with the internal function `do_across`. Presumably it has been implemented this way to provide a familiar `dplyr`-like interface but to avoid conflict with `dplyr`. – Ritchie Sacramento Jan 11 '23 at 03:20

1 Answers1

2

In collapse, across() is an internal function only for use inside fsummarise() and fmutate(). It can be abbreviated using acr(). It does not have any use outside fsummarise and fmutate, and therefore does not need to be exported (which avoids namespace conflicts with dplyr and me having to create facross() or something like that).

Since fsummarise() and fmutate() lazily evaluate expressions, they will detect that across() is being passed, and will always use the collapse version. They do not support dplyr::across() and also were not meant to parse something like collapse:::across(), which is dangerous and redundant.

So if collapse is not attached, using collapse::fsummarise(across(...)) is sufficient.

Sebastian
  • 1,067
  • 7
  • 12