获取一天内的事件总和

Get sum of events in one day

我有一个如下所示的数据集(15 年的数据),包含半小时间隔数据和事件的发生(1 表示发生了,0 表示没有发生)

Date                    Event
2002-04-27 19:30:00      0
2002-04-27 20:00:00      0
2002-04-27 20:30:00      0
2002-04-27 21:00:00      0
2002-04-27 21:30:00      1
2002-04-27 22:00:00      1
2002-04-27 22:30:00      0
2002-04-27 23:00:00      0
2002-04-27 23:30:00      1
2002-04-28 00:00:00      1
2002-04-28 00:30:00      1
2002-04-28 01:00:00      1
2002-04-28 01:30:00      0
2002-04-28 02:00:00      0
2002-04-28 02:30:00      0
2002-04-28 03:00:00      0
2002-04-28 03:30:00      0
2002-04-28 04:00:00      0
2002-04-28 04:30:00      0
2002-04-28 05:00:00      0
2002-04-28 05:30:00      0
2002-04-28 06:00:00      0
2002-04-28 06:30:00      0
2002-04-28 07:00:00      0

我想做的是计算每天(例如2002-04-27)发生的事件数。但是,连续的 1 意味着这只是一个事件,而且 1 跨越一天,例如 2002-04-27 21:30:00 有一个 1,2002-04-28 00:00:00 也是 1,但这将被视为仅发生在2002-04-27。像下面这样的输出是理想的。

Date           No_Event
2002-04-27       2
2002-04-28       0

那么,我该怎么做呢?非常感谢任何帮助。

先做一个"day"栏目

dat$day <- strftime(x = dat$Date, format = "%D") # try %F as well

找到连续的 1 并只保留第一个

for(i in nrow(dat):2) {
  if(dat$Event[i]==1 && dat$Event[i-1]==1)
      dat$Event[i] <- 0
}

然后汇总结果

by(data = dat$Event, INDICES = dat$day, FUN = sum)

dat$day: 04/27/02
[1] 2
-----------------------------------------------------------------
dat$day: 04/28/02
[1] 0

使用lubridate(按天分组)和data.table

library(data.table)
library(lubridate)
setDT(df)
df[Event!=shift(Event, fill=0), sum(Event), by=floor_date(Date, unit="day")]

#   floor_date V1
#1: 2002-04-27  2
#2: 2002-04-28  0

df 用于上例

 df <- data.frame(Date=seq(as.POSIXct("2002-04-27 19:30:00 ", tz="GMT"), as.POSIXct("2002-04-28 07:00:00 ", tz="GMT"), by="30 min"),
                     Event=c(0L, 0L, 0L, 0L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L))

这里有几种不同的方法:

1) base 这是一个基本的解决方案。首先,我们创建一个逻辑向量,如果当前事件为 1 且先前事件为 0(当 diff == 1 时发生),则该向量为 TRUE,然后我们按 Date:

求和
No_Events <- tapply(diff(c(0, df$Event)) == 1, as.Date(df$Date), sum)

给予:

> No_Events
2002-04-27 2002-04-28 
         2          0 

如果输出数据框很重要,请尝试 as.data.frame(No_Events)data.frame(Date = as.Date(names(No_Events)), No_Event = unname(No_Events))

1a) 这是一个使用 aggregate 而不是 tapply 的变体,我们首先创建一个包含 tr 的数据框 Date 列只有日期和一个 No_Event 列标记任何前面没有 1 的 1。然后我们执行 aggregate:

tr <- transform(df, No_Event = diff(c(0, df$Event)) == 1, Date = as.Date(Date))
aggregate(No_Event ~ Date, tr, sum)

给予:

        Date No_Event
1 2002-04-27        2
2 2002-04-28        0

2) zoo 这是动物园解决方案。将数据框读入动物园对象,将其与 diff==1 适当填充的列合并,然后 aggregate:

library(zoo)
z <- read.zoo(df, tz = "")
m <- merge(z, No_Event = diff(z) == 1, fill = coredata(z[1]))
z.ag <- aggregate(m, as.Date(format(time(z))), sum)

给予:

> z.ag
           z No_Event
2002-04-27 3        2
2002-04-28 3        0

忽略 z 列或通过 z.ag[, -1]z.ag[, -1, drop = FALSE] 删除它。