计算两个posixCT日期之间因素变量的出现

时间:2019-02-26 02:33:51

标签: r date count lubridate

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

  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,类别都是因素。非常感谢!

2 个答案:

答案 0 :(得分:0)

我这样做的方法是循环。运行时很高,但是可以正常运行。 首先是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)来查看结果,也可以只查看整个数据集。

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

答案 1 :(得分:0)

在r中使用循环通常是次优的想法,因为任何中等数据集都会陷入困境。如果您对此感兴趣,请在其他堆栈溢出答案中指定原因。 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)