1

私はプログラミングの初心者です。したがって、この問題は簡単に解決できる可能性があります。たとえば、同じ次元の 3 つの行列があります。

A = matrix(1:16,4,4)
B = matrix(rnorm(16,5,1),4,4)
C = matrix(rnorm(16,9,1),4,4)

A の値が 8 よりも小さい位置で B のすべての値を含む新しい行列 (D) を作成したいと考えています。それ以外の場合、A の値が 8 以上の場合、新しい行列 D には行列 C の値が含まれている必要があります。 「ifelse」関数を使用してすでに問題を解決しています。

D = ifelse(A<8,B,C)

ただし、これは非常に遅いです。この行列 D を生成するより高速な方法はありますか? よろしくお願いします!

4

2 に答える 2

1

これを試して:

D <- (A < 8) * B + (A >= 8) * C

それは少し速いです:

A = matrix(sample(16,1e4,TRUE),100,100)
B = matrix(rnorm(1e4,5,1),100,100)
C = matrix(rnorm(1e4,9,1),100,100)

require(microbenchmark)

microbenchmark(D1 <- (A < 8) * B + (A >= 8) * C, D2 <- ifelse(A<8,B,C))

Unit: microseconds
                             expr      min        lq    median       uq      max neval
 D1 <- (A < 8) * B + (A >= 8) * C  499.102  528.4075  542.2415  554.983  674.206   100
        D2 <- ifelse(A < 8, B, C) 4015.024 4062.5310 4079.4590 4173.564 5512.694   100

identical(D1,D2)

[1] TRUE

編集:これでさらに速くなる可能性があります:

D <- {A < 8} * {B - C} + C

括弧の代わりに中括弧と単一の比較に注意してください。ベンチマーク:

microbenchmark(D1 <- {A < 8} * {B - C} + C, D2 <- ifelse(A<8,B,C))

Unit: microseconds
                                    expr      min       lq    median       uq      max neval
 D1 <- {     A < 8 } * {     B - C } + C  289.050  300.881  310.7105  333.645  496.189   100
               D2 <- ifelse(A < 8, B, C) 4027.037 4057.980 4069.8110 4148.627 5372.173   100

sum(abs(D1-D2))
#[1] 8.304468e-14

しかし、 の減算と加算を考えると、数値精度に関しては少し影響がありCます。

于 2013-09-25T12:00:29.763 に答える
1

大規模な配列に対してこれを行ういくつかの方法を次に示します。

A <- matrix(1:16,10000,10000)
B <- matrix(rnorm(10000^2),10000,10000)
C <- matrix(rnorm(10000^2),10000,10000)

> invisible(gc())
> system.time(D<-ifelse(A<8,B,C))
   user  system elapsed 
 15.588   6.608  22.237 
> invisible(gc())
> system.time(D<- (A<8)*B+(A>=8)*C)
   user  system elapsed 
  3.104   3.152   6.267 
> invisible(gc())
> system.time({D<-B; w<-which(A>=8); D[w]<-C[w]})
   user  system elapsed 
  2.872   1.416   4.296 
> invisible(gc())
> system.time({D<-B; w<-(A>=8); D[w]<-C[w]})
   user  system elapsed 
  4.200   1.788   5.998 
> invisible(gc())
> system.time(D<- {A<8}*{B-C}+C)
   user  system elapsed 
  2.012   1.996   4.018 
> 

したがって、少なくとも私のマシンでは、最速の正確な方法は{D<-B; w<-which(A>=8); D[w]<-C[w]}. D<- {A<8}*{B-C}+CFerdinand.kraft によって提案された方法は、わずかに高速ですが、精度がいくらか犠牲になります。

于 2013-09-25T13:09:16.433 に答える