2012-06-07 30 views
32

Ich versuchte norm, aber ich denke, es gibt das falsche Ergebnis. (Die Norm der c(1, 2, 3) ist sqrt(1*1+2*2+3*3), aber es gibt 6 ..Wie berechnet man die euklidische Norm eines Vektors in 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 

Wer weiß, was die Funktion ist die Norm eines Vektors in R zu berechnen

+1

„Norm“ ist nicht ganz das, was Sie denken, es ist. Versuchen Sie 'sqrt (sum (x^2))'. R macht "was du erwartest". "Norm" und "Dist" sind so konzipiert, dass sie generalisierte Entfernungsberechnungen zwischen Zeilen einer Matrix bereitstellen. –

+0

Dies gibt einen Vektor mit den Quadratwurzeln jeder Komponente zum Quadrat zurück, also * 1 2 3 * anstelle der euklidischen Norm – runlevel0

Antwort

36

Dies ist eine triviale Funktion selbst zu schreiben?:

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

Hey, du hast mein Urheberrecht vom obigen Kommentar verletzt! Ich schicke dir ein Team von RIAA-Anwälten. :-) –

+4

@CarlWitthoft Ich bin gerade gegangen und habe ein paar Tantiemen bezahlt, also sind wir hoffentlich alle gleich. :) – joran

+5

Stimme dieser Antwort nicht zu. In R möchten Sie fast immer eine eingebaute Funktion verwenden, wenn eine verfügbar ist. Sie sind hoch optimiert. Die Antwort von Bernd ist die richtige Antwort. Wenn Sie darauf stoßen, scrollen Sie bitte nach unten und verwenden Sie die richtige R-Funktion, um dies durchzuführen. – Dalupus

2

Wir haben auch die Norm wie finden:

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

oder sogar können Sie auch versuchen, wie:

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

Beide werden die gleiche Antwort

+4

Zwei Vereinfachungen: Wenn die Komponenten von 'x' reelle Zahlen sind, können Sie abs (x)^2 durch x^2 ersetzen. Auf ähnliche Weise transponiert '% *%' Vektoren nach Bedarf, so dass Sie 't (x)% *% x' zu' x% *% x' vereinfachen können. – jochen

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

Der Standard geben ist "O".

"O", "o" oder "1" spezifiziert die eine Norm, (maximale absolute Spaltensumme);

"F" oder "f" gibt die Frobenius-Norm an (die euklidische Norm von x wird behandelt, als wäre sie ein Vektor);

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

Das Ergebnis ist 6, gleich wie norm(as.matrix(x1))

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

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

So ist, ist norm(as.matrix(x1),"f") Antwort.

0

Erstellen Sie Ihre Matrix als Column Vise mit Cbind dann funktioniert die Norm-Funktion gut mit Frobenius Norm (die Euklidische Norm) als Argument.

x1 < -cbind (1: 3)

Norm (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

Dies ist die richtige Antwort, die es R auch erlaubt, seine internen Optimierungen zu verwenden. – Dalupus

+0

Das braucht mehr Zeit als Jorahs Antwort für mich. Siehe AbdealiJKs Antwort, um die Zeit zu überprüfen. – Vincent

2

I'mma diese dort auch als Äquivalent R Ausdruck werfen

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

Sie R crossprod mit einem ähnlich benannten Vektor/cross product nicht verwirren. Es ist bekannt, dass diese Namensgebung confusion vor allem für diejenigen mit einem Physik/Mechanik-Hintergrund verursacht.

+0

Absolut richtig, der Code, den ich geschrieben habe, würde tun, was du sagst, aber ich habe wirklich nur versucht, die Vektornormberechnung hervorzuheben. Ich werde Jorans Namenskonvention hier folgen. Guter Vorschlag. – jxramos

1

Wenn Sie Daten haben.Rahmen oder eine Data.table "DT", und möchten die euklidische Norm (Norm 2) über jede Zeile berechnen, kann die apply Funktion verwendet werden.

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

Beispiel:

>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

Ich war überrascht, dass niemand versucht hatte, für die oben vorgeschlagenen Methoden die Ergebnisse Profilierung, so habe ich getan. Ich habe eine zufällige einheitliche Funktion verwendet, um eine Liste zu erzeugen und verwendet, dass für die Wiederholung (nur eine einfache Rückseite des Hüllkurventyp in der Benchmark):

> 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 

Es scheint, dass die Macht zu übernehmen und dann manuell sqrt ist schneller als die eingebaute norm für reale Werte Vektoren mindestens. Dies ist wahrscheinlich, weil Norm intern funktioniert ein 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)) 
} 

und die SVD-Funktion intern wandelt den Vektor in eine Matrix, und tut kompliziertere Sachen:

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

Ich liebe, wie diese Frage von "Wie bekomme ich R, um dies zu tun?" zur Optimierung. Ich habe auch meine eigene Distanzfunktion in R gemacht und bin dann neugierig geworden, was die eingebaute Funktion ist und warum es einfach nicht funktioniert, haha, "norm (v)" zu versuchen. Ich habe auch die Geschwindigkeit meiner Funktion überprüft. –

Verwandte Themen