rdplyrpipeexpression

Does piping a value to a logical operator inside of stopifnot() create an expression?


The first argument of stopifnot() should contain

any number of R expressions, which should each evaluate to (a logical vector of all) TRUE.

Meanwhile x %>% {. == z} presumably should be an expression that yields TRUE or FALSE. However, the behavior below suggests that this is not happening since the piped examples do not produce TRUE. What's happening?

# Set-up
library(dplyr)

# Data
df <- data.frame(x = 1:10)

# Store values
df_rows <- df_uniques <- df %>% nrow()

# Examples: piping
df_uniques %>% stopifnot(. == nrow(df)) # STOP - not TRUE
df_uniques %>% stopifnot(. == df_rows)  # STOP - not TRUE

# Examples: no pipe
stopifnot(df_uniques == nrow(df))       # TRUE
stopifnot(df_uniques == df_rows)        # TRUE

Solution

  • Look at the error you get:

    > df_uniques %>% stopifnot(. == nrow(df)) # STOP - not TRUE
    Error in stopifnot(., . == nrow(df)) : . is not TRUE
    

    What you're actually running is stopifnot(df_uniques, df_uniques == nrow(df)). The documentation states:

    ..., exprs  
    any number of R expressions, which should each evaluate to (a logical vector of all) TRUE. Use either ... or exprs, the latter typically an unevaluated expression of the form
    
    {
       expr1
       expr2
       ....
    }
    Note that e.g., positive numbers are not TRUE, even when they are coerced to TRUE, e.g., inside if(.) or in arithmetic computations in R.
    

    Specifically note

    Use either ... or exprs, the latter typically an unevaluated expression of the form.

    The function looks at just df_uniques==TRUE, which evaluates false. You can fix it with

    df_uniques %>% {. == nrow(df)} %>% stopifnot()

    or

    df_uniques %>% { stopifnot(. == nrow(df)) } as @G. Grothendieck posted.