2013-01-24 110 views
3

後創造新的專欄中,我有兩個data.tables,mainmetrics,都是由cid 我要添加到表main平均每個位於度量幾個值的鍵。連接兩個data.tables

但是,我想篩選code,只對metrics中的那些行與給定的code進行平均。

> metrics 
    cid code DZ value1 value2 
1: 1001 A 101  8  21 
2: 1001 B 102  11  26 
3: 1001 A 103  17  25 
4: 1002 A 104  25  39 
5: 1002 B 105  6  30 
6: 1002 A 106  23  40 
7: 1003 A 107  27  32 
8: 1003 B 108  16  37 
9: 1003 A 109  14  42 

# DESIRED OUTPUT 
> main 
    cid A.avg.val1 A.avg.val2 B.avg.val1  B.avg.val2  
1: 1001 12.5   23.0   11    26      
2: 1002 24.0   39.5    6    30    
3: 1003 20.5   37.0   16    37    



# SAMPLE DATA 
set.seed(1) 
main <- data.table(cid=1e3+1:3, key="cid") 
metrics <- data.table(cid=rep(1e3+1:3, each=3), code=rep(c("A", "B", "A"), 3), DZ=101:109, value1=sample(30, 9), value2=sample(20:50, 9), key="cid") 
code.filters <- c("A", "B") 

這些行可以獲得所需的輸出,但我很難將新列分配到main中。 (另外,以編程方式進行則是首選)。

main[metrics[code==code.filters[[1]]]][, list(mean(c(value1))), by=cid] 
main[metrics[code==code.filters[[1]]]][, list(mean(c(value2))), by=cid] 
main[metrics[code==code.filters[[2]]]][, list(mean(c(value1))), by=cid] 
main[metrics[code==code.filters[[1]]]][, list(mean(c(value2))), by=cid] 

此外,有人可以解釋爲什麼下面的行只取每個組的最後一個值?

main[metrics[ code=="A"], A.avg.val1 := mean(c(value1))] 
+0

其實它不是在數據庫中存儲計算值一個很好的做法。這些應該在輸出數據時完成。 – N1tr0

+0

也許,'不是一個好習慣'是錯誤的術語。也許,'有什麼意義'更好? :-)計算值的一個主要方面是它們發生了變化,爲什麼要在運行中計算並始終準確時存儲該數據?如果你存儲它並去調用它,它可能已經過時並且不正確。 – N1tr0

+0

@ N1tr0,我想你可能誤解了這個問題:我沒有將值存儲回數據庫,我將它存儲在data.table中,即存儲器中。 –

回答

2

關閉工作@阿倫的回答,下面得到期望的結果:

invisible( 
sapply(code.filters, function(cf) 
    main[metrics[code==cf, list(avgv1 = mean(value1), avgv2 = mean(value2)), by=cid], 
     paste0(cf, c(".avg.val1", ".avg.val2")) :=list(avgv1, avgv2)] 
)) 

> main 
    cid A.avg.val1 A.avg.val2 B.avg.val1 B.avg.val2 
1: 1001  12.5  23.0   11   26 
2: 1002  24.0  39.5   6   30 
3: 1003  20.5  37.0   16   37 
3

您不需要main。可以按如下方式從metrics直接得到它:

> tmp.dt <- metrics[, list(A.avg.val1 = mean(value1[code=="A"]), 
       A.avg.val2 = mean(value2[code=="A"]), 
       B.avg.val1 = mean(value1[code == "B"]), 
       B.avg.val2 = mean(value2[code == "B"])), by=cid] 

#  cid A.avg.val1 A.avg.val2 B.avg.val1 B.avg.val2 
# 1: 1001  12.5  23.0   11   26 
# 2: 1002  24.0  39.5   6   30 
# 3: 1003  20.5  37.0   16   37 

如果你仍然想main於子集只是做:

main <- data.table(cid = c(1001:1002)) 
> tmp.dt[main] 

#  cid A.avg.val1 A.avg.val2 B.avg.val1 B.avg.val2 
# 1: 1001  12.5  23.0   11   26 
# 2: 1002  24.0  39.5   6   30 
+0

主要是比上面示例中的數據表大得多。我需要它回到主要的進一步計算。但是,謝謝你的建議!我想我可以從這裏開始工作! –

+0

謝謝Arun,我不認爲'tmp.dt'是必需的,因爲我可以直接在'main [...]'中包裝你的建議。請參閱下面 –

+0

感謝您的指導;) –

2

我將分兩個步驟來完成此。首先,讓你的手段,那麼reshape數據

foo <- main[metrics] 
bar <- foo[, list(val1 = mean(value1), 
        val2 = mean(value2)), 
      by=c('cid', 'code')] 

library(reshape2) 
bar.melt <- melt(bar, id.var=c('cid', 'code')) 
dcast(data=bar.melt, 
     cid ~ code + variable) 

不過說真的,我可能會離開這個數據在「長」格式,因爲我覺得它更容易的工作!

+0

謝謝@Justin。我希望能夠以「data.table-esque」的方式做到這一點,因爲我希望獲得它提供的內存效率。 –