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