finding sum of of squares using pipe

Viewed 176

If x <- 1:5 then the following:

sum(x^2)

returns 55, the correct answer. However, if the pipe operator is used:

x %>% sum(.^2)

then this returns 70 (which happens to be the sum of x^2 and the sum of x).

Although there are some ways around this, I mainly would like to know what's going on.

3 Answers

Interesting question!

What's going on is that the pipe automatically passes its argument as the first argument to the following expression, so x %>% sum(.^2) is equivalent to sum(x, x^2).

I'm more used to working with %>% in a data-frame/tidyverse context, where the first argument to each of the tidyverse verbs (e.g. mutate, filter, select) is itself a data frame:

data.frame(x) %>% dplyr::mutate(y=sum(x^2))

You can do:

x %>%
.^2 %>%
 sum()

[1] 55

It works as the sum() line takes the output of the previous line (.^2) as it input. On the other hand, in your original approach, the sum() line takes as its input, both, the original vector and the power of it and sums it together.

Altenatively:

x %>%
 {sum(.^2)}

Here, by using braces, the content of left-hand side (LHS), which is the original vector in your case, is not being used as the sum() function's first argument (as explained by @Ben Bolker).

A more generalizable approach may be to build your own function, then pipe to that.

For example,

SqSum <- function(x){
  sum(x^2)
}
x %>% SqSum()

We can now use the same framework to do whatever operations we want.

Also note we avoid many errors that would go unnoticed. For example, using x %>% SqSum(.x) will return an error, as we only specified one argument for our function. This defensive style programming can be useful.

As for explanation, Ben nailed it...

Related