6

您好我想根据数据表中的值选择一组值。

具体来说,我想为 e == 1 的所有正值选择按日期和 id 分组的所有列

   id   date     e       logret 
   7 2011-07-29  1   -0.0272275211      
   7 2011-07-29  2    0.0034229025      
   7 2011-07-29  3    0.0042622177      
   8 2011-07-29  1    0.0035662770      
   8 2011-07-29  2   -0.0015268474 
   8 2011-07-29  3    0.0013333333
   7 2011-07-30  1    0.0044444444      
   7 2011-07-30  2   -0.0001111111 
   7 2011-07-30  3    0.0013333333

这里将选择 id 8 和日期 2011-07-29 的所有元素以及日期 2011-07-30 的 id 7 的所有元素,因为 e == 1 的 logret > 0 其中 id 7 的所有元素在 2011- 07-29 被忽略,因为第一个 logret(其中 e==1)<0

答:

   8 2011-07-29  1    0.0035662770      
   8 2011-07-29  2   -0.0015268474 
   8 2011-07-29  3    0.0013333333
   7 2011-07-30  1    0.0044444444      
   7 2011-07-30  2   -0.0001111111 
   7 2011-07-30  3    0.0013333333    

在 sql 中,我会使用某种子选择来实现这一点。我会 :

1) Select the id and date where e=1 and logret > 0
2) Select * join on results of subselect

我认为 data.table 也可以做到这一点,但我发现用 data.table 术语表达它很棘手。具体来说,我可以复制第 1 步,但不能在第 2 步中执行连接部分。

pos <- DT[e==1][logret > 0]

但无法将 pos 值重新加入我的 DT

4

2 回答 2

3

它不漂亮,也不在 中data.table,但这似乎可行:

# Recreate your data
df = read.table(header=TRUE, text="id   date    e       logret 
    7 2011-07-29 1   -0.0272275211      
    7 2011-07-29 2    0.0034229025      
    7 2011-07-29 2    0.0042622177      
    8 2011-07-29 1    0.0035662770      
    8 2011-07-29 2   -0.0015268474 
    8 2011-07-29 3    0.0013333333")
df[which(df$id != df$id[which(df$e == 1 & df$logret < 0)]),]
#   id       date e       logret
# 4  8 2011-07-29 1  0.003566277
# 5  8 2011-07-29 2 -0.001526847
# 6  8 2011-07-29 3  0.001333333
#
## Or the equivalent in "positive" terms
#
# df[which(df$id == df$id[which(df$e == 1 & df$logret > 0)]),]

根据评论和新样本数据进行更新

就在我的脑海里(我对这个包没有任何经验data.table;它在我的“学习”清单上)。这是一个可能的解决方案:

temp = split(df, df$date)
lapply(temp, 
       function(x) 
         x[which(x$id == x$id[which(x$e == 1 & x$logret > 0)]),])
# $`2011-07-29`
#   id       date e       logret
# 4  8 2011-07-29 1  0.003566277
# 5  8 2011-07-29 2 -0.001526847
# 6  8 2011-07-29 3  0.001333333
# 
# $`2011-07-30`
#   id       date e        logret
# 7  7 2011-07-30 1  0.0044444444
# 8  7 2011-07-30 2 -0.0001111111
# 9  7 2011-07-30 3  0.0013333333

更新 2

这也值得一试merge

merge(df, df[which(df$e == 1 & df$logret > 0), c(1, 2)])
#   id       date e        logret
# 1  7 2011-07-30 1  0.0044444444
# 2  7 2011-07-30 2 -0.0001111111
# 3  7 2011-07-30 3  0.0013333333
# 4  8 2011-07-29 1  0.0035662770
# 5  8 2011-07-29 2 -0.0015268474
# 6  8 2011-07-29 3  0.0013333333
于 2012-07-26T11:55:14.270 回答
2

我已经解决了一个回合:

pos <- DT[e==1][logret > 0, list(id,date)]
ans <- DT[J(pos$id,pos$date)];

有兴趣在 data.table 中听到更优雅的 1 行方法。


马修编辑:

如果key(DT)已经是,(id,date)那么一个班轮将是:

DT[DT[e==1 & logret>0, list(id,date)]]

这也应该更快。如果您可以依赖iddate成为 的前 2 列DT,则可以将其缩短为:

DT[DT[e==1 & logret>0]]
于 2012-07-26T13:25:06.280 回答