我想得到一个介于多个范围之间的值列表。
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]))}
然而实际数据集非常大,我正在寻找一种更有效的方法。
任何建议表示赞赏!谢谢!
答案 0 :(得分:5)
如果您拥有data.table的最新CRAN版本,则可以使用非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]
答案 1 :(得分: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
答案 2 :(得分:3)
以下是使用lapply
和%between%
rbindlist(lapply(seq_len(nrow(range)), function(i) values[value %between% range[i]]))
此方法根据范围中的变量循环遍历每次迭代中的范围data.table和子集值。 lapply
返回一个列表,rbindlist
构造成一个data.table。如果您想要一个向量,请将rbindlist
替换为unlist
。
为了检查给定数据上每个建议的速度,我进行了快速比较
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%
的矢量化扩展。