2012-06-07 138 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)」不起作用?哈哈。我也檢查了我的功能的速度.. –

相關問題