2014-06-22 5 views
1

두 개의 인수가있는 함수가 있습니다. 첫 번째 인수는 벡터를 사용하고 두 번째 인수는 스칼라를 사용합니다. 이 함수를 행렬의 각 행에 적용하려고하지만이 함수는 매번 다른 두 번째 인수를 사용합니다. 나는 다음을 시도했다, 그것은 작동하지 않았다. 각 행에 대해 p.value를 계산 한 다음 p.value를 행 번호로 나눌 것을 예상했습니다. 그 결과가 벡터가 될 것으로 예상했지만 대신 행렬을 얻었습니다. 이것은 의사적인 예이지만 내 목적을 설명합니다.R- 행렬의 각 행에 함수를 변경 인수를 사용하여 적용 하시겠습니까?

> foo = matrix(rnorm(100),ncol=20) 
> f = function (x,y) t.test(x[1:10],x[11:20])$p.value/y 
> goo = 1:5 
> apply(foo,1,f,y=goo) 
      [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 0.9406881 0.6134117 0.5484542 0.11299535 0.20420786 
[2,] 0.4703440 0.3067059 0.2742271 0.05649767 0.10210393 
[3,] 0.3135627 0.2044706 0.1828181 0.03766512 0.06806929 
[4,] 0.2351720 0.1533529 0.1371135 0.02824884 0.05105196 
[5,] 0.1881376 0.1226823 0.1096908 0.02259907 0.04084157 

다음 for 루프 전략은 예상 결과를 산출합니다. 실제 데이터에 대한 기대치는 매우 느립니다.

> res = numeric(5) 
> for (i in 1:5){ 
    res[i]=f(foo[i,],i) 
    } 
> res 
[1] 0.94068810 0.30670585 0.18281807 0.02824884 0.04084157 

의견을 보내주십시오. 당신의 진짜 목적은 당신의 예와 같은 경우,이 부문 벡터화 할 수

+0

'mapply' 기반 솔루션이있을 수 있습니다. –

+0

예 : –

+0

"mapply (f, split (foo, row (foo)), goo)"가 작동해야한다고 생각합니다. 왜 그것이 비효율적이라고합니까? 감사합니다 –

답변

2

:

f <- function(x) t.test(x[1:10], x[11:20])$p.value 
apply(foo, 1, f)/goo 

주석 바탕으로, 위는 적합하지 않습니다.

f = function (x,y) t.test(x[1:10],x[11:20])$p.value/y 
goo = 1:5 
diag(apply(foo,1,f,y=goo)) 

시간이나 공간의 비효율적되고 게다가, 이것은 또 다른 문제를 앓고 : 예제의 경우

, 당신은 반환 행렬의 대각선 원하는 결과임을 관찰 할 수 있습니다. y에 대한 연산 결과가 벡터화되어 있기 때문에 예제에 맞습니다. 그리고 그 경우 이전 솔루션이 더 좋습니다. 그래서 나는 당신의 실제 문제에서 귀하의 작업이 벡터화되지 않았다고 의심합니다.

때때로 for 루프가 가장 좋은 답변입니다. apply 계열의 기능은 마법 같은 것이 아닙니다. 그들은 아직도 고리 다.

여기에 sapply 솔루션이 있습니다. 시간당 for을 이길 수는 없지만 (아마도 손실되지는 않음) 높은 공간 오버 헤드가 없습니다. 아이디어는 f

sapply(seq(nrow(foo)), function(i) f(foo[i,], goo[i])) 
직접 부문은 최고 (그러나 실제로 적용)입니다
+0

고마워,하지만 내 실제 데이터. 나는 그 분열을하지 않을 것이다. 예제에서, 나는 f 함수가 스칼라 인자를위한 벡터를 취하는 것을 보여 주려했다. 그리고 apply 함수는 f 함수가 두 번째 스칼라 인수에 대해 벡터를 사용하는 것을 허용하지 않습니다. –

+0

@Li_Q 편집 된 버전보기. –

1
f <- function (x,y) t.test(x[1:10],x[11:20])$p.value/y 
f2 <- function(a, b){ 
    tt <- t.test(x = a[1:10], y = a[11:20])$p.value 
    tt/b 
} 
f3 <- function() { 
    res <- numeric(5) 
    for (i in 1:5){ 
     res[i] <- f(foo[i,],i) 
    } 
    res 
} 
f4 <- function(x) t.test(x[1:10], x[11:20])$p.value 

set.seed(101) 
foo <- matrix(rnorm(100),ncol=20) 
goo <- 1:5 
library(rbenchmark) 
benchmark(
    apply(foo, 1, f4)/goo, 
    mapply(f,split(foo,row(foo)),goo), 
    f2(foo,goo), 
    f3(),replications=1000, 
    sapply(seq(nrow(foo)), function(i) f(foo[i,], goo[i])), 
    columns=c("test","replications","elapsed","relative")) 

##      test replications elapsed relative 
## 1 apply(foo, 1, f4)/goo   1000 1.581  5.528 
## 3   f2(foo, goo)   1000 0.286  1.000 
## 4     f3()   1000 1.458  5.098 
## 2    mapply(...)   1000 1.599  5.591 
## 5    sapply(...)   1000 1.486  5.196 

에 전달할 행 인덱스를 적용하고 foo의 행과 goo의 요소를 추출하는 것을 사용하는 것입니다; 이 예제에서는 다른 솔루션들 사이에는 큰 차이가 없지만 for 루프가 sapply보다 우수합니다. 이는 mapply보다 좋습니다. 좀 더 현실적인 예를 들어이 문제를 해결해야 문제의 규모가 어떻게 확대되는지 확인할 수 있습니다.

+0

내 대답을 다시 열어야한다고 생각합니까? 나는 OP가 이미 내가 올린 것을 알고있는 것처럼 느꼈다. –

+0

나는 상처받을 것이라고 생각하지 않는다. –

관련 문제