1

我有一个项目数据框,其中包含在不同时间发生的一定数量的不同事件。例如,说我在各种足球比赛中有过几次事件(进球、角球、红牌等)。我想计算每场比赛中每支球队在特定时间之前发生的每个事件的数量(每场比赛的时间不同)。

所以我可以有一个事件数据框(其中 C 是角球,G 是球门,R 是红牌),如下所示:

events <- data.frame(
            game_id = c(1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   2,   2),
            team    = c(1,   1,   2,   1,   2,   2,   1,   1,   2,   2,   2,   1,   1),
            event_id= c('C', 'C', 'C', 'G', 'C', 'R', 'C', 'C', 'C', 'C', 'G', 'G', 'C'),
            time    = c(5,   14,   27,  67,  78,  87, 10,  19,  33,  45,  60,  78,  89))

和另一个时间数据框来查找每个事件,如下所示:

eventTime <- data.frame(
             game_id = c(1, 2),
             time    = c(45, 65))

因此,对于第 1 场比赛,我想在第 45 分钟之前计算每支球队的每个事件的数量,而对于第 2 场比赛,我想做同样的事情,但在第 60 分钟,所以返回如下内容:

game_id time t1_C t1_G t1_R t2_C t2_G t2_R
    1    45   2    0     0   1    0     0
    2    65   2    0     0   2    1     0

由于在第1场比赛中,第1队在第45分钟前有2个角球,0进球和0张红牌,而第2队有1个角球,0进球和0张红牌。

我一直在通过使用 apply 来遍历和子集我之后的数据并计算行数来做到这一点,但是我有 1000 行,这需要很多时间。

有谁知道这样做的最快方法?

编辑:我没有提到任何 game_id 都可能在 eventTime 数据帧中以不同的时间出现多次。例如,game_id 可能出现两次,时间分别为 45 和 70,我想为每个独特的事件/时间组合获得适当的计数。

4

3 回答 3

2

一步一步地运行这个来理解,我认为这应该会给你预期的结果。此外,如果您愿意,还有减少代码的空间 -

library(data.table)
library(reshape)
library(reshape2)

events <- data.table(events)
eventTime <- data.table(eventTime)
eventTime[,TimeLimit := time]

setkeyv(eventTime,c('game_id','time'))
setkeyv(events,c('game_id','time'))

eventsSubset <- eventTime[events, roll = -Inf][!is.na(TimeLimit)]

eventsSubset <- eventsSubset[,list(Freq = .N), by = c('team','event_id','game_id','TimeLimit')]

eventsReshaped <- cast(eventsSubset, game_id + TimeLimit ~ event_id+team, fun.aggregate = sum, value = "Freq")

输出

> eventsReshaped 
  game_id TimeLimit C_1 C_2 G_2
1       1        45   2   1   0
2       2        65   2   2   1

PS-这假设在您的整个数据集中,每种类型的事件至少会发生一次。此特定代码的输出仅聚合找到的事件,这就是结果不包含所有事件团队组合的原因。如果您想确保不会发生这种情况,您可以向原始数据集添加虚拟条目。

于 2013-10-10T13:49:41.390 回答
1

感谢你们俩,我认为你们的两个答案都可以回答我最初的问题,但对于编辑后的问题不太适用。但是,我结合了您的两个答案的部分内容,以获得对我有用的东西。

我使用了 Ben Bolkers 答案的第一部分,方法是合并数据帧并在时间小于 stopTime 的地方设置子集。然后转换为数据表并使用 Coderemifa 答案的最后两行。所以如下

library(reshape)
library(reshape2)
library(plyr)
names(eventTime)[2] <- "stopTime"
events <- merge(events,eventTime)
e2 <- subset(events,time<stopTime)
eventsSubset <- data.table(e2)
eventsSubset <- eventsSubset[,list(Freq = .N), by=c('team','event_id','game_id','stopTime')]
eventsReshaped <- cast(eventsSubset, game_id + stopTime~ event_id+team, fun.aggregate = sum, value = "Freq")
于 2013-10-10T15:31:53.940 回答
1

这将有助于将事件时间重命名为不同于“时间”的名称:

names(eventTime)[2] <- "stopTime"

将停止时间合并到主数据集中:

events <- merge(events,eventTime)

加载有用的包:

library(reshape2)
library(plyr)

保留停止时间之前的事件的子集:

e2 <- subset(events,time<stopTime)

创建一个游戏 * 团队 * 事件表并将其“融化”为长格式:

m2 <- melt(with(e2,table(game_id,team,event_id)))

重新排列为您喜欢的宽格式:

m3 <- dcast(m2,game_id~team+event_id)

将停止时间放回结果中:

merge(eventTime,m3)
于 2013-10-10T14:00:28.667 回答