在R中,如何根据日期和时间格式的小时基数将一个时间段的一行拆分为多行
如何在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, "
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