3

初心者の質問: 約 50K 要素の data.frame のこの二重ループは、非常にゆっくりと評価され、30 秒以上かかります。これを修正するには何らかの形の適用関数を使用する必要があることをオンラインで読みましたが、これまでのところコードを正しく取得できません。ゲイン結果を持つ最初の data.frame から始めて、目標は、ターゲットより大きい値のみが入力され、他のすべてが 0 である 2 番目の data.frame を取得することです。

このコードは機能します:

ExcessGain = function(Value, Target){
  max(0,Value - Target)
}

Pcnt_O_O_x = data.frame()

for (j in 1:ncol(Pcnt_O_O)){
  for (i in 1:nrow(Pcnt_O_O)){
    Pcnt_O_O_x[i,j] = ExcessGain(Pcnt_O_O[i,j], GainTargetPcnt)
  }
}

内部ループの代わりに適用関数を使用して、何らかの方法でこれを高速化できますか?

4

1 に答える 1

3

関数は、配列内の各セルの値からターゲット値を減算しているように見えます。負の値はすべて 0 に置き換えられます。その場合、ループは必要ありません。R の組み込みのベクトル化を使用してこれを行うことができます。

set.seed(123)
# If you have a data.frame of all numeric elements turn it into a matrix first
df <- as.matrix( data.frame( matrix( runif(25) , nrow = 5 ) ) )

target <- 0.5
df
#        X1        X2        X3         X4        X5
#1 0.2875775 0.0455565 0.9568333 0.89982497 0.8895393
#2 0.7883051 0.5281055 0.4533342 0.24608773 0.6928034
#3 0.4089769 0.8924190 0.6775706 0.04205953 0.6405068
#4 0.8830174 0.5514350 0.5726334 0.32792072 0.9942698
#5 0.9404673 0.4566147 0.1029247 0.95450365 0.6557058

df2 <- df - target
df2
#          X1          X2          X3         X4        X5
#1 -0.21242248 -0.45444350  0.45683335  0.3998250 0.3895393
#2  0.28830514  0.02810549 -0.04666584 -0.2539123 0.1928034
#3 -0.09102308  0.39241904  0.17757064 -0.4579405 0.1405068
#4  0.38301740  0.05143501  0.07263340 -0.1720793 0.4942698
#5  0.44046728 -0.04338526 -0.39707532  0.4545036 0.1557058

df2[ df2 < 0 ] <- 0
df2
#        X1         X2        X3        X4        X5
#1 0.0000000 0.00000000 0.4568333 0.3998250 0.3895393
#2 0.2883051 0.02810549 0.0000000 0.0000000 0.1928034
#3 0.0000000 0.39241904 0.1775706 0.0000000 0.1405068
#4 0.3830174 0.05143501 0.0726334 0.0000000 0.4942698
#5 0.4404673 0.00000000 0.0000000 0.4545036 0.1557058

matrixでの操作と での操作の速度の違いを示すベンチマークを次に示しますdata.framef.df( df )f.m( m )は、それぞれ 100 万の要素を持つ data.frame と matrix で動作する 2 つの関数です。

require( microbenchmark )
microbenchmark( f.df( df ) , f.m( m ) , times = 10L )

#Unit: milliseconds
#     expr        min         lq     median         uq        max neval
# f.df(df) 6944.09808 9009.39684 9233.18528 9533.75089 10036.5963    10
#   f.m(m)   37.26433   39.00189   40.46229   41.15626   130.6983    10

マトリックスの操作は、マトリックスが大きい場合、2桁速くなります。

適用関数を本当に使用する必要がある場合は、次のようにマトリックスのすべてのセルに適用できます。

m <- matrix( runif(25) , nrow = 5 )
target <- 0.5
apply( m , 1:2 , function(x) max(x - target , 0 ) )
#         [,1]      [,2]       [,3]      [,4]      [,5]
#[1,] 0.4575807 0.0000000 0.15935928 0.0000000 0.1948637
#[2,] 0.0000000 0.0000000 0.00000000 0.0000000 0.0000000
#[3,] 0.0000000 0.0000000 0.00000000 0.0000000 0.0000000
#[4,] 0.3912719 0.0000000 0.06155316 0.1533290 0.0000000
#[5,] 0.3228921 0.4697041 0.23554353 0.1352888 0.0000000
于 2013-04-25T15:30:15.560 に答える