【问题标题】:Select row prior to first occurrence of an event by group按组选择事件第一次发生之前的行
【发布时间】:2014-08-17 22:43:00
【问题描述】:

我有一系列观察结果来描述是否以及何时在特定区域发现动物。下面的示例表确定了一天中何时看到 (status == 1) 或未看到 (status == 0) 某种动物。

   id       date status
1   1 2014-06-20      1
2   1 2014-06-21      1
3   1 2014-06-22      1
4   1 2014-06-23      1
5   1 2014-06-24      0
6   2 2014-06-20      1
7   2 2014-06-21      1
8   2 2014-06-22      0
9   2 2014-06-23      1
10  2 2014-06-24      1
11  3 2014-06-20      1
12  3 2014-06-21      1
13  3 2014-06-22      0
14  3 2014-06-23      1
15  3 2014-06-24      0
16  4 2014-06-20      1
17  4 2014-06-21      0
18  4 2014-06-22      0
19  4 2014-06-23      0
20  4 2014-06-24      1

使用data.table 包,我可以确定该地区第一天不再看到动物:

library(data.table)
dt <- as.data.table(df)
dt[status == 0, .SD[1], by = id]
  id       date status
1:  1 2014-06-24      0
2:  2 2014-06-22      0
3:  3 2014-06-22      0
4:  4 2014-06-21      0

虽然上表很有用,但我想知道如何操作该函数来查找动物第一次缺席之前的日期。换句话说,我想知道每只动物在临时离开之前在该区域的最后一天。

我的实际数据集根据情况将这些存在/不存在观察分为不同的时间长度(例如,存在/不存在以 3 小时间隔、6 小时等为间隔)。因此,访问前一行比从每个值中减去时间间隔更容易,因为它总是在变化。我想要的输出如下:

  id       date status
1:  1 2014-06-23      1
2:  2 2014-06-21      1
3:  3 2014-06-21      1
4:  4 2014-06-20      1

请随时使用base 代码或其他软件包(即dplyr)来回答这个问题,我总是在寻找新的东西。感谢您的宝贵时间!

【问题讨论】:

    标签: r aggregate data.table


    【解决方案1】:

    尝试以下方法:

    dt[dt[status == 0, .I[1] - 1, by = id]$V1]
    #   id       date status
    #1:  1 2014-06-23      1
    #2:  2 2014-06-21      1
    #3:  3 2014-06-21      1
    #4:  4 2014-06-20      1
    

    顺便说一句,这种方法(使用.I 而不是.SD)也会快得多。有关更多信息,请参阅this post。

    【讨论】:

    • 感谢您的解决方案和参考。这帮了大忙!
    【解决方案2】:

    这是一个通过dplyr 的方法:

    df %>% 
      group_by(id) %>%
      mutate(status_change = status - lead(status)) %>%
      filter(status_change == 1)
      id       date status status_change
    1  1 2014-06-23      1             1
    2  2 2014-06-21      1             1
    3  3 2014-06-21      1             1
    4  3 2014-06-23      1             1
    5  4 2014-06-20      1             1
    

    这利用了status 作为数字变量的优势。 lead() 访问下一个值;当动物消失时变化为1。

    【讨论】:

    • 之前没见过lead用过,非常好用。为避免向数据集添加新列,您可以在 filter:filter(status - lead(status) == 1) 中进行数学运算。
    • @AndrewMacDonald,您的解决方案非常有用,因为它可以识别动物消失之前的所有日子,而不仅仅是第一个事件。再次感谢您!
    猜你喜欢
    • 2019-02-08
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 2013-07-19
    • 2022-01-03
    • 1970-01-01
    相关资源
    最近更新 更多