2012-06-07 99 views
32

我试过norm,但我认为它给出了错误的结果。 (中c(1, 2, 3)规范为sqrt(1*1+2*2+3*3),但它返回6 ..如何计算R中向量的欧几里得范数?

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 

有谁知道有什么功能来计算R A向量的范数

+1

“规范”是不是挺你在想什么它是。尝试'sqrt(sum(x^2))'。 R确实“你期望的是什么”。 'norm'和'dist'被设计用来在矩阵的行之间提供广义的距离计算。 –

+0

这将返回一个向量,其中每个分量的平方根都是平方根,因此* 1 2 3 *代替欧几里德准则 – runlevel0

回答

36

这是自己写一个简单的功能?

norm_vec <- function(x) sqrt(sum(x^2)) 
+4

@CarlWitthoft我刚去支付一些版税,所以希望我们都是正方形的。 :) – joran

+5

非常不同意这个答案。在R中,如果可用,几乎总是希望使用内置函数。他们高度优化。贝恩德的答案是正确的答案。如果遇到此问题,请向下滚动并使用适当的R功能执行此操作。 – Dalupus

2

我们还可以找到标准为:

Result<-sum(abs(x)^2)^(1/2) 

,甚至你还可以尝试如下:

Result<-sqrt(t(x)%*%x) 

两者都会给出相同的答案

+4

两个简化:如果'x'的组件是实数,则可以用x^2代替abs(x)^ 2。同样,'%*%'根据需要转换向量,因此可以将't(x)%*%x'简化为'x%*%x'。 – jochen

11
norm(x, type = c("O", "I", "F", "M", "2")) 

默认为"O"

"O""o""1"指定一个范数(最大绝对列总和); “F”或“f”指定Frobenius范数(x的Euclidean范数视为它的向量);

norm(as.matrix(x1),"o") 

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

norm(as.matrix(x1),"f") 

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

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

0

使用cbind创建矩阵作为列老虎钳,那么范数函数与Frobenius范数(欧几里得范数)作为参数运作良好。

X1 < -cbind(1:3)

范数(X1, “F”)

[1] 3.741657

SQRT(1 * 1 + 2 * 2 + 3 * 3)

[1] 3.741657

35
norm(c(1,1), type="2")  # 1.414214 
norm(c(1, 1, 1), type="2") # 1.732051 
+1

这是正确的答案,它也允许R使用它的内部优化。 – Dalupus

+0

这比Jorah的回答对我来说需要更多的时间。请参阅AbdealiJK的检查时间的答案。 – Vincent

2

我就要扔了这一点,有太多作为等效R的表达

norm_vec(x) <- function(x){sqrt(crossprod(x))} 

不要用类似的命名矢量/ cross product混淆的r crossprod。已知这种命名会导致confusion尤其适用于那些具有物理/力学背景的人。

+0

绝对正确,我写的代码会做你所说的,但我真的只是试图强调向量范数计算。我会在这里跟随Joran的命名约定。好建议。 – jxramos

1

如果您有数据。帧或data.table'DT',并且想要计算每行的欧几里得范数(范数2),则可以使用apply函数。

apply(X = DT, MARGIN = 1, FUN = norm, '2') 

例子:

>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

我很惊讶,没有人曾试图剖析了上述建议的方法的结果,所以我这样做。我用一个统一的随机函数生成一个列表,并使用提供重复(就在信封类型基准的简单回):

> 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 

似乎手动服用电源,然后再开方比快至少对于真实值向量的内建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)) 
} 

和SVD功能的载体在内部转换为基体,并执行更复杂的东西:

> svd 
function (x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE) 
{ 
    x <- as.matrix(x) 
    ... 
+0

我很喜欢这个问题,从“我如何获得R做这个?”进行优化。我也只是在R中创建了自己的距离函数,然后就很好奇内置函数是什么,为什么只是尝试“norm(v)”不起作用?哈哈。我也检查了我的功能的速度.. –

相关问题