Meaning of if_any .cols = everything() in documentation

The reference for across and if_any includes a line that says if_any (.cols = everything(), ...). I thought that meant that if I did not supply a .cols argument, everything() would be used, but that is not what I observe.

Can someone explain to me what that notation means, or what I am doing wrong?

Example trying to select all rows with any variable greater than 50.

library(tidyverse)
t = 
 tribble(~x, ~y,
         10, 100,
         70, -140,
         -60, 30,
        -121, -300)
t %>% filter(if_any(.fn = ~ . > 50))
#> # A tibble: 0 x 2
#> # … with 2 variables: x <dbl>, y <dbl>
t %>% filter(if_any(everything(), .fn = ~ . > 50))
#> # A tibble: 2 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1    10   100
#> 2    70  -140

Created on 2021-03-01 by the reprex package (v1.0.0)

Session info
sessionInfo()
#> R version 3.6.3 (2020-02-29)
#> Platform: x86_64-conda_cos6-linux-gnu (64-bit)
#> Running under: Linux Mint 19.3
#> 
#> Matrix products: default
#> BLAS/LAPACK: /home/x/.conda/envs/ml/lib/libopenblasp-r0.3.10.so
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] forcats_0.5.0   stringr_1.4.0   dplyr_1.0.4     purrr_0.3.4    
#> [5] readr_1.4.0     tidyr_1.1.2     tibble_3.0.4    ggplot2_3.3.2  
#> [9] tidyverse_1.3.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] Rcpp_1.0.5        cellranger_1.1.0  pillar_1.4.6      compiler_3.6.3   
#>  [5] dbplyr_2.0.0      highr_0.8         tools_3.6.3       digest_0.6.27    
#>  [9] lubridate_1.7.9.2 jsonlite_1.7.1    evaluate_0.14     lifecycle_0.2.0  
#> [13] gtable_0.3.0      pkgconfig_2.0.3   rlang_0.4.10      reprex_1.0.0     
#> [17] cli_2.1.0         DBI_1.1.0         yaml_2.2.1        haven_2.3.1      
#> [21] xfun_0.19         withr_2.3.0       xml2_1.3.2        httr_1.4.2       
#> [25] styler_1.3.2      knitr_1.30        hms_0.5.3         generics_0.1.0   
#> [29] fs_1.5.0          vctrs_0.3.6       grid_3.6.3        tidyselect_1.1.0 
#> [33] glue_1.4.2        R6_2.5.0          fansi_0.4.1       readxl_1.3.1     
#> [37] rmarkdown_2.5     modelr_0.1.8      magrittr_1.5      backports_1.2.0  
#> [41] scales_1.1.1      ellipsis_0.3.1    htmltools_0.5.0   rvest_0.3.6      
#> [45] assertthat_0.2.1  colorspace_2.0-0  utf8_1.1.4        stringi_1.5.3    
#> [49] munsell_0.5.0     broom_0.7.2       crayon_1.3.4

You have a typo as rather than being .fn the parameter has an s
.fns

Although it is not documented, both .fn and .fns are accepted (at least in this case).

You can see that the reprex it is spelled the same both ways, and in the second the action has the desired effect.

I verified that changing .fn to .fns does not change the observed behavior.

Docmo, My apologies.

There seems to be a related erratic issue with if_all().

I've found a couple of reported issues on the Github repo tidyverse / dplyr, but I've not extensively investigated if these are exactly covering this strange behavior. But to me, it also appears not to be working as expected.

library(tidyverse)

t = tribble(~x, ~y,
            10, 100,
            70, -140,
            -60, 30,
            -121, -300
            )

# if_all() ----------------------------------------------------------------
## no .cols argument specified: row 4 should not have been returned
t %>% filter(if_all(.fn = ~ . > -200))
#> # A tibble: 4 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1    10   100
#> 2    70  -140
#> 3   -60    30
#> 4  -121  -300

## .cols argument provided: expected behavior
t %>% filter(if_all(everything(), .fn = ~ . > -200))
#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1    10   100
#> 2    70  -140
#> 3   -60    30

# if_any() ----------------------------------------------------------------
## no .cols argument specified: rows 1 + 2 expected to be returned
t %>% filter(if_any(.fns = ~ . > 50))
#> # A tibble: 0 x 2
#> # ... with 2 variables: x <dbl>, y <dbl>

## .cols argument provided: expected behavior
t %>% filter(if_any(everything(), .fn = ~ . > 50))
#> # A tibble: 2 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1    10   100
#> 2    70  -140

Created on 2021-03-02 by the reprex package (v1.0.0)

On investigation it appears that it is attempting to rely on the .cols default of the across function, however this would not seem to work in general.

if_any
function (.cols, .fns = NULL, ..., .names = NULL) 
{
    df <- across({
        {
            .cols
        }
    }, .fns = .fns, ..., .names = .names)

example of how this doesnt work in general

y<- function(x=5)x
y(7)
# 7
y()
# 5
callsy <- function(x)y(x)
callsy(7)
# 7
callsy()
# Error in y(x) : argument "x" is missing, with no default

Correct answer: the change to the default being .everything() was made Feb 12, 2021 so having dplyr 1.0.4 installed is not recent enough to have this change.

@nirgrahamuk
Your example does not accurately parallel the situation if if_any.
In the source code you can see that the .cols argument of if_any actually does have a default argument. If you can be a little more careful posting a reply we would keep the signal/noise ratio high.

Thanks for the pointer to look in the source code, though.

I diagnosed the issue you had for dplyr 1.0.4 and explained why.
the solution added to the dev version 12days ago simply underlines that my analysis of the situation as you presented it to us was correct...
If the documentation you read was not aligned with the current release of dplyr thats all that is.

Thank you for explaining. I did not understand that I was not looking at the code I was running, and that the code you referenced was from the dplyr 1.0.4 that I was using.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.