分离单个事件的方法

Way to separate out individual events

我有一个大型数据集,每 1/2 秒就有一次观察。它代表机器人中的一系列挤奶。因此,一头牛进入机器人并被挤奶,同时测量不同的东西。然后奶牛离开,有一段时间没有奶牛,直到另一头奶牛进来。我为我的数据的过度简化样本编写了代码。

示例数据

set.seed(66)
ID <- rep(c(84,-999,88,-999),c(5,3,7,5))
TimeStamp <- rep(c("09:31:12",NA,"09:45:31",NA),c(5,3,7,5))
VAR1 <- sample(x = 800:3000, 20)
mydf <- data.frame(ID=ID, TimeStamp=TimeStamp, VAR1 = VAR1)
eventIDs <- as.numeric(factor(mydf[, "TimeStamp"], exclude = NULL))
mydf[, "eventIDs"] <- eventIDs
mydf
#     ID TimeStamp VAR1 eventIDs
#1    84  09:31:12 2978        1
#2    84  09:31:12 2625        1
#3    84  09:31:12 2088        1
#4    84  09:31:12 1716        1
#5    84  09:31:12 2254        1
#6  -999      <NA> 1632        3
#7  -999      <NA> 1731        3
#8  -999      <NA> 2648        3
#9    88  09:45:31 1625        2
#10   88  09:45:31 2798        2
#11   88  09:45:31 1366        2
#12   88  09:45:31 1245        2
#13   88  09:45:31 1291        2
#14   88  09:45:31 2801        2
#15   88  09:45:31 2746        2
#16 -999      <NA> 1411        3
#17 -999      <NA> 1738        3
#18 -999      <NA> 1398        3
#19 -999      <NA> 1918        3
#20 -999      <NA> 1575        3

数据中的ID变量表示cow/no-cow事件。 -999是在ID == NA时决定的。 TimeStamp代表挤奶开始。此变量用于标识 eventIDs 变量。这很重要,因为在一天的过程中,奶牛可能会被多次挤奶。这就是为什么创建它是为了将每头奶牛的每个挤奶事件分开。 VAR1 表示正在调查的任何变量。

期望输出

我需要每个挤奶和每个非挤奶的 VAR1 的平均值。目前,这是我的输出:

(res1 <- aggregate(mydf[,"VAR1"],
                   by = list(ID = mydf[,"ID"], eventIDs = mydf[,"eventIDs"]),
                   FUN = mean))
#    ID eventIDs        x
#1   84        1 2332.200
#2   88        2 1981.714
#3 -999        3 1756.375

这是显而易见的结果,因为没有指示变量来分隔每个连续的 'non-milking' 事件。事实上我想要这样:

meanVAR1 <- c((2978+2625+2088+1716+2254)/5,
              (1632+1731+2648)/3,
              (1625+2798+1366+1245+1291+2801+2746)/7,
              (1411+1738+1398+1918+1575)/5) 
eventIDs <- c(1,3,2,3) 
(res2 <- data.frame(ID = ID1, meanVAR1 = meanVAR1, eventIDs = eventIDs))
#    ID meanVAR1 eventIDs
#1   84 2332.200        1
#2 -999 2003.667        3
#3   88 1981.714        2
#4 -999 1608.000        3

有什么建议吗?

假设您的数据按照您的示例中的时间顺序排序。使用 rle 创建每个事件唯一的代理 ID 非常容易:

mydf$ID2 = rep(1:length(rle(mydf$ID)$lengths),times=rle(mydf$ID)$lengths)

然后结合 aggregate 或在我的示例中 data.table 这个新 ID 将帮助我们获得所需的结果:

setDT(mydf)[,list(meanVar1=mean(VAR1)),by=c("ID","ID2","eventIDs")]
   #       ID ID2 eventIDs meanVar1
   # 1:   84 1   1        1 2332.200
   # 2: -999 2   2        3 2003.667
   # 3:   88 3   3        2 1981.714
   # 4: -999 4   4        3 1608.000

使用 devel version of data.table v1.9.5,它实现了一个新功能 rleid() 以在这些情况下使用:

require(data.table) # v1.9.5+
ans = setDT(mydf)[, .(meanVAR1 = mean(VAR1)), by=.(ID, eventIDs, rleid(ID))]    
#      ID eventIDs rleid meanVAR1
# 1:   84        1     1 2332.200
# 2: -999        3     2 2003.667
# 3:   88        2     3 1981.714
# 4: -999        3     4 1608.000

如果您不需要 rleid 列,您可以通过以下操作将其删除:

ans[, rleid := NULL]

查看 HTML vignettes 以了解更多信息。