For循环以计算R

时间:2019-01-23 20:43:29

标签: r

我想针对每次观察计算R的时间之间的差异,因为它与公交车的到站时间和时间表有关。我到目前为止的代码是:

for (i in ida1d$DATA_TRAMA) {
   for (j in horidat$CORD4) {
       if((ida1d$DATA_TRAMA - horidat$CORD4 < ida1d$diff)) {
           ida1d$diff <- ida1d$DATA_TRAMA - horidat$CORD4
       }                    
   }            
}

我有这些数据框:

  • ida1d,其中包含我想要的具体信息
  • horidat,其中有时间表
  • ida1d$DATA_TRAMAhoridat$CORD4均为POSIXct %Y-m%-%d %H:%M:%S格式。

现在我想做的是在ida1d表中有一列,并带有不同之处。问题在于,对于前几个观察,它可以正确计算差异,但是从某个角度来看,它不能正确计算horidat(时间表)的观察数,而对于ida1d,则观察数是88我认为计算的问题可能是因为此,因此尝试使用for循环来解决问题,但是我认为我缺少了一些东西...

ida1d的日期和时间是公交车全天到达公交车站的时间:

ida1d$DATA_TRAMA
     [1] 2010-10-01 00:00:08 
         2010-10-01 00:29:45 
         2010-10-01 06:22:56            
         2010-10-01 06:38:55 
         2010-10-01 06:52:41 
         2010-10-01 07:05:08 
         2010-10-01 07:15:17 
         2010-10-01 07:25:14
         2010-10-01 07:38:25 
         2010-10-01 07:44:55 
         2010-10-01 07:54:44
         2010-10-01 08:05:05 
         2010-10-01 08:14:43 
         2010-10-01 08:24:11 
         2010-10-01 08:33:29 
         2010-10-01 08:46:26
         2010-10-01 08:54:40 
         2010-10-01 09:04:34
         2010-10-01 09:14:53 

这是公共汽车(horidat)的时间表

horidat$CORD4
 [2] 2010-10-01 00:00:00 
     2010-10-01 00:30:00 
     2010-10-01 06:25:00  
     2010-10-01 06:45:00 
     2010-10-01 07:00:00 
     2010-10-01 07:15:00 
     2010-10-01 07:30:00 
     2010-10-01 07:45:00 
     2010-10-01 07:57:00 
     2010-10-01 08:09:00 
     2010-10-01 08:21:00 
     2010-10-01 08:32:00 
     2010-10-01 08:43:00 
     2010-10-01 08:54:00 
     2010-10-01 09:06:00 
     2010-10-01 09:18:00  

我可以计算出[1]和[2]之间的差,正如我们在结果[3]下方看到的那样:

ida1d$diff
Time differences in secs
 [3]      8    
         -15   
         -124  
         -365   
         -439   
         -592   
         -883 
         -1186 
         -1115 
         -1445  
         -1576  
         -1615  
         -1697  
         -1789  
         -1951  
         -1894  
         -2120  
         -2246 

我们可以看到它从一开始就很好地开始,然后在其余的计算中都出错了,这就是我的问题,我想为每次观察获得列中差的最小值,也许它使用其他值,因此我猜是错误的计算...

2 个答案:

答案 0 :(得分:2)

我要发表评论,但没有声誉。寻找几点。

看起来一个表有事件,另一个表有某种属性?如果您可以提供有关每个表格中有哪些内容的详细信息,那将会有所帮助。

无论如何,我都会大致勾勒出我将如何处理它。通常,您要避免for循环。您可以使用联接或矢量操作,它们的性能更高。该解决方案似乎将是两个数据框之间的连接,并带有一个突变来创建差异列。如果不是这种情况,请告诉我!

# install these if you don't have them
library(dplyr)
library(magrittr)

