2012-06-07 39 views
32

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 vuelve 6 ..cómo calcular la norma euclidiana de un vector en 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 

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

+1

"norma" no es exactamente lo que usted piensa es. Pruebe 'sqrt (sum (x^2))'. R hace "lo que esperas". 'norma' y' dist' están diseñados para proporcionar cálculos de distancia generalizados entre las filas de una matriz. –

+0

Esto devuelve un vector con las raíces cuadradas de cada uno de los componentes al cuadrado, por lo tanto * 1 2 3 * en lugar de la Norma Euclidiana – runlevel0

Respuesta

36

Esta es una función trivial para escribir usted mismo?:

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

Oye, ¡violó mis derechos de autor del comentario anterior! Enviaré un equipo de abogados de RIAA después de ti. :-) –

+4

@CarlWitthoft Acabo de ir y pagué algunas regalías, así que espero que todos estemos bien. :) – joran

+5

Muy en desacuerdo con esta respuesta. En R, casi siempre quiere usar una función integrada si hay una disponible. Ellos están altamente optimizados. La respuesta de Bernd es la respuesta correcta. Si se encuentra con esto, desplácese hacia abajo y use la función R adecuada para realizar esto. – Dalupus

2

también podemos encontrar en la norma como:

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

o incluso También puede tratar como:

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

Tanto dará la misma respuesta

+4

Dos simplificaciones: si los componentes de 'x' son números reales, puede reemplazar abs (x)^2 con x^2. Del mismo modo, '% *%' transpone vectores según sea necesario, por lo que puede simplificar 't (x)% *% x' a' x% *% x'. – jochen

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

El valor predeterminado es "O".

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

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

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

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

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

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

Por lo tanto, es norm(as.matrix(x1),"f") respuesta.

0

Crea tu matriz como tornillo de banco con cbind luego la función de norma funciona bien con la norma de Frobenius (la norma euclidiana) como argumento.

x1 < -cbind (1: 3)

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

Esta es la respuesta correcta que también permite a R usar sus optimizaciones internas. – Dalupus

+0

Esto toma más tiempo que la respuesta de jorah para mí. Vea la respuesta de AbdealiJK para verificar los tiempos. – Vincent

2

I'mma tirar esto hacia fuera allí también como una expresión equivalente R

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

No se debe confundir crossprod de R con un vector de nombre similar/cross product. Esa denominación es conocida por causar confusion especialmente para aquellos con un fondo de física/mecánica.

+0

Absolutamente correcto, el código que escribí haría lo que dijera, pero en realidad solo estaba tratando de resaltar el cálculo de la norma vectorial. Seguiré la convención de nombres de Joran aquí. Buena sugerencia. – jxramos

1

Si tiene datos.frame o data.table 'DT', y desea calcular la norma Euclidian (norma 2) en cada fila, se puede utilizar la función apply.

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

Ejemplo:

>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

Me sorprendió que nadie había intentado perfilar los resultados de los métodos sugeridos por encima, por lo que lo hice. He utilizado una función aleatoria uniforme para generar una lista y se utiliza para que la repetición (Sólo un simple regreso del tipo dotación de referencia):

> 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 teniendo el poder y luego manualmente sqrt es más rápido que el built-in norm para vectores de valores reales al menos. Esto es probablemente debido a que la norma hace internamente 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)) 
} 

y la función SVD convierte internamente el vector en una matriz, y lo hace más complicado cosas:

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

Me encanta cómo salió esta pregunta de "¿Cómo hago para que R haga esto?" a la optimización También hice mi propia función de distancia en R y luego me di cuenta de la función incorporada y de por qué no funcionaba el hecho de intentar "norma (v)" jaja. También verifiqué la velocidad de mi función ... –

Cuestiones relacionadas