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のベクトルのノルムを計算する関数は何ですか?
これはあなた自身を書く簡単な機能です:
norm_vec <- function(x) sqrt(sum(x^2))
norm(c(1,1), type="2") # 1.414214
norm(c(1, 1, 1), type="2") # 1.732051
上記の提案された方法の結果のプロファイリングを誰も試みなかったことに驚いたので、それを行いました。ランダムな一様関数を使用してリストを生成し、それを繰り返しに使用しました(エンベロープタイプのベンチマークの単純なバック)。
> 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)
...
_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")
が答えです。
また、標準を次のように見つけることもできます。
Result<-sum(abs(x)^2)^(1/2)
またはとしても試すことができます:
Result<-sqrt(t(x)%*%x)
両方が同じ答えを与えます
私もこれを同等のR式として投げ捨てます
norm_vec(x) <- function(x){sqrt(crossprod(x))}
Rのクロスプロッドを同様の名前のvector/ cross product と混同しないでください。その命名は、特に物理学/機械学のバックグラウンドを持つ人にとって confusion を引き起こすことが知られています。
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
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
問題を回避する別の方法を知っています。最初にすべての数値に対数関数を適用し、合計します。これを実装する時間はありません。
Cbindを使用して列バイスとして行列を作成します。その後、ノルム関数はフロベニウスノルム(ユークリッドノルム)を引数として使用するとうまく機能します。
x1 <-cbind(1:3)
norm(x1、 "f")
[1] 3.741657
sqrt(1 * 1 + 2 * 2 + 3 * 3)
[1] 3.741657