2010-11-21 99 views
85

假設我有一個n乘2的矩陣和一個將2-矢量作爲其參數之一的函數。我想將這個函數應用到矩陣的每一行並得到一個n向量。如何在R中做到這一點?將函數應用於矩陣或數據幀的每一行

例如,我想計算三點二維標準正態分佈的密度:

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

如何將功能適用於out每一行?

如何以指定的方式將除點之外的其他參數的值傳遞給函數?

回答

136

您只需使用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> 

這需要一個矩陣,並應用(傻)函數每一行。您將額外的參數作爲第四,第五,...參數傳遞給apply()

+0

謝謝你細細品味!如果矩陣的行不是函數的第一個參數呢?如何指定矩陣的每一行分配給函數的哪個arg? – Tim 2010-11-21 04:10:39

+0

閱讀'apply()'的幫助 - 它按行進行掃描(當第二個參數是1,否則按列),並且當前行(或列)總是第一個參數。這就是事物的定義。 – 2010-11-21 04:15:46

+0

@Tim:如果您使用內部R函數,並且該行不是第一個參數,請按照Dirk的說法進行操作,並創建您自己的自定義函數,其中第**行是**第一個參數。 – 2010-11-22 12:58:06

6

第一步是製作函數對象,然後應用它。如果希望有相同的行數的矩陣對象,可以預定義,並使用對象[]形式所示(否則返回值將被簡化爲一個向量):

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 

如果你想使用比你的默認參數等,則調用應該包含函數命名的參數:

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

適用()也可以在高維數組使用和MARGIN參數可以是一個矢量,以及一個整數。

14

如果您想要應用常用函數(如sum或mean),則應該使用rowSumsrowMeans,因爲它們比apply(data, 1, sum)方法快。否則,堅持apply(data, 1, fun)。你可以通過FUN爭吵後額外的參數(如德克已經建議):

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 

然後,你可以做這樣的事情:

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 
2

,如果你要使用的數據集的不同部分的另一種方法而不是一個單一的值是使用rollapply(data, width, FUN, ...)。使用寬度向量允許您在數據集的不同窗口上應用函數。我用它來構建一個自適應過濾例程,雖然它不是非常有效。

11

下面是將函數應用於矩陣的每一行的簡短示例。 (在這裏,應用的功能正常化的每一行1)

注:apply()結果必須是使用t()拿到佈局輸入矩陣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))) 

結果:

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

申請做這項工作很好,但速度很慢。 使用sapply和vapply可能會有用。 dplyr的rowwise也可能是有用的 讓我們來看看如何做任何數據框的行明智的產品的例子。

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

注意,使用vapply/sapply /應用之前分配給變量是很好的做法,因爲它減少了很多時間。讓我們來看看微基準測試結果

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

有如何噸()正在使用

相關問題