Appliquer une fonction à chaque ligne d’une masortingce ou d’un bloc de données

Supposons que j’ai une masortingce de 2 et une fonction qui prend un vecteur 2 comme un de ses arguments. Je voudrais appliquer la fonction à chaque ligne de la masortingce et obtenir un vecteur n. Comment faire cela en R?

Par exemple, je voudrais calculer la densité d’une dissortingbution normale 2D standard sur trois points:

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)) 

Comment appliquer la fonction à chaque ligne de out ?

Comment passer des valeurs pour les autres arguments en plus des points de la fonction de la manière que vous spécifiez?

    Vous utilisez simplement la fonction 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> 

    Cela prend une masortingce et applique une fonction (idiote) à chaque ligne. Vous passez des arguments supplémentaires à la fonction en tant que quasortingème, cinquième, … arguments à apply() .

    Si vous souhaitez appliquer des fonctions communes telles que sum ou mean, vous devez utiliser rowSums ou rowMeans car ils sont plus rapides que l’approche apply(data, 1, sum) . Sinon, restz avec apply(data, 1, fun) . Vous pouvez passer des arguments supplémentaires après l’argument FUN (comme Dirk l’a déjà suggéré):

     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 

    Ensuite, vous pouvez faire quelque chose comme ceci:

     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 

    Voici un court exemple d’application d’une fonction à chaque ligne d’une masortingce. (Ici, la fonction appliquée normalise chaque ligne à 1.)

    Note: Le résultat de la méthode apply() a dû être transposé en utilisant t() pour obtenir la même disposition que la masortingce de saisie A

     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) )) 

    Résultat:

      [,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 

    La première étape consisterait à créer l’object fonction, puis à l’appliquer. Si vous voulez un object masortingce ayant le même nombre de lignes, vous pouvez le prédéfinir et utiliser le formulaire object [] comme illustré (sinon la valeur renvoyée sera simplifiée en un vecteur):

     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 vous souhaitez utiliser des parameters autres que vos parameters par défaut, l'appel doit inclure des arguments nommés après la fonction:

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

    apply () peut également être utilisé sur les tableaux de dimensions supérieures et l'argument MARGIN peut être un vecteur et un entier unique.

    Apply fait bien son travail, mais est assez lent. Utiliser sapply et vapply pourrait être utile. dplyr’s rowwise pourrait également être utile Voyons un exemple de la manière de réaliser un produit en ligne de n’importe quel bloc de données.

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

    Notez que l’atsortingbution d’une variable avant d’utiliser vapply / sapply / apply est une bonne pratique car elle réduit considérablement le temps. Voyons les résultats de 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)) ) 

    Regardez attentivement comment t () est utilisé

    Une autre approche si vous souhaitez utiliser une partie variable du jeu de données au lieu d’une seule valeur consiste à utiliser rollapply(data, width, FUN, ...) . L’utilisation d’un vecteur de largeurs vous permet d’appliquer une fonction sur une fenêtre variable du jeu de données. Je l’ai utilisé pour créer une routine de filtrage adaptatif, même si elle n’est pas très efficace.