45 votos

¿Cómo calcular la norma euclidiana de un vector en R?

Intenté norm, pero creo que da el resultado incorrecto. (la norma de c(1, 2, 3) es sqrt(1*1+2*2+3*3), pero devuelve 6..

x1 <- 1:3
norm(x1)
# Error en norm(x1) : 'A' debe ser una matriz numérica
norm(as.matrix(x1))
# [1] 6
as.matrix(x1)
#      [,1]
# [1,]    1
# [2,]    2
# [3,]    3
norm(as.matrix(x1))
# [1] 6

¿Alguien sabe cuál es la función para calcular la norma de un vector en R?

74voto

eznme Puntos 13158
norm(c(1,1), type="2")     # 1.414214
norm(c(1, 1, 1), type="2")  # 1.732051

Se traduce a:

norm(c(1,1), tipo="2")     # 1.414214
norm(c(1, 1, 1), tipo="2")  # 1.732051

57voto

joran Puntos 68079

Esta es una función trivial para escribir por ti mismo:

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

25voto

AbdealiJK Puntos 2897

Me sorprendió que nadie hubiera intentado perfilar los resultados de los métodos sugeridos anteriormente, así que lo hice. Usé una función de distribución uniforme aleatoria para generar una lista y la utilicé para la repetición (solo un simple tipo de referencia rápido):

> 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 

Parece que elevar al cuadrado y luego tomar la raíz cuadrada manualmente es más rápido que el builtin norm para vectores de valores reales al menos. Esto se debe probablemente a que internamente norm hace una 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))
}

y la función SVD internamente convierte el vector en una matriz, y realiza operaciones más complicadas:

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

EDICIÓN (20 Oct 2019):

Ha habido algunos comentarios que señalan el problema de corrección que el caso de prueba anterior no revela:

> norm_vec(c(10^155))
[1] Inf
> norm(c(10^155), type="2")
[1] 1e+155

Esto sucede porque los números grandes se consideran como infinito en R:

> 10^309
[1] Inf

Así que parece que:

Parece que elevar al cuadrado y luego tomar la raíz cuadrada manualmente es más rápido que el builtin norm para vectores de valores reales para números pequeños.

¿Qué tan pequeños? Lo suficiente para que la suma de los cuadrados no se desborde.

15voto

stata Puntos 515
norm(x, type = c("O", "I", "F", "M", "2"))

El valor por defecto es "O".

"O", "o" o "1" especifica la norma uno, (suma absoluta máxima de columnas);

"F" o "f" especifica la norma de Frobenius (la norma euclidiana de x tratada como si fuera un vector);

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

El resultado es 6, igual que norm(as.matrix(x1))

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

El resultado es sqrt(1*1+2*2+3*3)

Entonces, norm(as.matrix(x1),"f") es la respuesta.

4voto

Saurabh Puntos 817

También podemos encontrar la norma como :

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

O incluso también puedes intentar:

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

Ambos darán la misma respuesta

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X