J'ai essayé norm
, mais je pense que cela donne le mauvais résultat. (la norme de c(1, 2, 3)
est sqrt(1*1+2*2+3*3)
, mais elle renvoie 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
Quelqu'un sait-il quelle est la fonction pour calculer la norme d'un vecteur dans R?
C'est une fonction triviale pour vous écrire:
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
J'ai été surpris que personne n'ait essayé de profiler les résultats pour les méthodes suggérées ci-dessus, alors je l'ai fait. J'ai utilisé une fonction uniforme aléatoire pour générer une liste et l'ai utilisée pour la répétition (juste un simple dos du type d'enveloppe de référence):
> 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
Il semble que prendre la puissance puis sqrt manuellement soit plus rapide que le norm
intégré pour les vecteurs de valeurs réelles au moins. C'est probablement parce que la norme fait en interne un 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))
}
et la fonction SVD convertit en interne le vecteur en matrice, et fait des choses plus compliquées:
> 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"))
La valeur par défaut est "O"
.
"O"
, "o"
Ou "1"
Spécifie la seule norme, (somme maximale absolue des colonnes);
"F" ou "f" spécifie la norme Frobenius (la norme euclidienne de x traitée comme s'il s'agissait d'un vecteur);
norm(as.matrix(x1),"o")
Le résultat est 6, identique à norm(as.matrix(x1))
norm(as.matrix(x1),"f")
Le résultat est sqrt(1*1+2*2+3*3)
Donc, norm(as.matrix(x1),"f")
est la réponse.
Nous pouvons également trouver la norme comme:
Result<-sum(abs(x)^2)^(1/2)
OU même vous pouvez également essayer comme:
Result<-sqrt(t(x)%*%x)
Les deux donneront la même réponse
Je vais aussi lancer ça comme une expression R équivalente
norm_vec(x) <- function(x){sqrt(crossprod(x))}
Ne confondez pas le crossprod de R avec un vecteur de même nom/ produit croisé . Cette dénomination est connue pour causer confusion surtout pour ceux qui ont une formation en physique/mécanique.
Si vous avez un data.frame ou un data.table 'DT' et que vous souhaitez calculer la norme euclidienne (norme 2) sur chaque ligne, la fonction apply
peut être utilisée.
apply(X = DT, MARGIN = 1, FUN = norm, '2')
Exemple:
>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
Suite à la réponse d'AbdealiJK,
J'ai expérimenté davantage pour avoir un aperçu.
En voici un.
x = c(-8e+299, -6e+299, 5e+299, -8e+298, -5e+299)
sqrt(sum(x^2))
norm(x, type='2')
Le premier résultat est Inf
et le second est 1.227355e+300
ce qui est tout à fait correct comme je vous le montre dans le code ci-dessous.
library(Rmpfr)
y <- mpfr(x, 120)
sqrt(sum(y*y))
Le résultat est 1227354879...
. Je n'ai pas compté le nombre de numéros de fin, mais tout semble correct. Je connais un autre moyen de contourner ce problème OVERFLOW
qui consiste d'abord à appliquer la fonction de journalisation à tous les nombres et à les résumer, que je n'ai pas le temps de mettre en œuvre!
Créez votre matrice comme étau de colonne en utilisant cbind puis la fonction norm fonctionne bien avec la norme Frobenius (la norme euclidienne) comme argument.
x1 <-cbind (1: 3)
norme (x1, "f")
[1] 3,741657
sqrt (1 * 1 + 2 * 2 + 3 * 3)
[1] 3,741657