【问题标题】:Count occurrences of a factor variable between two posixCT dates计算两个 posixCT 日期之间因子变量的出现次数
【发布时间】:2019-07-19 12:43:18
【问题描述】:

我有一个大型数据框,其中每一行代表一个事件的单个实例。为便于说明,请考虑包含以下五列的数据框:

  1. 事件发生的日期和时间
  2. 事件的日期和时间 + 2 小时
  3. 事件的日期和时间 - 2 小时
  4. 事件所在城市
  5. 事件类型

请参阅下面的可重现示例。

library(dplyr)
library(lubridate)
set.seed(5567)

df <- data.frame(time = sample(seq(as.POSIXct('2019/01/10'), 
                                   as.POSIXct('2019/01/20'), 
                                   by="15 mins"), 100))

df <- mutate(df,
             two.Before = df$time - hours(2),
             two.After = df$time + hours(2),
             loc = sample(c("New York", "Boston", "Atlanta", "Chicago"), 100, 
                          replace=TRUE) %>% as.factor,
             type = sample(c("Bus", "Car"), 100, 
                           replace=TRUE) %>% as.factor)

head(df)

对于每个实例,我需要创建两个新列:

  1. 一列,其中包含在事件发生前两小时和事件发生后两小时内在该同一城市发生的实例数。
  2. 一个类似的列,其中统计了在该同一个城市发生的公共汽车事故和仅公共汽车事故的数量,在之前和之前的两个小时内事件发生两小时后。

如果有人可以提供帮助,将不胜感激。我的日期都是 posixCt 并且类别都是因素。非常感谢!

【问题讨论】:

    标签: r date count lubridate


    【解决方案1】:

    我的做法是使用循环。运行时间相当长,但它工作正常。 首先是col1,它在同一城市的+-2 小时内发生。 注意:循环中的最后一行是-1,这是为了消除第一次观察的重复计算。 第二个是col2,它的作用与上述相同,但也包括 type = "Bus"。 注意:循环中的最后一行 -1 这样做是为了消除第一次观察的重复计数(与第一个循环有点不同,因为我们首先需要确保有多个观察,因为并非所有类型都是“公共汽车”)。

    df$col1<-0
    for (i in 1:nrow(df)){
      for (j in 1:nrow(df)){
        if (hour(df[i,]$time)==hour(df[j,]$time) & df[i,]$loc==df[j,]$loc) 
          {df[i,]$col1<-df[i,]$col1+1}
        else if ((hour(df[i,]$time)-hour(df[j,]$time))<2 & (hour(df[i,]$time)-hour(df[j,]$time))>(-2) & df[i,]$loc==df[j,]$loc)
          {df[i,]$col1<-df[i,]$col1+1}
      }
      df[i,]$col1<-df[i,]$col1-1
    }
    
    
    df$col2<-0
    for (i in 1:nrow(df)){
      for (j in 1:nrow(df)){
        if (hour(df[i,]$time)==hour(df[j,]$time) & df[i,]$loc==df[j,]$loc & df[j,]$type=="Bus")
          {df[i,]$col2<-df[i,]$col2+1}
        else if ((hour(df[i,]$time)-hour(df[j,]$time))<2 & (hour(df[i,]$time)-hour(df[j,]$time))>(-2) & 
                 df[i,]$loc==df[j,]$loc & df[j,]$type=="Bus")
          {df[i,]$col2<-df[i,]$col2+1}
      }
      if (df[i,]$col2>0){df[i,]$col2<-df[i,]$col2-1}
    }
    

    您可以输入head(df) 来查看结果或只查看整个数据集。

    如果您对代码的任何部分有任何疑问,请告诉我。

    【讨论】:

    • 嘿数据 Sharkie,感谢您的帮助。出于某种原因,您的代码没有为我运行。当我尝试运行它时收到此消息:“$&lt;-.data.frame(*tmp*, "col2", value = numeric(0)) 中的错误:替换有 0 行,数据有 1"
    • 嘿@DJC!所以你必须运行你的代码,然后在底部添加我的代码。我刚刚在我的电脑上测试了完整的代码,它工作正常。
    • 继续尝试但没有骰子:(
    • @DJC Pete M 上面的解决方案没有准确计算,因为它考虑了实际日期。如果您只想关注几个小时的观察而不是日期,您需要修剪数据以仅查看晚上 10 点、晚上 11 点等时间(不是 2017 年 9 月 10 日晚上 10 点;2017 年 9 月 17 日晚上 11 点)。
    • @DJC 我在您提到的代码中发现了一个错误,我在其中一行中打错了字。代码现已更新。请尝试运行它并告诉我。
    【解决方案2】:

    在 r 中使用循环通常是一个次优的想法,因为任何适度的数据集都会陷入困境。如果您有兴趣,请在其他 Stack Overflow 答案中指定原因。 r 中的最佳实践是,如果您正在考虑使用 for 循环遍历数据框中的所有记录,请改用函数的 apply family

    我在下面编写了一些快速代码,它应该可以相当快地完成任务,并且基于您提供的代码构建。

    df$row <- rownames(df)
    
    #Column 1: count occurrences +/- 2hrs within same city
    df$col1 <- mapply(function(time, city, row) sum(df[df$row != row,"two.Before"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city), 
                  df$time, df$loc, df$row)
    
    #Column2: count occurrences +/- 2hrs within same city and on a bus
    df$col2 <- mapply(function(time, city, bus, row) sum(df[df$row != row,"two.Before"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city & df[df$row != row,"type"] == "Bus"), 
                  df$time, df$loc, df$type, df$row)
    
    #Remove row index
    df <- subset(df, select = -c(row))
    

    如果您有任何问题,请告诉我。对于我测试的一些数据点,它似乎按预期工作。这假设您不想在两次计数中计算该行,否则所有 col1 计数将为 1。

    编辑

    仅在事件发生前两小时查看的代码如下(再次基于提供的代码构建)。

    df$row <- as.numeric(rownames(df))
    
    #Column 1: count occurrences +/- 2hrs within same city
    df$col1 <- mapply(function(time, city, row) sum(df[df$row != row,"time"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city), 
                  df$time, df$loc, df$row)
    
    #Column2: count occurrences +/- 2hrs within same city and on a bus
    df$col2 <- mapply(function(time, city, bus, row) sum(df[df$row != row,"time"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city & df[df$row != row,"type"] == "Bus"), 
                  df$time, df$loc, df$type, df$row)
    

    【讨论】:

    • 非常感谢皮特。你是一个传奇。在这里帮了我很大的忙:)
    • 不用担心,很高兴为您提供帮助。正如 Data Sharkie 指出的那样,我将您的问题解释为 df$time 列中日期和时间的 +/- 2 小时。如果这不正确,请告诉我,我会更新代码以反映这一点。
    • 嗨皮特。关于这个的最后一个问题。我突然意识到,如果我们试图预测某个未来的事件,我们将无法获得事件发生后两个小时内发生次数的信息!我尝试但未能修改您的代码以仅在事件发生前两个小时进行计数。有没有机会帮助我:)?
    • 您好 DJC,我已将答案编辑为仅包括事件发生前的两个小时,但其他规则保持不变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 2019-07-06
    • 2013-03-01
    • 1970-01-01
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多