2017-04-26 16 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) 

私は現在、しかし、実際のループのため、

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の可能性を参加

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

私は何かを見落としていますか、これは "値"テーブルの複数の/多数の列の場合には不都合でしょうか?すなわち列を列挙しないで簡単な方法がありますか? –

+2

便利な関数 '%inrange%'を使う: 'values [value%inrange%range]' – Henrik

+0

@Henrikとてもいいです!私の答えにそれを含めました(答えとして投稿したい場合は、ここでそれを削除します) – Jaap

5

最新のCRANバージョンのdata.tableを使用している場合は、非等価結合を使用できます。たとえば、あなたが、あなたの元のデータサブセットに使用できるインデックスを作成することができます

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

います:

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

は、この方法は、各反復でdata.table範囲およびサブセット値をループlapply%between%

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

を使用して一つの方法であります範囲内の変数に従って。 lapplyはリストを返します。rbindlistはdata.tableに構成されています。ベクトルが必要な場合はrbindlistunlistに置き換えます。


ベンチマーク

ただ、与えられたデータに各提案の速度をチェックすることが期待されるかもしれませんが、私は簡単な比較

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%のベクトル化された拡張です。

関連する問題