3

大きなRデータフレームのすべての行のフィルタリングとカウントを最適化する方法の続き

私はdata.table次のようなものを持っています:

  name day wages hour colour
1  Ann   1   100    6  Green
2  Ann   1   150   18   Blue
3  Ann   2   200   10   Blue
4  Ann   3   150   10  Green
5  Bob   1   100   11    Red
6  Bob   1   200   17    Red
7  Bob   1   150   20  Green
8  Bob   2   100   11    Red

一意の名前と日のペアごとに、4つの期間のうちの1つについて、いくつかの事実を知りたいと思います。私が気にかけている期間は次のとおりです。

t1 (hour < 9) 
t2 (hour < 17) 
t3 (hour > 9) 
t4 (hour > 17)

事実のいくつかの例は次のとおりです。

wages > 175
colour = "Green"

data.table私は次のフィルターでこれを達成することができます

setkey(dt,name,day)
result <- dt[,list(wages.t1=sum(wages>175&hour<9),
     wages.t2=sum(wages>175&hour<17),
     wages.t3=sum(wages>175&hour>9),
     wages.t4=sum(wages>175&hour>17),
     green.t1=sum(colour=="Green"&hour<9),
     green.t2=sum(colour=="Green"&hour<17),
     green.t3=sum(colour=="Green"&hour>9),
     green.t4=sum(colour=="Green"&hour>17)),

list(name、day)]

私にくれ

     name day wages.t1 wages.t2 wages.t3 wages.t4 green.t1 green.t2 green.t3 green.t4
[1,]  Ann   1        0        0        0        0        1        1        0        0
[2,]  Ann   2        0        1        1        0        0        0        0        0
[3,]  Ann   3        0        0        0        0        0        1        1        0
[4,]  Bob   1        0        0        1        0        0        0        1        1
[5,]  Bob   2        0        0        0        0        0        0        0        0

しかし、これはa)読み取りと書き込みがひどく、b)非効率のようです。

どうすればもっとうまくできるかについてのヒントはありますか?私の実際のシナリオでは、数十万の行、4つの期間、および期間ごとに30〜35のファクトがあることに注意してください。

-作成するコードdt

dt = data.table(
  name = factor(c("Ann", "Ann", "Ann", "Ann", 
                  "Bob", "Bob", "Bob", "Bob")), 
  day = c(1, 1, 2, 3, 1, 1, 1, 2), 
  wages = c(100, 150, 200, 150, 100, 200, 150, 100), 
  hour = c(6, 18, 10, 10, 11, 17, 20, 11), 
  colour = c("Green", "Blue", "Blue", "Green", "Red",
             "Red", "Green", "Red")
)
4

1 に答える 1

4

次のようなものはどうですか:

f = list(quote(wages>175),quote(colour=="Green"))
t = list(quote(hour<9),quote(hour<17),quote(hour>9),quote(hour>17))
dt = as.data.table(df)
dt[,as.list(mapply("%*%",
            lapply(t,eval,.SD),
            rep(lapply(f,eval,.SD),each=length(t))
           )), by=list(name,day)]
     name day V1 V2 V3 V4 V5 V6 V7 V8
[1,]  Ann   1  0  0  0  0  1  1  0  0
[2,]  Ann   2  0  1  1  0  0  0  0  0
[3,]  Ann   3  0  0  0  0  0  1  1  0
[4,]  Bob   1  0  0  1  0  0  0  1  1
[5,]  Bob   2  0  0  0  0  0  0  0  0

明らかに列名は取り組まれていませんが、このアプローチで問題がなければ追加できます。

tそれぞれfがグループごとに1回だけ評価され、次にそれらの結果の組み合わせが組み合わされるため、これはより効率的です。

于 2012-04-19T14:45:20.737 に答える