获取一天内的事件总和
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]
删除它。
我有一个如下所示的数据集(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]
删除它。