【问题标题】:Count events before a specific time for a series of items in R为 R 中的一系列项目计算特定时间之前的事件
【发布时间】:2013-10-10 13:38:25
【问题描述】:

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

所以我可以有一个事件数据框(其中 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 场比赛中,第 45 分钟前,第 1 队有 2 个角球,0 球和 0 张红牌,而第 2 队有 1 个角球,0 球和 0 张红牌。

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

有人知道最快的方法吗?

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

【问题讨论】:

    标签: r events time count dataframe


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢我认为这符合我的要求,但是我在最初的问题中没有提到其他一些事情(对不起,我的错,现在将编辑问题)。有一些 game_id 在 eventTime 中出现多次,例如我可以有两次game_id,一次时间= 45,一次时间= 70,对于每个事件/时间组合,我都想获得计数。我不认为上述方法可以解决这个问题?
    • 不。首先想到 - 遍历每一行 eventstime 并将输出绑定到主数据集。
    【解决方案2】:

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

    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)
    

    【讨论】:

      【解决方案3】:

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

      我使用了 Ben Bolkers 答案的第一部分,方法是合并数据帧并在 time 小于 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")
      

      【讨论】:

        猜你喜欢
        • 2017-05-21
        • 2012-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-02
        • 2021-11-06
        • 1970-01-01
        • 2016-09-18
        相关资源
        最近更新 更多