horidat %>%
  xxxx_join(ida1d, on=c('some_column1','some_column2') %>%
  mutate(diff = as.numeric(difftime(DATA_TRAMA, CORD4, units='secs')))

xxxx_join是适当的连接,例如left_join。

答案 1 :(得分:2)

这是使用fuzzyjoin软件包的一种方法。使用data.table的方法更快,例如herehere,但是对我来说,这种方法更易于遵循,并且在必要时可以更轻松地调整匹配规则。

fuzzyjoin::difference_left_join的作用类似于基R中的mergeleft_join中的dplyr,在两个数据集之间创建了数据库样式的“联接”。在这种情况下,它将连接两个表中的相应时间戳。作为“左”连接,它将保留原始到达数据帧的每一行的至少一个副本,并为每个与CORD4足够近的匹配DATA_TRAMA计划的停靠点包括一行时间。在这种情况下,通过设置max_dist = 15*60,我们将在到达时间的15分钟(15分钟x 60秒)内获得所有计划的停靠点。这可能比您想要的要多(41个足够接近的比赛,需要19个到达时间),但是,您可以灵活地决定将哪些预定的停靠点与实际到达时间联系起来。

在这种情况下,为了选择最接近时间的计划停靠点,我使用group_by中的top_ndplyr来保留每次到达的绝对时间差最小的行。

编辑:添加了带符号的差异,并限制了对一列的连接

library(dplyr); library(fuzzyjoin)

ida1d %>% 
  # select() to bring in only CORD4 from horidat
  difference_left_join(horidat %>% select(CORD4), 
                   by = c(DATA_TRAMA = "CORD4"),
                   max_dist = 15*60, distance_col = "abs_dif") %>%
  # difference_left_join based on absolute differences
  # add signed difference
  mutate(difference = DATA_TRAMA - CORD4) %>%
  # could use filter like this to limit to only late buses:
  # filter(difference >= 0) %>%
  group_by(DATA_TRAMA) %>%
  top_n(-1, wt = difference) %>%
  ungroup()

# A tibble: 19 x 4
   DATA_TRAMA          CORD4               abs_dif  difference
   <dttm>              <dttm>              <time>   <time>    
 1 2010-10-01 00:00:08 2010-10-01 00:00:00   8 secs    8 secs 
 2 2010-10-01 00:29:45 2010-10-01 00:30:00  15 secs  -15 secs 
 3 2010-10-01 06:22:56 2010-10-01 06:25:00 124 secs -124 secs 
 4 2010-10-01 06:38:55 2010-10-01 06:45:00 365 secs -365 secs 
 5 2010-10-01 06:52:41 2010-10-01 07:00:00 439 secs -439 secs 
 6 2010-10-01 07:05:08 2010-10-01 07:00:00 308 secs  308 secs 
 7 2010-10-01 07:15:17 2010-10-01 07:15:00  17 secs   17 secs 
 8 2010-10-01 07:25:14 2010-10-01 07:30:00 286 secs -286 secs 
 9 2010-10-01 07:38:25 2010-10-01 07:45:00 395 secs -395 secs 
10 2010-10-01 07:44:55 2010-10-01 07:45:00   5 secs   -5 secs 
11 2010-10-01 07:54:44 2010-10-01 07:57:00 136 secs -136 secs 
12 2010-10-01 08:05:05 2010-10-01 08:09:00 235 secs -235 secs 
13 2010-10-01 08:14:43 2010-10-01 08:09:00 343 secs  343 secs 
14 2010-10-01 08:24:11 2010-10-01 08:21:00 191 secs  191 secs 
15 2010-10-01 08:33:29 2010-10-01 08:32:00  89 secs   89 secs 
16 2010-10-01 08:46:26 2010-10-01 08:43:00 206 secs  206 secs 
17 2010-10-01 08:54:40 2010-10-01 08:54:00  40 secs   40 secs 
18 2010-10-01 09:04:34 2010-10-01 09:06:00  86 secs  -86 secs 
19 2010-10-01 09:14:53 2010-10-01 09:18:00 187 secs -187 secs

样本数据:

ida1d = data.frame(DATA_TRAMA = as.POSIXct(
  c(
    "2010-10-01 00:00:08",
    "2010-10-01 00:29:45",
    "2010-10-01 06:22:56",
    "2010-10-01 06:38:55",
    "2010-10-01 06:52:41",
    "2010-10-01 07:05:08",
    "2010-10-01 07:15:17",
    "2010-10-01 07:25:14",
    "2010-10-01 07:38:25",
    "2010-10-01 07:44:55",
    "2010-10-01 07:54:44",
    "2010-10-01 08:05:05",
    "2010-10-01 08:14:43",
    "2010-10-01 08:24:11",
    "2010-10-01 08:33:29",
    "2010-10-01 08:46:26",
    "2010-10-01 08:54:40",
    "2010-10-01 09:04:34",
    "2010-10-01 09:14:53"
  )
))

horidat = data.frame(CORD4 = as.POSIXct(
  c(
    "2010-10-01 00:00:00",
    "2010-10-01 00:30:00",
    "2010-10-01 06:25:00",
    "2010-10-01 06:45:00",
    "2010-10-01 07:00:00",
    "2010-10-01 07:15:00",
    "2010-10-01 07:30:00",
    "2010-10-01 07:45:00",
    "2010-10-01 07:57:00",
    "2010-10-01 08:09:00",
    "2010-10-01 08:21:00",
    "2010-10-01 08:32:00",
    "2010-10-01 08:43:00",
    "2010-10-01 08:54:00",
    "2010-10-01 09:06:00",
    "2010-10-01 09:18:00"
  )
))