Pregunta

Supongamos que tengo a n por 2 de la matriz y una función que toma un 2-vector como uno de sus argumentos. Me gustaría aplicar la función a cada fila de la matriz y obtener un vector n. La forma de hacerlo en R?

Por ejemplo, me gustaría para calcular la densidad de una distribución de 2D estándar normal en tres puntos:

bivariate.density(x = c(0, 0), mu = c(0, 0), sigma = c(1, 1), rho = 0){
    exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+x[2]^2/sigma[2]^2-2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
}

out <- rbind(c(1, 2), c(3, 4), c(5, 6))

Cómo aplicar la función a cada fila de out?

Cómo pasar valores para los otros argumentos además de los puntos a la función de la forma que se especifica?

¿Fue útil?

Solución

Sólo tiene que utilizar la función apply():

R> M <- matrix(1:6, nrow=3, byrow=TRUE)
R> M
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
R> apply(M, 1, function(x) 2*x[1]+x[2])
[1]  4 10 16
R> 

Esto toma una matriz y se aplica una función (tonto) para cada fila. Se pasa argumentos adicionales a la función como cuarta, quinta, ... argumentos a apply().

Otros consejos

En caso de que quiera aplicar funciones comunes, tales como suma o media, se debe utilizar rowSums o rowMeans ya que son más rápido que el enfoque apply(data, 1, sum). De lo contrario, seguir con apply(data, 1, fun). Puede pasar argumentos adicionales después argumento divertido (como ya se ha sugerido Dirk):

set.seed(1)
m <- matrix(round(runif(20, 1, 5)), ncol=4)
diag(m) <- NA
m
     [,1] [,2] [,3] [,4]
[1,]   NA    5    2    3
[2,]    2   NA    2    4
[3,]    3    4   NA    5
[4,]    5    4    3   NA
[5,]    2    1    4    4

A continuación, puede hacer algo como esto:

apply(m, 1, quantile, probs=c(.25,.5, .75), na.rm=TRUE)
    [,1] [,2] [,3] [,4] [,5]
25%  2.5    2  3.5  3.5 1.75
50%  3.0    2  4.0  4.0 3.00
75%  4.0    3  4.5  4.5 4.00

Aquí está un breve ejemplo de la aplicación de una función a cada fila de una matriz. (Aquí, la función aplica normaliza cada fila a 1).

Nota:. El resultado del apply() tuvo que ser transpuesto utilizando t() para obtener el mismo diseño que el A matriz de entrada

A <- matrix(c(
  0, 1, 1, 2,
  0, 0, 1, 3,
  0, 0, 1, 3
), nrow = 3, byrow = TRUE)

t(apply(A, 1, function(x) x / sum(x) ))

Resultados:

     [,1] [,2] [,3] [,4]
[1,]    0 0.25 0.25 0.50
[2,]    0 0.00 0.25 0.75
[3,]    0 0.00 0.25 0.75

El primer paso sería hacer que el objeto función, luego aplicarlo. Si desea un objeto de matriz que tiene el mismo número de filas, puede predefinir y utilizar el objeto [] forma como se ilustra (de lo contrario el valor devuelto se simplificará a un vector):

bvnormdens <- function(x=c(0,0),mu=c(0,0), sigma=c(1,1), rho=0){
     exp(-1/(2*(1-rho^2))*(x[1]^2/sigma[1]^2+
                           x[2]^2/sigma[2]^2-
                           2*rho*x[1]*x[2]/(sigma[1]*sigma[2]))) * 
     1/(2*pi*sigma[1]*sigma[2]*sqrt(1-rho^2))
     }
 out=rbind(c(1,2),c(3,4),c(5,6));

 bvout<-matrix(NA, ncol=1, nrow=3)
 bvout[] <-apply(out, 1, bvnormdens)
 bvout
             [,1]
[1,] 1.306423e-02
[2,] 5.931153e-07
[3,] 9.033134e-15

Si desea utilizar aparte de sus parámetros por defecto entonces la llamada debe incluir argumentos con nombre después de la función:

bvout[] <-apply(out, 1, FUN=bvnormdens, mu=c(-1,1), rho=0.6)

aplicar () también se puede utilizar en matrices de dimensiones superiores y el argumento margen puede ser un vector, así como un solo número entero.

Aplicar hace el trabajo bien, pero es bastante lento. Usando sapply y vapply podría ser útil. por filas de dplyr también podría ser útil Veamos un ejemplo de cómo hacer fila producto racional de cualquier trama de datos.

a = data.frame(t(iris[1:10,1:3]))
vapply(a, prod, 0)
sapply(a, prod)

Tenga en cuenta que la asignación a la variable antes de usar vapply / sapply / aplicar una buena práctica, ya que reduce el tiempo mucho. Vamos a ver resultados microbenchmark

a = data.frame(t(iris[1:10,1:3]))
b = iris[1:10,1:3]
microbenchmark::microbenchmark(
    apply(b, 1 , prod),
    vapply(a, prod, 0),
    sapply(a, prod) , 
    apply(iris[1:10,1:3], 1 , prod),
    vapply(data.frame(t(iris[1:10,1:3])), prod, 0),
    sapply(data.frame(t(iris[1:10,1:3])), prod) ,
    b %>%  rowwise() %>%
        summarise(p = prod(Sepal.Length,Sepal.Width,Petal.Length))
)

Tener una mirada cuidadosa a cómo t () se está utilizando

Otro enfoque si desea utilizar una porción variable del conjunto de datos en lugar de un único valor es el uso de rollapply(data, width, FUN, ...). El uso de un vector de anchos le permite aplicar una función en una ventana variable del conjunto de datos. He utilizado este para construir una rutina de filtrado adaptativo, aunque no es muy eficiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top