Home > Enterprise >  Different outputs with pipe after arithmetic operator vs calling it directly
Different outputs with pipe after arithmetic operator vs calling it directly

Time:05-24

I'm getting an unexpected result when piping a matrix into as.data.frame and could use some wisdom on why it's happening. When I run the below code:

library(magrittr)
matrix(c(1,0,0,1), nrow = 2)*5 %>% as.data.frame()

I'm expecting to get

  V1 V2
1  5  0
2  0  5

but instead I get

  .
1 5

This is confusing because it works fine when I wrap the as.data.frame call around the matrix construction:

> as.data.frame(matrix(c(1,0,0,1), nrow = 2)*5)
  V1 V2
1  5  0
2  0  5

and when I pipe the multiplication function as well:

> matrix(c(1,0,0,1), nrow = 2) %>% `*`(5) %>% as.data.frame()
  V1 V2
1  5  0
2  0  5

and when I save the intermediate result and pipe that into the next function:

> v <- matrix(c(1,0,0,1), nrow = 2)*5
> v %>% as.data.frame()
  V1 V2
1  5  0
2  0  5

This made me pretty sure it's due to the arithmetic operation being performed before sending it into the pipe, which we can confirm with other arithmetic and other functions to ensure it's not particular to the * operator or the as.data.frame function:

# Plus instead of times
> matrix(c(1,0,0,1), nrow = 2) 1 %>% as.data.frame()
  .
1 2

# rowSums instead of as.data.frame()
> matrix(c(1,0,0,1), nrow = 2)*5 %>% rowSums()
Error in rowSums(.) : 'x' must be an array of at least two dimensions

I'm clearly not understanding how pipes work with arithmetic operators or what the arithmetic functions return(?) so I could use some advice for what's happening here. Is this a known quirk of which I haven't been able to find documentation? Hadley's book doesn't mention this being an issue in the chapter on pipes and the Technical Notes section of help("%>%") seems to only caution against functions that capture their calling environment. The final note there mentions arithmetic operators but makes it seem like it's only operator precedence that's affected when the results are different from switching the as.data.frame call and the multiplication step:

matrix(c(1,0,0,1), nrow = 2) %>% as.data.frame() %>% `*`(5)
  V1 V2
1  5  0
2  0  5

Why do I get different results when piping a arithmetically-modified matrix into another function?

CodePudding user response:

As specified by the ?Syntax help page, the %>% operator has a higher precedence than the * operator. This means that

matrix(c(1,0,0,1), nrow = 2) * 5 %>% as.data.frame()

is the same as

matrix(c(1,0,0,1), nrow = 2) * (5 %>% as.data.frame())

So the 5 is passed to as.data.frame before the multiplication with the matrix happens. When combining operators of different precedence, you can be more explicity with () or {} to make sure the order happens in which you expect. These both will work

(matrix(c(1,0,0,1), nrow = 2) * 5) %>% as.data.frame()
{matrix(c(1,0,0,1), nrow = 2) * 5} %>% as.data.frame()
  • Related