2017-09-01 12 views
1

私はIDと速度のデータセットを持っています。しきい値を超える変数のインスタンスを数える

id <- c(1,1,1,1,2,2,2,2,3,3,3) 

speed <- c(40,30,50,40,45,50,30,55,50,50,60) 

i <- cbind(id, speed) 

limit <- 35 

言って、「スピード」十字架「リミット」の場合は1としてカウントされますし、速度は下記来ると「リミット」を横切る場合にのみ、再びカウントされます。

私はデータが欲しいと思っています。

id | Speed Viol. 
---------- 
1 | 2 
--------- 
2 | 2 
--------- 
3 | 1 
--------- 

ここではid(count)です。

id1 (1) 40 (2) 50,40 

id2 (1) 45,50 (2) 55 

id3 (1) 50,50,60 

if()を使用しない方法。

+0

あなたは 'tapply'を試しましたか? –

答えて

5

ここにはコメントとオリジナルのベクトルに示唆されている方法tapplyがあります。

tapply(speed, id, FUN=function(x) sum(c(x[1] > limit, diff(x > limit)) > 0)) 
1 2 3 
2 2 1 

は、IDごとに各グループに機能を適用します。この関数は、IDの最初の要素が35を超えているかどうかをチェックし、これをdiffの出力に連結します。その引き数は、後続の観測値が35を超えているかどうかをチェックします。diffは、IDがそれを下回った後、レベル。結果のベクトルの負の値は> 0でFALSE(0)に変換され、これらの結果が合計されます。

tapplyは名前付きベクトルを返します。これはかなり操作しやすいものです。しかし、あなたはdata.frameをしたい場合は、DBにより示唆されるように、そしてあなたの代わりにaggregateを使用することもできます。

aggregate(speed, list(id=id), FUN=function(x) sum(c(x[1] > limit, diff(x > limit)) > 0)) 
    id x 
1 1 2 
2 2 2 
3 3 1 
2

ここにはdplyrソリューションがあります。私はグループidでグループ化し、速度が各行の上限を超えているかどうかをチェックしますが、前のエントリにはありませんでした。 (私はlagを使用して前の行を取得します)。この場合、TRUEが生成されます。または、id(つまりrow_number()==1)の最初の行で、上限を超えている場合はTRUEとなります。次に、それぞれidのすべてのTRUEの値をsummariseを使用して合計します。

id <- c(1,1,1,1,2,2,2,2,3,3,3) 
speed <- c(40,30,50,40,45,50,30,55,50,50,60) 
i <- data.frame(id, speed) 
limit <- 35 

library(dplyr) 

i %>% 
    group_by(id) %>% 
    mutate(viol=(speed>limit&lag(speed)<limit)|(row_number()==1&speed>limit)) %>% 
    summarise(sum(viol)) 

# A tibble: 3 x 2 
    id `sum(viol)` 
    <dbl>  <int> 
1  1   2 
2  2   2 
3  3   1 
1

をここで与えdata.tableを持つ別のオプション、

library(data.table) 

setDT(i)[, id1 := rleid(speed > limit), by = id][ 
      speed > limit, .(violations = uniqueN(id1)), by = id][] 

です
id violations 
1: 1   2 
2: 2   2 
3: 3   1 
0
aggregate(speed~id, data.frame(i), function(x) sum(rle(x>limit)$values)) 
# id speed 
#1 1  2 
#2 2  2 
#3 3  1 

主な考え方は、x > limitが制限速度に違反した場合のインスタンスをチェックし、rle(x)はそれらのインスタンスを連続違反または連続非違反に分類することです。次に、連続した違反のグループをカウントするだけです(rle(x>limit)$valuesTRUEの場合)。

関連する問題