按时间值排序按最后一个最大值排序的行

时间:2017-01-19 13:44:03

标签: r dplyr

我有一个带有id,排序时间值和值的数据帧。对于每组id,我想删除值小于时间值较小的行的行。

data <- data.frame(id = c(rep(c("a", "b"), each = 3L), "b"), 
                   time = c(0, 1, 2, 0, 1, 2, 3),
                   value = c(1, 1, 2, 3, 1, 2, 4))

> data
  id time value
1  a    0     1
2  a    1     1
3  a    2     2
4  b    0     3
5  b    1     1
6  b    2     2
7  b    3     4

结果将是:

> data
  id time value
1  a    0     1
2  a    2     2
3  b    0     3
4  b    3     4

(对于id == b行,其中time %in% c(3, 4)被删除,因为值value小于time更低的值

我在考虑lag

data %>%
   group_by(id) %>%
   filter(time == 0 | lag(value, order_by = time) < value)

Source: local data frame [5 x 3]
Groups: id [2]

      id  time value
  <fctr> <dbl> <dbl>
1      a     0     1
2      a     2     2
3      b     0     3
4      b     2     2
5      b     3     4

但它没有按预期工作,因为它是一个矢量化函数,所以相反的想法是使用“递归滞后函数”或检查最后一个最大值。我可以通过循环递归地执行它,但我确信有更直接和更高级别的方法来执行它。

任何帮助将不胜感激,谢谢!

3 个答案:

答案 0 :(得分:3)

以下是data.table解决方案:

library(data.table)
setDT(data)
data[, myVal := cummax(c(0, shift(value)[-1])), by=id][value > myVal][, myVal := NULL][]
   id time value
1:  a    0     1
2:  a    2     2
3:  b    0     3
4:  b    3     4

链的第一部分使用shiftcummax来创建滞后值变量的累积最大值。在c(0, shift(value)[-1])中,添加0以提供比变量中任何值更值的值。更一般地说,您可以使用min(value)-1 [-1]子集删除shift的第一个元素,即NA。链的第二部分选择值大于累积最大值的观察值。最后两个链删除累积的最大变量并打印出结果。

答案 1 :(得分:3)

另一种选择是使用data.table

执行自我反/非等联接
library(data.table) # v1.10.0
setDT(data)[!data, on = .(id, time > time, value <= value)]
#    id time value
# 1:  a    0     1
# 2:  a    2     2
# 3:  b    0     3
# 4:  b    3     4

基本上说:&#34; 如果time较大但value不相等,那么我不想要这些行(!签)&#34;

答案 2 :(得分:0)

以下是dplyr的选项。按照&#39; id&#39;进行分组后,我们filter行&#39;值&#39;大于“延迟”的累积最大值。的价值&#39;柱

library(dplyr)
data %>% 
  group_by(id) %>%
  filter(value > cummax(lag(value, default = 0)) ) 
#      id  time value
#   <fctr> <dbl> <dbl>
#1      a     0     1
#2      a     2     2
#3      b     0     3
#4      b     3     4

slice {id}后面的另一个选项是arrange和&#39;时间&#39; (正如OP提到的order

data %>%
     group_by(id) %>%
     arrange(id, time) %>%
     slice(which(value > cummax(lag(value, default = 0)))) 
相关问题