可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I tried norm
, but I think it gives the wrong result. (the norm of c(1, 2, 3)
is sqrt(1*1+2*2+3*3)
, but it returns 6
..
x1 <- 1:3 norm(x1) # Error in norm(x1) : 'A' must be a numeric matrix norm(as.matrix(x1)) # [1] 6 as.matrix(x1) # [,1] # [1,] 1 # [2,] 2 # [3,] 3 norm(as.matrix(x1)) # [1] 6
Does anyone know what's the function to calculate the norm of a vector in R?
回答1:
This is a trivial function to write yourself:
norm_vec <- function(x) sqrt(sum(x^2))
回答2:
norm(c(1,1), type="2") # 1.414214 norm(c(1, 1, 1), type="2") # 1.732051
回答3:
norm(x, type = c("O", "I", "F", "M", "2"))
The default is "O"
.
"O"
, "o"
or "1"
specifies the one norm, (maximum absolute column sum);
"F" or "f" specifies the Frobenius norm (the Euclidean norm of x treated as if it were a vector);
norm(as.matrix(x1),"o")
The result is 6, same as norm(as.matrix(x1))
norm(as.matrix(x1),"f")
The result is sqrt(1*1+2*2+3*3)
So, norm(as.matrix(x1),"f")
is answer.
回答4:
I was surprised that nobody had tried profiling the results for the above suggested methods, so I did that. I've used a random uniform function to generate a list and used that for repetition (Just a simple back of the envelop type of benchmark):
> uut <- lapply(1:100000, function(x) {runif(1000, min=-10^10, max=10^10)}) > norm_vec <- function(x) sqrt(sum(x^2)) > norm_vec2 <- function(x){sqrt(crossprod(x))} > > system.time(lapply(uut, norm_vec)) user system elapsed 0.58 0.00 0.58 > system.time(lapply(uut, norm_vec2)) user system elapsed 0.35 0.00 0.34 > system.time(lapply(uut, norm, type="2")) user system elapsed 6.75 0.00 6.78 > system.time(lapply(lapply(uut, as.matrix), norm)) user system elapsed 2.70 0.00 2.73
It seems that taking the power and then sqrt manually is faster than the builtin norm
for real values vectors at least. This is probably because norm internally does an SVD:
> norm function (x, type = c("O", "I", "F", "M", "2")) { if (identical("2", type)) { svd(x, nu = 0L, nv = 0L)$d[1L] } else .Internal(La_dlange(x, type)) }
and the SVD function internally converts the vector into a matrix, and does more complicated stuff:
> svd function (x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE) { x <- as.matrix(x) ...
回答5:
We can also find the norm as :
Result<-sum(abs(x)^2)^(1/2)
OR Even You can also try as:
Result<-sqrt(t(x)%*%x)
Both will give the same answer
回答6:
I'mma throw this out there too as an equivalent R expression
norm_vec(x) <- function(x){sqrt(crossprod(x))}
Don't confuse R's crossprod with a similarly named vector/cross product. That naming is known to cause confusion especially for those with a physics/mechanics background.
回答7:
If you have a data.frame or a data.table 'DT', and want to compute the Euclidian norm (norm 2) across each row, the apply
function can be used.
apply(X = DT, MARGIN = 1, FUN = norm, '2')
Example:
>DT accx accy accz 1: 9.576807 -0.1629486 -0.2587167 2: 9.576807 -0.1722938 -0.2681506 3: 9.576807 -0.1634264 -0.2681506 4: 9.576807 -0.1545590 -0.2681506 5: 9.576807 -0.1621254 -0.2681506 6: 9.576807 -0.1723825 -0.2682434 7: 9.576807 -0.1723825 -0.2728810 8: 9.576807 -0.1723825 -0.2775187 > apply(X = DT, MARGIN = 1, FUN = norm, '2') [1] 9.581687 9.582109 9.581954 9.581807 9.581932 9.582114 9.582245 9.582378
回答8:
Create your matrix as column vise using cbind then the norm function works well with Frobenius norm (the Euclidean norm) as an argument.
x1<-cbind(1:3)
norm(x1,"f")
[1] 3.741657
sqrt(1*1+2*2+3*3)
[1] 3.741657