问题描述
TLDR:需要创建不同行的序列,但是时间序列有问题
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