2017-04-26 70 views
3

我想获取多个范围之间的值列表。多个范围的子集

library(data.table) 
values <- data.table(value = c(1:100)) 
range <- data.table(start = c(6, 29, 87), end = c(10, 35, 92)) 

我需要的结果只包括落在这些范围之间的值:但是实际

results <- c(6, 7, 8, 9, 10, 29, 30, 31, 32, 33, 34, 35, 87, 88, 89, 90, 91, 92) 

我目前做这一个for循环,

results <- data.table(NULL) 
for (i in 1:NROW(range){ 
      results <- rbind(results, 
       data.table(result = values[value >= range[i, start] & 
       value <= range[i, end], value]))} 

数据集非常大,我正在寻找更有效的方法。

任何建议表示赞赏!谢谢!

回答

5

使用非球菌加盟data.table可能性:

values[range, on = .(value >= start, value <= end), .(results = x.value)] 

这给:

results 
1:  6 
2:  7 
3:  8 
4:  9 
5:  10 
6:  29 
7:  30 
8:  31 
9:  32 
10:  33 
11:  34 
12:  35 
13:  87 
14:  88 
15:  89 
16:  90 
17:  91 
18:  92 

或按照@Henrik的建议:values[value %inrange% range]。这工作也非常的data.table与多列:

# create new data 
set.seed(26042017) 
values2 <- data.table(value = c(1:100), let = sample(letters, 100, TRUE), num = sample(100)) 

> values2[value %inrange% range] 
    value let num 
1:  6 v 70 
2:  7 f 77 
3:  8 u 21 
4:  9 x 66 
5: 10 g 58 
6: 29 f 7 
7: 30 w 48 
8: 31 c 50 
9: 32 e 5 
10: 33 c 8 
11: 34 y 19 
12: 35 s 97 
13: 87 j 80 
14: 88 o 4 
15: 89 h 65 
16: 90 c 94 
17: 91 k 22 
18: 92 g 46 
+1

我是否忽略了一些东西,或者这对于“values”表中的多个/许多列的情况是不实际的?即有没有列出列的简单方法? –

+2

使用便捷功能'%inrange%':'values [value%inrange%range]' – Henrik

+0

@Henrik很好!包括在我的答案中(如果你想把它作为答案发布:继续,我会在这里删除它) – Jaap

5

如果您拥有最新的CRAN版本的data.table,则可以使用非Equi连接。例如,您可以创建一个索引,然后您可以使用子集的原始数据:

idx <- values[range, on = .(value >= start, value <= end), which = TRUE] 
# [1] 6 7 8 9 10 29 30 31 32 33 34 35 87 88 89 90 91 92 
values[idx] 
2

这里使用lapply%between%

rbindlist(lapply(seq_len(nrow(range)), function(i) values[value %between% range[i]])) 

此方法遍历data.table范围,并在每个迭代子集值的一种方法根据范围内的变量。 lapply返回一个列表,其中rbindlist构造成data.table。如果你想要一个矢量,用unlist代替rbindlist


基准

只是为了检查在给定的数据,每条建议的速度,我跑的快速比较

microbenchmark(
    lmo=rbindlist(lapply(seq_len(nrow(range)), function(i) values[value %between% range[i]])), 
    dd={idx <- values[range, on = .(value >= start, value <= end), which = TRUE]; values[idx]}, 
    jaap=values[range, on = .(value >= start, value <= end), .(results = x.value)], 
    inrange=values[value %inrange% range]) 

这回

Unit: microseconds 
    expr  min  lq  mean median  uq  max neval cld 
    lmo 1238.472 1460.5645 1593.6632 1520.8630 1613.520 3101.311 100 c 
     dd 688.230 766.7750 885.1826 792.8615 825.220 3609.644 100 b 
    jaap 798.279 897.6355 935.9474 921.7265 970.906 1347.380 100 b 
inrange 463.002 518.3110 563.9724 545.5375 575.758 1944.948 100 a 

正如预期的那样,我的循环解决方案比其他的慢很多。然而,明确的赢家是%inrange%,这本质上是%between%的矢量化扩展。