Frage

Angenommen, ich habe eine n von 2-Matrix und einer Funktion, die einen 2-Vektor als eine seiner Argumente annimmt. Ich möchte die Funktion jeder Zeile der Matrix anzuwenden und einen n-Vektor zu erhalten. Wie dies in R tun?

Zum Beispiel würde Ich mag die Dichte einer 2D-Standardnormalverteilung auf drei Punkte berechnen:

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

So wird die Funktion jeder Reihe von out anwenden?

Wie Werte für die anderen Argumente neben den Punkten auf die Funktion in der Art und Weise passieren Sie angeben?

War es hilfreich?

Lösung

Sie einfach die apply()-Funktion:

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> 

Dies nimmt eine Matrix und wendet eine (dumme) Funktion zu jeder Zeile. Sie übergeben zusätzliche Argumente für die Funktion als vierte, fünfte, ... Argumente apply().

Andere Tipps

Falls Sie häufig verwendete Funktionen wie Summe oder Mittelwert anwenden möchten, sollten Sie rowSums oder rowMeans verwenden, da sie sind schneller als apply(data, 1, sum) Ansatz. Ansonsten bleibt bei apply(data, 1, fun). Sie können zusätzliche Argumente nach FUN Argument übergeben (wie Dirk schon vorgeschlagen):

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

Dann können Sie etwas tun:

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

Hier ist ein kurzes Beispiel eine Funktion zu jeder Zeile einer Matrix aufgebracht wird. (Hier die Funktion angewendet normalisiert jede Zeile. 1)

. Hinweis: Das Ergebnis aus der apply() sein mußte transponiert t() mit dem gleichen Layout wie die Eingabematrix A bekommen

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

Ergebnis:

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

Der erste Schritt wäre es, die Funktionsobjekt zu machen, die Anwendung dann. Wenn Sie ein Matrix-Objekt mögen, dass die gleiche Anzahl von Zeilen hat, können Sie es vordefinieren und das Objekt verwenden [] Form, wie dargestellt (ansonsten der zurückgegebene Wert auf einen Vektor vereinfacht wird):

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

Wenn Sie wollte andere verwenden, als Ihre Standardparameter dann sollte der Anruf benannten Argumente nach der Funktion sind:

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

apply () kann auch auf höhere dimensionale Arrays verwendet werden, und das RAND-Argument kann ein Vektor sowie eine einzelne ganze Zahl sein.

Bewerben macht den Job gut, aber ziemlich langsam ist. Mit sapply und vapply könnte nützlich sein. dplyr die zeilenweise könnte auch nützlich sein Mal sehen, ein Beispiel, wie zeilenweise Produkt von jedem Datenrahmen zu tun.

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

Beachten Sie, dass an Variablen zugewiesen wird, bevor Sie vapply / sapply / apply ist eine gute Praxis, wie es an der Zeit eine Menge reduziert. Mal sehen, Ergebnisse-Micro

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

Haben Sie einen sorgfältigen Blick auf, wie t () verwendet wird

Ein weiterer Ansatz, wenn Sie einen Variierung Teil des Datensatzes anstelle eines einzigen Wert verwenden möchten, ist rollapply(data, width, FUN, ...) zu verwenden. Verwendung eines Vektors von Breiten ermöglicht Ihnen, eine Funktion auf einem unterschiedlichen Fenster des Datensatzes anzuwenden. Ich habe verwendet, um dieses eine adaptive Filterung Routine zu bauen, obwohl es nicht sehr effizient ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top