在R中,如何根据日期和时间格式的小时基数将一个时间段的一行拆分为多行

在R中,如何根据日期和时间格式的小时基数将一个时间段的一行拆分为多行,r,R,如何在R中完成以下任务 df <- tribble( ~ID, ~StartTime, ~EndTime , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00" , 02, "2018-05-14 21:30:00", "2018-05-15 02:00:00" , 03, "

如何在R中完成以下任务

df <- tribble(
    ~ID,         ~StartTime,              ~EndTime    
    , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00"
    , 02, "2018-05-14 21:30:00", "2018-05-15 02:00:00"
    , 03, "2018-05-15 07:00:00", "2018-05-16 22:30:00"
    , 04, "2018-05-16 23:00:00", "2018-05-16 23:40:00"
    , 05, "2018-05-17 01:00:00", "2018-05-19 15:00:00"
)

df$StartDate <- as.POSIXlt(df$StartDate, tryFormats = "%Y-%m-%d %H:%M:%S")
df$EndDate   <- as.POSIXlt(df$EndDate, tryFormats = "%Y-%m-%d %H:%M:%S")
后处理多行:

01, "2018-05-14 09:30:00", "2018-05-14 10:00:00"
01, "2018-05-14 10:00:00", "2018-05-14 11:00:00"
01, "2018-05-14 11:00:00", "2018-05-14 12:00:00"
01, "2018-05-14 12:00:00", "2018-05-14 12:10:00"

希望我的请求是明确的。

我们可以编写一个函数,在两个时间戳之间生成每小时一次的序列。使用
map2
我们为每对
StartTime
EndTime
调用该函数,并展开数据帧

library(dplyr)
library(lubridate)

generate_hourly_time <- function(x, y) {
   EndTime <- ceiling_date(x, 'hour')
   EndTime2 <- seq(EndTime, floor_date(y, 'hour'), 'hour')
   tibble(StartTime = c(x, EndTime2), EndTime = c(EndTime2, y))
}


df %>%
  mutate(across(-1, ymd_hms)) %>%
  #For dplyr < 1.0.0
  #mutate_at(-1, ymd_hms) %>%
  mutate(time = purrr::map2(StartTime, EndTime, generate_hourly_time)) %>%
  select(ID, time) %>%
  tidyr::unnest(time)


# A tibble: 117 x 3
#      ID StartTime           EndTime           
#   <dbl> <dttm>              <dttm>             
# 1     1 2018-05-14 09:30:00 2018-05-14 10:00:00
# 2     1 2018-05-14 10:00:00 2018-05-14 11:00:00
# 3     1 2018-05-14 11:00:00 2018-05-14 12:00:00
# 4     1 2018-05-14 12:00:00 2018-05-14 12:10:00
# 5     2 2018-05-14 21:30:00 2018-05-14 22:00:00
# 6     2 2018-05-14 22:00:00 2018-05-14 23:00:00
# 7     2 2018-05-14 23:00:00 2018-05-15 00:00:00
# 8     2 2018-05-15 00:00:00 2018-05-15 01:00:00
# 9     2 2018-05-15 01:00:00 2018-05-15 02:00:00
#10     2 2018-05-15 02:00:00 2018-05-15 02:00:00
# … with 107 more rows
库(dplyr)
图书馆(lubridate)
生成每小时\u时间%
mutate(time=purrr::map2(开始时间、结束时间、每小时生成时间))%>%
选择(ID,时间)%>%
tidyr::unnest(时间)
#A tibble:117x3
#ID开始时间结束时间
#                               
# 1     1 2018-05-14 09:30:00 2018-05-14 10:00:00
# 2     1 2018-05-14 10:00:00 2018-05-14 11:00:00
# 3     1 2018-05-14 11:00:00 2018-05-14 12:00:00
# 4     1 2018-05-14 12:00:00 2018-05-14 12:10:00
# 5     2 2018-05-14 21:30:00 2018-05-14 22:00:00
# 6     2 2018-05-14 22:00:00 2018-05-14 23:00:00
# 7     2 2018-05-14 23:00:00 2018-05-15 00:00:00
# 8     2 2018-05-15 00:00:00 2018-05-15 01:00:00
# 9     2 2018-05-15 01:00:00 2018-05-15 02:00:00
#10     2 2018-05-15 02:00:00 2018-05-15 02:00:00
#…还有107行
我希望它有用:

df <- tribble(
  ~ID,         ~StartTime,              ~EndTime    
  , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00"
  , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00"
  , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00"
  , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00"
  , 01, "2018-05-14 09:30:00", "2018-05-14 12:10:00"
  , 02, "2018-05-14 21:30:00", "2018-05-15 02:00:00"
  , 03, "2018-05-15 07:00:00", "2018-05-16 22:30:00"
  , 04, "2018-05-16 23:00:00", "2018-05-16 23:40:00"
  , 05, "2018-05-17 01:00:00", "2018-05-19 15:00:00"
)

nrow(df)

id.unique <- unique(df[,'ID'])
id.unique.numeric <- as.numeric(unlist(id.unique))

id.i <- id.unique.numeric

for (i in id.i) {
  out.pre <- subset(df, ID==i)
  name.out <- paste('df', i, '<-out.pre', sep = '')
  eval(parse(text=name.out))
}

df1
df您还可以执行以下操作:

library(tidyverse)
df %>%
  pivot_longer(-ID)%>%
  group_by(ID)%>%
  mutate(start = list(unique(c(value[1],seq(strptime(value[1],"%F %H"),
                                     value[2],"1 hour")[-1],value[2]))),
         name = NULL, value = NULL)%>%
  slice(1)%>%
  unnest(start)%>%
  mutate(end = lead(start,1,last(start)))
# A tibble: 117 x 3
# Groups:   ID [5]
      ID start               end                
   <dbl> <dttm>              <dttm>             
 1     1 2018-05-14 09:30:00 2018-05-14 10:00:00
 2     1 2018-05-14 10:00:00 2018-05-14 11:00:00
 3     1 2018-05-14 11:00:00 2018-05-14 12:00:00
 4     1 2018-05-14 12:00:00 2018-05-14 12:10:00
 5     1 2018-05-14 12:10:00 2018-05-14 12:10:00
 6     2 2018-05-14 21:30:00 2018-05-14 22:00:00
 7     2 2018-05-14 22:00:00 2018-05-14 23:00:00
 8     2 2018-05-14 23:00:00 2018-05-15 00:00:00
 9     2 2018-05-15 00:00:00 2018-05-15 01:00:00
10     2 2018-05-15 01:00:00 2018-05-15 02:00:00
# ... with 107 more rows
库(tidyverse)
df%>%
枢轴长度(-ID)%>%
分组依据(ID)%>%
mutate(start=list(惟一的(c(值[1],seq(strtime(值[1]),%F%H)),
值[2],“1小时”)[-1],值[2]),
名称=空,值=空)%>%
切片(1)%>%
unnest(开始)%%>%
突变(结束=领先(开始,1,最后(开始)))
#A tibble:117x3
#组别:ID[5]
ID起始端
1     1 2018-05-14 09:30:00 2018-05-14 10:00:00
2     1 2018-05-14 10:00:00 2018-05-14 11:00:00
3     1 2018-05-14 11:00:00 2018-05-14 12:00:00
4     1 2018-05-14 12:00:00 2018-05-14 12:10:00
5     1 2018-05-14 12:10:00 2018-05-14 12:10:00
6     2 2018-05-14 21:30:00 2018-05-14 22:00:00
7     2 2018-05-14 22:00:00 2018-05-14 23:00:00
8     2 2018-05-14 23:00:00 2018-05-15 00:00:00
9     2 2018-05-15 00:00:00 2018-05-15 01:00:00
10     2 2018-05-15 01:00:00 2018-05-15 02:00:00
# ... 还有107行

最后一行是否应为原始数据中的
12:10:00
?感谢您的查询,但当时间为23:00至1:30时,它不起作用,因为day也应得到更新。例如:1 2018-05-14 23:30:00 2018-05-15 01:10:00至2018-05-14 23:30:00 2018-05-15 00:00:00,2018-05-15 00:00:00 2018-05-15 01:00:00 2018-05-15 01:00:00 2018-05-15 01:00:00:00@abhishekjaiswal对我来说是的。请参见我显示的输出中ID=2的行,那里的日期发生了变化。它为您共享的数据提供了什么输出?要查看更改,您需要将数据分配给对象
df1%mutate(跨(-1,ymd_hms))……等
,并查看
df1
中的更改。好的,让我检查一下。感谢当我使用3.5.1中的代码时,在cross(-1,ymd_hms)中出现错误:找不到函数“cross”错误。是否有解决方法。
cross
dplyr 1.0.0
中提供。如果您的版本较旧,请使用
mutate_at(-1,ymd_hms)
library(tidyverse)
df %>%
  pivot_longer(-ID)%>%
  group_by(ID)%>%
  mutate(start = list(unique(c(value[1],seq(strptime(value[1],"%F %H"),
                                     value[2],"1 hour")[-1],value[2]))),
         name = NULL, value = NULL)%>%
  slice(1)%>%
  unnest(start)%>%
  mutate(end = lead(start,1,last(start)))
# A tibble: 117 x 3
# Groups:   ID [5]
      ID start               end                
   <dbl> <dttm>              <dttm>             
 1     1 2018-05-14 09:30:00 2018-05-14 10:00:00
 2     1 2018-05-14 10:00:00 2018-05-14 11:00:00
 3     1 2018-05-14 11:00:00 2018-05-14 12:00:00
 4     1 2018-05-14 12:00:00 2018-05-14 12:10:00
 5     1 2018-05-14 12:10:00 2018-05-14 12:10:00
 6     2 2018-05-14 21:30:00 2018-05-14 22:00:00
 7     2 2018-05-14 22:00:00 2018-05-14 23:00:00
 8     2 2018-05-14 23:00:00 2018-05-15 00:00:00
 9     2 2018-05-15 00:00:00 2018-05-15 01:00:00
10     2 2018-05-15 01:00:00 2018-05-15 02:00:00
# ... with 107 more rows