如何在data.table中选择一个值?

时间:2013-12-12 08:41:55

标签: r data.table

我的数据格式如下

structure(list(atp = c(1, 0, 1, 0, 0, 1), len = c(2, NA, 3, NA, 
NA, 1), Day_1 = c(8, 7, 8, 9, 6, 6), Day_2 = c(94, 94, 102, 97, 
102, 100), Day_3 = c(104, 162, 133, 142, 96, 122)), .Names = c("atp", 
"len", "Day_1", "Day_2", "Day_3"), row.names = c(NA, -6L), class = "data.frame")

我想获得以下输出

structure(list(atp = c(1, 0, 1, 0, 0, 1), len = c(2, NA, 3, NA, 
NA, 1), Day_1 = c(8, 7, 8, 9, 6, 6), Day_2 = c(94, 94, 102, 97, 
102, 100), Day_3 = c(104, 162, 133, 142, 96, 122), output = c(94, 
NA, 133, NA, NA, 6)), .Names = c("atp", "len", "Day_1", "Day_2", 
"Day_3", "output"), row.names = c(NA, -6L), class = "data.frame")

基本上取决于第2列值,它从第3,4或5列中选择值。

我通过以下代码实现了它

result<-cbind(y, output=apply(y, 1, function(r) r[r["len"]+2]))

但这个过程非常耗时。有没有办法加快这个过程?我怎样才能使用data.tables?

4 个答案:

答案 0 :(得分:3)

一种可能的方法:

result <- cbind(y, 
                output = unlist(y[3:5])[nrow(y) * (y$len -1) + seq.int(nrow(y))])

另一个(这应该更快):

result <- cbind(y, output = y[3:5][cbind(seq.int(nrow(y)), y$len)])

这两种方法都会产生:

#   atp len Day_1 Day_2 Day_3 output
# 1   1   2     8    94   104     94
# 2   0  NA     7    94   162     NA
# 3   1   3     8   102   133    133
# 4   0  NA     9    97   142     NA
# 5   0  NA     6   102    96     NA
# 6   1   1     6   100   122      6

答案 1 :(得分:2)

事实证明,我的解决方案具有误导性,对不起。

无论如何,这是一些有趣的基准测试:http://pastebin.com/adwmFRXP

对于N = 1e3:

          test replications elapsed relative user.self sys.self user.child sys.child
3       sven()          100    0.03    1.000      0.03     0.00         NA        NA
5 codoremifa()          100    0.07    2.333      0.07     0.00         NA        NA
4     shadow()          100    0.21    7.000      0.19     0.00         NA        NA
1    default()          100    0.59   19.667      0.60     0.00         NA        NA
2  tonytonov()          100    1.31   43.667      1.04     0.27         NA        NA

对于N = 1e4:

          test replications elapsed relative user.self sys.self user.child sys.child
3       sven()           50    0.02      1.0      0.02     0.00         NA        NA
5 codoremifa()           50    0.03      1.5      0.03     0.00         NA        NA
4     shadow()           50    0.09      4.5      0.09     0.00         NA        NA
2  tonytonov()           50    0.57     28.5      0.45     0.12         NA        NA
1    default()           50    2.93    146.5      2.93     0.00         NA        NA

对于N = 1e5:

          test replications elapsed relative user.self sys.self user.child sys.child
3       sven()           10    0.01        1      0.02     0.00         NA        NA
5 codoremifa()           10    0.02        2      0.02     0.00         NA        NA
4     shadow()           10    0.03        3      0.03     0.00         NA        NA
2  tonytonov()           10    0.12       12      0.11     0.02         NA        NA
1    default()           10    8.75      875      8.66     0.01         NA        NA

对于N = 1e6:

          test replications elapsed relative user.self sys.self user.child sys.child
3       sven()           10    0.01        1      0.02     0.00         NA        NA
5 codoremifa()           10    0.01        1      0.02     0.00         NA        NA
4     shadow()           10    0.03        3      0.03     0.00         NA        NA
2  tonytonov()           10    0.13       13      0.11     0.01         NA        NA
1    default()           10   86.73     8673     85.89     0.56         NA        NA

答案 2 :(得分:1)

其中dt1是您的第一个数据集 -

for ( i in unique(dt1[!is.na(dt1$len),'len']))
{
  dt1[dt1$len == i & !is.na(dt1$len),'Output'] <- dt1[dt1$len == i & !is.na(dt1$len),paste0('Day_',i)]
}

答案 3 :(得分:0)

以下是使用data.table的答案。这应该是大data.frame的最快版本。但是,它也明确使用了您提供的数据结构,因此可能不容易推广。

dt <- data.table(y)
dt[, output:=ifelse(len==1, Day_1, 
                    ifelse(len==2, Day_2, Day_3))]