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()