根据条件创建时间差序列

问题描述

TLDR:需要创建不同行的序列,但是时间序列有问题

我有一个数据帧列表,每个数据帧看起来都与此(df1)类似:

sector1 = data.frame(date = rep(seq.POSIXt(as.POSIXct("2001-01-01 00:00:00"),format = "%Y/%m/%d %H:%M:%s",as.POSIXct("2001-01-01  04:00:00"),format = "%Y/%m/%d  %H:%M:%s","hour"),length.out = 7),order = rep(1,length.out = 7))


sector2 = data.frame(date = rep(seq.POSIXt(as.POSIXct("2001-02-01 04:30:00"),as.POSIXct("2001-02-01  06:00:00"),order = rep(2,length.out = 7))


sector3 = data.frame(date = rep(seq.POSIXt(as.POSIXct("2001-03-01 06:30:00"),as.POSIXct("2001-03-01  10:00:00"),order = rep(3,length.out = 7))


# binding sectors
df1 = rbind(sector1,sector2,sector3) %>% distinct(date,order)

基本上,它们都有一个“订单”和一个日期(以及其他列)。我需要提取最早日期的行顺序,在该日期顺序从一种状态更改为另一种状态(最终仅返回唯一的顺序;因此,在这种情况下,我希望有3行),然后计算该状态花费的时间发生变化。出于本示例的目的,我将在单个数据帧上执行操作,但是无论答案是什么,都应意识到将使用lapply将其应用于列表。

设置repex数据框:

#adding spurIoUs row with order 3 but date that precedes order 2
df1[12,] = data.frame(date = as.POSIXct("2001-02-01 03:30:00"),order = 3)

# extracting rows of length(unique(df1$order))
df2 = df1 %>% group_by(order) %>% slice_min(order_by = date,n = 1) 

df2 =  df2 %>% arrange(date)

最初,我使用以下方法实现了这一目标,尽管速度很慢:

df2 %>% group_by(order) %>% slice_min(order_by = date,n = 1) %>% 
  as.data.frame() %>%  mutate(time_between = as.numeric(date-lag(date),units = 'hours'))

上述操作是按顺序分组,然后将第一行切片(通常对应于最早时间,通常按时间顺序)。然后,我正在计算每次订单更改之间的时间。

这是结果:

                 date order time_between
1 2001-01-01 00:00:00     1           NA
2 2001-02-01 04:30:00     2        748.5
3 2001-02-01 03:30:00     3         -1.0

尽管上面的方法在大多数情况下都有效(相当慢),但是在后续命令(在上面的示例中为3)的日期加上时间戳之前的时间戳(在上面的示例中为2)时,会出现问题。这意味着我的时间值为负(-1.0),这没有任何意义。

我想做的是不仅仅是按顺序分组,然后对第一行进行切片是一种逻辑运算,如果要提取的行的日期/时间在前一个顺序之前,它将得到丢弃并选择时间之后的第一行,在这种情况下,它将是2001-03-01 06:30:00 3

                 date order time_between
1 2001-01-01 00:00:00     1           NA
2 2001-02-01 04:30:00     2        748.5
3 2001-03-01 06:30:00     3        674.0

如前所述,我在一个数据框列表中进行了上述操作,因此是这样实现的:

lapply(list1,function(x) {x %>% group_by(order) %>% slice_min(order_by = date,n = 1) %>% ungroup()})
lapply(list1,function(x) {x %>% mutate(time_between = as.numeric(date-lag(date),units = 'hours'))})

其他示例数据框:

df1 = data.frame(datetime = as.POSIXct(c("2019-04-11 21:46:55","2019-04-13 00:19:23","2019-04-15 01:20:41","2019-04-15 04:18:12","2019-04-23 00:50:45","2019-04-22 08:44:41","2019-04-24 05:54:17","2019-04-23 07:21:36")),order = c(1,3,4,5,6,7,9,7))

解决方法

我不确定到底是哪个步骤在拖慢速度,但是从df1开始,您可以使用distinct为每个日期保留一行,然后使用lag和{{ 1}}。

as.numeric

对于数据帧列表,显然将其与library(dplyr) df1 %>% mutate(date = lubridate::ymd_hms(date)) %>% arrange(order,date) %>% distinct(order,.keep_all = TRUE) %>% mutate(time_between = as.numeric(date - lag(date),units = 'hours')) # date order only_date time_between #1 2001-01-01 00:00:00 1 2001-01-01 NA #2 2001-02-01 04:30:00 2 2001-02-01 748.5 #3 2001-03-01 06:30:00 3 2001-03-01 674.0 / lapply配合使用:

map