Why anything but sweep? The fundamental data type in Matlab is a matrix... they don't have vectors, they have Nx1 matrices and 1xM matrices. Vectors don't have any concept of "row" vs. "column". Straight division is always elementwise with recycling as needed, and matrices are really vectors in row-major order: 1 2 3 4 5 6 is really 1 4 2 5 3 6 and when you do straight division NN / lambda then lambda is repeated: 1 4 2 5 3 6 2 3 4 2 3 4 to get 0.5 1.3 0.5 2.5 1.0 1.5 but if you transpose first 1 4 2 5 3 6 then that corresponds to an underlying vector: 1 2 3 4 5 6 which lines up with lambda in t(NN)/lambda as: 1 2 3 4 5 6 2 3 4 2 3 4 to obtain: 0.50 0.67 0.75 2.0 1.67 1.50 and inherits the dimensions of t(NN): 0.50 2.00 0.67 1.67 0.75 1.50 which can be transposed back as in t( t( NN ) / lambda ): 0.50 0.67 0.75 2.00 1.67 1.50 but that requires a lot of moving elements around while sweep does not. Operators are not necessarily "better" than named functions... they just look different. On February 27, 2024 11:54:26 AM PST, Evan Cooch <evan.cooch at gmail.com> wrote:>So, trying to convert a very long, somewhat technical bit of lin alg >MATLAB code to R. Most of it working, but raninto a stumbling block that >is probaably simple enough for someone to explain. > >Basically, trying to 'line up' MATLAB results from an element-wise >division of a matrix by a vector with R output. > >Here is a simplified version of the MATLAB code I'm translating: > >NN = [1, 2, 3; 4, 5, 6];? % Example matrix >lambda = [2, 3, 4];? % Example vector >result_matlab = NN ./ lambda; > >which yields > > ?0.50000?? 0.66667?? 0.75000 > ?2.00000?? 1.66667?? 1.50000 > > >So, the only way I have stumbled onto in R to generate the same results >is to use 'sweep'. The following 'works', but I'm hoping someone can >explain why I need something as convoluted as this seems (to me, at least). > >NN <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, byrow = TRUE)? # Example matrix >lambda <- c(2, 3, 4)? # Example vector >sweep(NN, 2, lambda, "/") > > > ???? [,1]????? [,2] [,3] >[1,]? 0.5 0.6666667 0.75 >[2,]? 2.0 1.6666667 1.50 > >First tried the more 'obvious' NN/lambda, but that yields 'the wrong >answer' (based solely on what I'm trying to accomplish): > > > ?????? [,1] [,2] [,3] >[1,] 0.500000? 0.5? 1.0 >[2,] 1.333333? 2.5? 1.5 > >So, why 'sweep'? > > [[alternative HTML version deleted]] > >______________________________________________ >R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >https://stat.ethz.ch/mailman/listinfo/r-help >PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >and provide commented, minimal, self-contained, reproducible code.-- Sent from my phone. Please excuse my brevity.
Berwin A Turlach
2024-Feb-28 09:42 UTC
[R] converting MATLAB -> R | element-wise operation
On Tue, 27 Feb 2024 13:51:25 -0800 Jeff Newmiller via R-help <r-help at r-project.org> wrote:> The fundamental data type in Matlab is a matrix... they don't have > vectors, they have Nx1 matrices and 1xM matrices.Also known as column vectors and row vectors. :)> Vectors don't have any concept of "row" vs. "column".They do in (numerical) linear algebra. And MATLAB was written by numerical analysts for numerical analysts. :-) So they distinguish between row and column vectors. GAUSS also distinguishes between row and column vectors. R (and S) does not distinguish between row and column vectors, and is in this aspect quite unique among the groups of vector-oriented programming languages (AFAICT). But treating every vector as a column vector, together with the recycling rule, allows for the easy coding of the matrix/vector calculations that one (mostly) comes across in statistical computing. For the rare occasion when this is not true the sweep() command is provided, typically remembered once one was bitten by the lack of distinction between row and column vectors. :) Cheers, Berwin
Agree that sweep is the tool here. (If you think it is clunky, check how more general array-sweep operations can be done in Matlab.) However, it isn't really true that sweep isn't moving things around. Notice the call to aperm() at the end of the code for sweep(): perm <- c(MARGIN, seq_along(dims)[-MARGIN]) FUN(x, aperm(array(STATS, dims[perm]), order(perm)), ...) What this essentially does for "our" case is> rbind(1:3,4:6)/t(matrix(c(2,3,4), 3,2))[,1] [,2] [,3] [1,] 0.5 0.6666667 0.75 [2,] 2.0 1.6666667 1.50 I.e. take the matrix, create the divisor by replicating STATS to form a matrix of same size. This is easier if the MARGIN indices come first, because the recycling works. So you get the 2x3 matrix by filling a 3x2 and then transposing it (aperm() does this more generally). Finally, just call FUN on the two arrays. -pd> On 27 Feb 2024, at 22:51 , Jeff Newmiller via R-help <r-help at r-project.org> wrote: > > Why anything but sweep? > > The fundamental data type in Matlab is a matrix... they don't have vectors, they have Nx1 matrices and 1xM matrices. > > Vectors don't have any concept of "row" vs. "column". Straight division is always elementwise with recycling as needed, and matrices are really vectors in row-major order: > > 1 2 3 > 4 5 6 > > is really > > 1 4 2 5 3 6 > > and when you do straight division NN / lambda then lambda is repeated: > > 1 4 2 5 3 6 > 2 3 4 2 3 4 > > to get > > 0.5 1.3 0.5 2.5 1.0 1.5 > > but if you transpose first > > 1 4 > 2 5 > 3 6 > > then that corresponds to an underlying vector: > > 1 2 3 4 5 6 > > which lines up with lambda in t(NN)/lambda as: > > 1 2 3 4 5 6 > 2 3 4 2 3 4 > > to obtain: > > 0.50 0.67 0.75 2.0 1.67 1.50 > > and inherits the dimensions of t(NN): > > 0.50 2.00 > 0.67 1.67 > 0.75 1.50 > > which can be transposed back as in t( t( NN ) / lambda ): > > 0.50 0.67 0.75 > 2.00 1.67 1.50 > > but that requires a lot of moving elements around while sweep does not. > > Operators are not necessarily "better" than named functions... they just look different. > > > On February 27, 2024 11:54:26 AM PST, Evan Cooch <evan.cooch at gmail.com> wrote: >> So, trying to convert a very long, somewhat technical bit of lin alg >> MATLAB code to R. Most of it working, but raninto a stumbling block that >> is probaably simple enough for someone to explain. >> >> Basically, trying to 'line up' MATLAB results from an element-wise >> division of a matrix by a vector with R output. >> >> Here is a simplified version of the MATLAB code I'm translating: >> >> NN = [1, 2, 3; 4, 5, 6]; % Example matrix >> lambda = [2, 3, 4]; % Example vector >> result_matlab = NN ./ lambda; >> >> which yields >> >> 0.50000 0.66667 0.75000 >> 2.00000 1.66667 1.50000 >> >> >> So, the only way I have stumbled onto in R to generate the same results >> is to use 'sweep'. The following 'works', but I'm hoping someone can >> explain why I need something as convoluted as this seems (to me, at least). >> >> NN <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, byrow = TRUE) # Example matrix >> lambda <- c(2, 3, 4) # Example vector >> sweep(NN, 2, lambda, "/") >> >> >> [,1] [,2] [,3] >> [1,] 0.5 0.6666667 0.75 >> [2,] 2.0 1.6666667 1.50 >> >> First tried the more 'obvious' NN/lambda, but that yields 'the wrong >> answer' (based solely on what I'm trying to accomplish): >> >> >> [,1] [,2] [,3] >> [1,] 0.500000 0.5 1.0 >> [2,] 1.333333 2.5 1.5 >> >> So, why 'sweep'? >> >> [[alternative HTML version deleted]] >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. > > -- > Sent from my phone. Please excuse my brevity. > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.-- Peter Dalgaard, Professor, Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Office: A 4.23 Email: pd.mes at cbs.dk Priv: PDalgd at gmail.com