计算超过阈值的变量的实例

时间:2017-09-01 11:41:25

标签: r count grouping

我有一个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

说,如果&#39;速度&#39;十字架限制&#39;将其计为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()

4 个答案:

答案 0 :(得分:5)

这是评论和原始载体中建议的方法tapply

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

tapply通过ID将功能应用于每个组。该函数检查ID的第一个元素是否超过35,然后将其连接到diff的输出,其参数检查后续观察是否大于35.因此diff检查是否为ID在跌破该水平后回到35以上。使用> 0将结果向量中的负值转换为FALSE(0),并将这些结果相加。

tapply返回一个命名向量,使用起来相当不错。但是,如果您需要data.frame,则可以使用aggregate代替d.b建议:

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

答案 1 :(得分:2)

这是一个dplyr解决方案。我按id进行分组,然后检查速度是否高于每行的限制,但不在上一个条目中。 (我使用lag获取上一行)。如果是这种情况,则会生成TRUE。或者,如果它是id的第一行(即row_number()==1)且超出限制,则也会给出TRUE。然后,我使用TRUE对每个id的所有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

答案 2 :(得分: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

答案 3 :(得分: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时)。