Home > Back-end >  "invalid use of pipe placeholder" with base R pipe inside dplyr::mutate
"invalid use of pipe placeholder" with base R pipe inside dplyr::mutate

Time:06-15

Why is this command with base R pipe and placeholder within dplyr::mutate returning an error message ?

library(dplyr)
iris[,-5] |> mutate(Row_sum = apply(X = _, 1, function(x) sum(x)))

#> Error in mutate(iris[, -5], Row_sum = apply(X = "_", 1, function(x) sum(x))) : 
#> invalid use of pipe placeholder

Works fine outside mutate :

iris[,-5] |> apply(X = _, 1, function(x) sum(x))

#>   [1] 10.2  9.5  9.4  9.4 10.2 11.4  9.7 10.1  8.9  9.6 10.8 10.0  9.3  8.5 11.2
#>  [16] 12.0 11.0 10.3 11.5 10.7 10.7 10.7  9.4 10.6 10.3  9.8 10.4 10.4 10.2  9.7
#>  [31]  (...)

Works fine inside mutate with magrittr pipe

iris[,-5] %>% mutate(Row_sum = apply(X = ., 1, function(x) sum(x))) %>% head

#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Row_sum
#> 1          5.1         3.5          1.4         0.2    10.2
#> 2          4.9         3.0          1.4         0.2     9.5
#> 3          4.7         3.2          1.3         0.2     9.4
#> 4          4.6         3.1          1.5         0.2     9.4
#> 5          5.0         3.6          1.4         0.2    10.2
#> 6          5.4         3.9          1.7         0.4    11.4

CodePudding user response:

The problem is you can't use the _ with |> when using nested function calls. For example the first one works, the second does not

5 |> log()
# [1] 1.609438
5 |> log(exp(_))
# Error in log(5, exp("_")) : invalid use of pipe placeholder

Note that |> with _ is a bit different than %>% with . in this case. If you used . with %>% as part of an expression, the full piped object was still passed as the first parameter to the function. So you essentially included it twice. This will never happen with |> and _. For example

iris %>% split(.$Species)

works because it's the same as

split(iris, iris$Species)

Note that the iris basically gets included twice. But this does not work with the new pipe operator

iris |> split(_$Species)
# Error in split(iris, "_"$Species) : invalid use of pipe placeholder

because again it's basically a nested function call (the $ counts as a function call). That's one of the reason they simultaneously updated split to use a formula now as well. So this will work

iris |> split(~Species)

If you just want to add a row sum without the fifth column, you can do

iris |>
    mutate(Row_sums=rowSums(across(-5)))
# or
iris[, -5]|>
    mutate(Row_sums=rowSums(across(everything())))
  • Related