如何计算R中向量的欧几里德范数?

Han*_*Sun 37 statistics r vector

我试过了norm,但我认为它给出了错误的结果.(规范c(1, 2, 3)sqrt(1*1+2*2+3*3),但它返回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
Run Code Online (Sandbox Code Playgroud)

有谁知道在R中计算向量范数的函数是什么?

Ber*_*ann 61

norm(c(1,1), type="2")     # 1.414214
norm(c(1, 1, 1), type="2")  # 1.732051
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案,也允许R使用它的内部优化. (3认同)

jor*_*ran 49

这是写自己的一个微不足道的功能:

norm_vec <- function(x) sqrt(sum(x^2))
Run Code Online (Sandbox Code Playgroud)

  • 嘿,你从上面的评论中侵犯了我的版权!我将派遣一队RIAA律师.:-) (12认同)
  • @Dalupus在做出如此强烈的陈述之前,你应该费心去对这两个解决方案进行基准测试.您可能会发现结果令人惊讶.当我这样做时,我发现我的版本快了大约5倍.(这并不是说可能没有理由使用`规范`.但你应该在强烈说话之前检查.) (8认同)
  • 非常不同意这个答案.在R中,如果有可用的话,你几乎总是想要使用内置函数.它们经过高度优化.Bernd的答案是正确的答案.如果您遇到此问题,请向下滚动并使用正确的R功能执行此操作. (7认同)
  • @CarlWitthoft我刚刚去了并支付了一些版税,所以希望我们都是正方形的.:) (4认同)
  • 这实际上不是速度问题。尝试`norm_vec(c(10 ^ 200))`和`norm(c(10 ^ 200),type =“ 2”)`来看看区别。 (2认同)

Abd*_*iJK 16

我很惊讶没有人尝试过对上述方法的结果进行分析,所以我做到了.我使用了一个随机的统一函数来生成一个列表并将其用于重复(只是一个简单的封装类型的基准):

> 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 
Run Code Online (Sandbox Code Playgroud)

似乎手动获取功率然后sqrt比norm实际值向量的内置更快.这可能是因为规范内部做了一个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))
}
Run Code Online (Sandbox Code Playgroud)

并且SVD函数在内部将向量转换为矩阵,并执行更复杂的操作:

> svd
function (x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE) 
{
    x <- as.matrix(x)
    ...
Run Code Online (Sandbox Code Playgroud)


sta*_*ata 13

norm(x, type = c("O", "I", "F", "M", "2"))
Run Code Online (Sandbox Code Playgroud)

默认是"O".

"O","o""1"指定一个标准,(最大绝对列总和);

"F"或"f"指定Frobenius范数(x的欧几里德范数被视为矢量);

norm(as.matrix(x1),"o")
Run Code Online (Sandbox Code Playgroud)

结果是6,相同 norm(as.matrix(x1))

norm(as.matrix(x1),"f")
Run Code Online (Sandbox Code Playgroud)

结果是 sqrt(1*1+2*2+3*3)

所以,norm(as.matrix(x1),"f")是答案.