Home > Back-end >  Error when using the apply function on a matrix in R
Error when using the apply function on a matrix in R

Time:10-25

I'm trying to use apply to use the L1 norm on each column of a matrix in R. If we have a matrix

X=matrix(data=rnorm(100),nrow=10,ncol=10)

Then when I run

apply(X,2,function(x) norm(x,type="1"))

I get the error:

Error in base::norm(x, type, ...) : 'A' must be a numeric matrix

I've found that this is because when we index X, we lose the matrix type. For example, running

norm(X[,1],type="1")

we get the same error. Hence, I've run

  old <- `[`
`[` <- function(...) { old(..., drop=FALSE) }

To stop the matrix type being dropped when we subset X. Now, this works

norm(X[,1],type="1")

But I still get the same error for

apply(X,2,function(x) norm(x,type="1"))

CodePudding user response:

You could do apply(X, 2, function(x) norm(matrix(x, ncol = 1), type = "1"), but you could also just do colSums(abs(X))--there's not much point in using norm here.

CodePudding user response:

You should be aware that apply(X, 2, ...) is producing "vector"s like below, which are not the matrix format as norm requested

> set.seed(1)

> X <- matrix(data = rnorm(100), nrow = 10, ncol = 10)

> apply(X, 2, str)
 num [1:10] -0.626 0.184 -0.836 1.595 0.33 ...
 num [1:10] 1.512 0.39 -0.621 -2.215 1.125 ...
 num [1:10] 0.919 0.7821 0.0746 -1.9894 0.6198 ...
 num [1:10] 1.3587 -0.1028 0.3877 -0.0538 -1.3771 ...
 num [1:10] -0.165 -0.253 0.697 0.557 -0.689 ...
 num [1:10] 0.398 -0.612 0.341 -1.129 1.433 ...
 num [1:10] 2.4016 -0.0392 0.6897 0.028 -0.7433 ...
 num [1:10] 0.476 -0.71 0.611 -0.934 -1.254 ...
 num [1:10] -0.569 -0.135 1.178 -1.524 0.594 ...
 num [1:10] -0.543 1.208 1.16 0.7 1.587 ...
NULL

A quick fix might be using as.matrix or t(), e.g.,

> apply(X, 2, function(x) str(as.matrix(x)))
 num [1:10, 1] -0.626 0.184 -0.836 1.595 0.33 ...
 num [1:10, 1] 1.512 0.39 -0.621 -2.215 1.125 ...
 num [1:10, 1] 0.919 0.7821 0.0746 -1.9894 0.6198 ...
 num [1:10, 1] 1.3587 -0.1028 0.3877 -0.0538 -1.3771 ...
 num [1:10, 1] -0.165 -0.253 0.697 0.557 -0.689 ...
 num [1:10, 1] 0.398 -0.612 0.341 -1.129 1.433 ...
 num [1:10, 1] 2.4016 -0.0392 0.6897 0.028 -0.7433 ...
 num [1:10, 1] 0.476 -0.71 0.611 -0.934 -1.254 ...
 num [1:10, 1] -0.569 -0.135 1.178 -1.524 0.594 ...
 num [1:10, 1] -0.543 1.208 1.16 0.7 1.587 ...
NULL

> apply(X, 2, function(x) str(t(x)))
 num [1, 1:10] -0.626 0.184 -0.836 1.595 0.33 ...
 num [1, 1:10] 1.512 0.39 -0.621 -2.215 1.125 ...
 num [1, 1:10] 0.919 0.7821 0.0746 -1.9894 0.6198 ...
 num [1, 1:10] 1.3587 -0.1028 0.3877 -0.0538 -1.3771 ...
 num [1, 1:10] -0.165 -0.253 0.697 0.557 -0.689 ...
 num [1, 1:10] 0.398 -0.612 0.341 -1.129 1.433 ...
 num [1, 1:10] 2.4016 -0.0392 0.6897 0.028 -0.7433 ...
 num [1, 1:10] 0.476 -0.71 0.611 -0.934 -1.254 ...
 num [1, 1:10] -0.569 -0.135 1.178 -1.524 0.594 ...
 num [1, 1:10] -0.543 1.208 1.16 0.7 1.587 ...
NULL

such that

> apply(X, 2, function(x) norm(as.matrix(x), type = "1"))
 [1] 6.497906 8.282578 6.963624 6.011803 5.194332 8.010169 9.687043 5.383619
 [9] 6.336799 9.304195

or (be careful, we use type = "I" here)

> apply(X, 2, function(x) norm(t(x), type = "I"))
 [1] 6.497906 8.282578 6.963624 6.011803 5.194332 8.010169 9.687043 5.383619
 [9] 6.336799 9.304195

Cross-check with colSums(abs(X)) (as mentioned by Gregor Thomas)

> colSums(abs(X))
 [1] 6.497906 8.282578 6.963624 6.011803 5.194332 8.010169 9.687043 5.383619
 [9] 6.336799 9.304195
  • Related