2

I was writing up notes to compare apply() and sweep() and discovered the following strange differences. In order the generate the same result, sweep() needs MARGIN = 1 while apply wants MARGIN = 2. Also the argument specifying the matrix is uppercase X in apply() but lowercase in sweep().

my.matrix <- matrix(seq(1,9,1), nrow=3)
row.sums <- rowSums(my.matrix)
apply.matrix <- apply(X = my.matrix, MARGIN = 2, FUN = function (x) x/row.sums)
sweep.matrix <- sweep(x = my.matrix, MARGIN = 1, STATS = rowSums(my.matrix), FUN="/")
apply.matrix - sweep.matrix ##yup same matrix

Isn't sweep() an "apply-type" function? Is this just another R quirk or have I lost my mind?

Mark R
  • 775
  • 1
  • 8
  • 23
  • What is your question, i.e., what exactly is unclear after reading the documentation? – Roland Sep 22 '16 at 12:59
  • Question: do two closely related functions indeed have different syntax for the same problem? – Mark R Sep 22 '16 at 13:01
  • Note that R has been developed over a long time and R-Core takes great care not to break existing code. Both of these functions are probably a legacy from S and compatibility with S/S-PLUS was a great concern in the early days. – Roland Sep 22 '16 at 13:24

1 Answers1

5

Note that for apply,

If each call to ‘FUN’ returns a vector of length ‘n’, then ‘apply’ returns an array of dimension ‘c(n, dim(X)[MARGIN])’ if ‘n > 1’

In your example, MARGIN can (and should) be set to 1 in both cases; but the returned value from apply should be transposed. This is easiest to see if the original matrix is not square:

my.matrix <- matrix(seq(1,12,1), nrow=4)
apply.matrix <- t(apply(X = my.matrix, MARGIN = 1, FUN = function(x) x/sum(x)))
sweep.matrix <- sweep(x = my.matrix, MARGIN = 1, STATS = rowSums(my.matrix), FUN="/")
all.equal(apply.matrix, sweep.matrix)
# [1] TRUE

Also see this answer to Can you implement 'sweep' using apply in R?, which says very much the same thing.

Community
  • 1
  • 1
Weihuang Wong
  • 12,868
  • 2
  • 27
  • 48