web-dev-qa-db-ja.com

Rのベクトルのユークリッドノルムを計算する方法は?

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

Rのベクトルのノルムを計算する関数は何ですか?

36
Hanfei Sun

これはあなた自身を書く簡単な機能です:

norm_vec <- function(x) sqrt(sum(x^2))
45
joran
norm(c(1,1), type="2")     # 1.414214
norm(c(1, 1, 1), type="2")  # 1.732051
54
Bernd Elkemann

上記の提案された方法の結果のプロファイリングを誰も試みなかったことに驚いたので、それを行いました。ランダムな一様関数を使用してリストを生成し、それを繰り返しに使用しました(エンベロープタイプのベンチマークの単純なバック)。

> 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 

少なくとも実際の値のベクトルでは、パワーを取得してから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))
}

sVD関数は内部的にベクトルを行列に変換し、より複雑なことを行います:

> svd
function (x, nu = min(n, p), nv = min(n, p), LINPACK = FALSE) 
{
    x <- as.matrix(x)
    ...
12
AbdealiJK
_norm(x, type = c("O", "I", "F", "M", "2"))
_

デフォルトは_"O"_です。

_"O"_、_"o"_または_"1"_は、1つのノルム(最大絶対列合計)を指定します。

「F」または「f」は、フロベニウスノルム(ベクトルのように扱われるxのユークリッドノルム)を指定します。

_norm(as.matrix(x1),"o")
_

結果はnorm(as.matrix(x1))と同じ6です

_norm(as.matrix(x1),"f")
_

結果はsqrt(1*1+2*2+3*3)です

したがって、norm(as.matrix(x1),"f")が答えです。

12
stata

また、標準を次のように見つけることもできます。

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

またはとしても試すことができます:

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

両方が同じ答えを与えます

2
Saurabh

私もこれを同等のR式として投げ捨てます

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

Rのクロスプロッドを同様の名前のvector/ cross product と混同しないでください。その命名は、特に物理学/機械学のバックグラウンドを持つ人にとって confusion を引き起こすことが知られています。

2
jxramos

Data.frameまたは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
1
ilyas

AbdealiJKの回答に続いて、

いくつかの洞察を得るために、さらに実験しました。

ここに一つあります。

x = c(-8e+299, -6e+299, 5e+299, -8e+298, -5e+299)
sqrt(sum(x^2))
norm(x, type='2')

最初の結果はInfで、2番目の結果は1.227355e+300これは、以下のコードで示すように非常に正しいです。

library(Rmpfr)
y <- mpfr(x, 120)
sqrt(sum(y*y))    

結果は1227354879...。末尾の数字の数はカウントしませんでしたが、大丈夫です。私はこのOVERFLOW問題を回避する別の方法を知っています。最初にすべての数値に対数関数を適用し、合計します。これを実装する時間はありません。

0
KH Kim

Cbindを使用して列バイスとして行列を作成します。その後、ノルム関数はフロベニウスノルム(ユークリッドノルム)を引数として使用するとうまく機能します。

x1 <-cbind(1:3)

norm(x1、 "f")

[1] 3.741657

sqrt(1 * 1 + 2 * 2 + 3 * 3)

[1] 3.741657

0
subash m