我从Elasticsearch系统中提取了一些数据,这些数据显示了在日期范围内员工的可用性,并按小时划分。
员工每天24小时都无法使用,但我想在24小时的时段内显示数据,其中0
填充没有数据的单元格。
我的想法是,我需要创建一个空白数据框,将结果插入其中,然后用0
填充其余数据框,但是我真的很想知道是否有更好的方法。
请注意,初始数据帧的大小并不总是相同,因为不同的日期返回不同的小时值(七个小时的时间段,三个小时的时间段,十二小时的时间段等)。
还请注意,在查询结果中没有任何命中/结果的情况下,由于没有关联数据,因此不会出现之间的小时间隔(请参见18:00
和21:00
之间)。
目前,整个数据框架如下:
hour associate_count minutes_covered
<dttm> <int> <dbl>
1 2018-08-06 10:00:00 2 37
2 2018-08-06 11:00:00 2 60
3 2018-08-06 12:00:00 2 42
4 2018-08-06 13:00:00 1 56
5 2018-08-06 14:00:00 2 60
6 2018-08-06 15:00:00 2 60
7 2018-08-06 16:00:00 2 60
8 2018-08-06 17:00:00 1 52
9 2018-08-06 18:00:00 1 0 # NOTE THAT THERE IS A 3-HOUR GAP HERE UNTIL THE NEXT HIT
10 2018-08-06 21:00:00 1 10
数据框后面的数据:
df <- structure(list(hour = structure(c(1533546000, 1533549600, 1533553200,
1533556800, 1533560400, 1533564000, 1533567600, 1533571200, 1533574800
), class = c("POSIXct", "POSIXt"), tzone = "Europe/London"),
associate_count = c(2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 1L),
minutes_covered = c(37, 60, 42, 56, 60, 60, 60, 52, 0)), row.names = c(NA,
-9L), class = c("tbl_df", "tbl", "data.frame"))
如何使数据看起来像这样?
hour associate_count minutes_covered
1 2018-08-06 00:00 0 0
2 2018-08-06 01:00 0 0
3 2018-08-06 02:00 0 0
4 2018-08-06 03:00 0 0
5 2018-08-06 04:00 0 0
6 2018-08-06 05:00 0 0
7 2018-08-06 06:00 0 0
8 2018-08-06 07:00 0 0
9 2018-08-06 08:00 0 0
10 2018-08-06 09:00 0 0
11 2018-08-06 10:00 2 37
12 2018-08-06 11:00 2 60
13 2018-08-06 12:00 2 42
14 2018-08-06 13:00 1 56
15 2018-08-06 14:00 2 60
16 2018-08-06 15:00 2 60
17 2018-08-06 16:00 2 60
18 2018-08-06 17:00 1 52
19 2018-08-06 18:00 1 0
20 2018-08-06 19:00 0 0
21 2018-08-06 20:00 0 0
22 2018-08-06 21:00 1 10
23 2018-08-06 22:00 0 0
24 2018-08-06 23:00 0 0
答案 0 :(得分:2)
您可以为此使用tidyr::complete
。如果需要,它还可以让您另外填写其他变量以扩展数据框。
library(tidyverse)
library(lubridate)
df <- structure(list(hour = structure(c(1533546000, 1533549600, 1533553200, 1533556800, 1533560400, 1533564000, 1533567600, 1533571200, 1533574800), class = c("POSIXct", "POSIXt"), tzone = "Europe/London"), associate_count = c(2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 1L), minutes_covered = c(37, 60, 42, 56, 60, 60, 60, 52, 0)), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame"))
my_complete <- function(df, start_date, end_date){
start_hour <- str_c(start_date, " 00:00:00") %>% ymd_hms
end_hour <- str_c(end_date, " 00:00:00") %>% ymd_hms
df %>%
complete(
hour = seq(from = start_hour, to = end_hour, by = "hour"),
fill = list(associate_count = 0L, minutes_covered = 0)
)
}
my_complete(df, "2018-08-06", "2018-08-07")
#> # A tibble: 25 x 3
#> hour associate_count minutes_covered
#> <dttm> <int> <dbl>
#> 1 2018-08-06 00:00:00 0 0
#> 2 2018-08-06 01:00:00 0 0
#> 3 2018-08-06 02:00:00 0 0
#> 4 2018-08-06 03:00:00 0 0
#> 5 2018-08-06 04:00:00 0 0
#> 6 2018-08-06 05:00:00 0 0
#> 7 2018-08-06 06:00:00 0 0
#> 8 2018-08-06 07:00:00 0 0
#> 9 2018-08-06 08:00:00 0 0
#> 10 2018-08-06 09:00:00 2 37
#> # ... with 15 more rows
由reprex package(v0.2.0)于2018-08-13创建。
答案 1 :(得分:0)
# create a sequence of hours for your day
allhours <- data.frame(hour=seq(from= as.POSIXct("2018-06-08 00:00"),
to = as.POSIXct("2018-06-08 23:00"),
by = "hours"))
# merge that sequence with your data (all=TRUE is important here)
res <- merge(df, allhours, by="hour", all=TRUE)
# convert NAs to Zeros
res[is.na(res$associate_count), "associate_count"] <- 0
res[is.na(res$minutes_covered), "minutes_covered"] <- 0
答案 2 :(得分:0)
我不确定100%的预期输出是多少。但是我们可能会从以下地方出发:
new_df <- data.frame(hour=seq(ymd_hms('2018-08-06 00:00:00'),
ymd_hms('2018-08-06 23:00:00'), by = '1 hour'))
现在我们可以加入旧的数据框
new_df %>% left_join(df)
Joining, by = "hour"
hour associate_count minutes_covered
1 2018-08-06 00:00:00 NA NA
2 2018-08-06 01:00:00 NA NA
3 2018-08-06 02:00:00 NA NA
4 2018-08-06 03:00:00 NA NA
5 2018-08-06 04:00:00 NA NA
6 2018-08-06 05:00:00 NA NA
7 2018-08-06 06:00:00 NA NA
8 2018-08-06 07:00:00 NA NA
9 2018-08-06 08:00:00 NA NA
10 2018-08-06 09:00:00 2 37
11 2018-08-06 10:00:00 2 60
12 2018-08-06 11:00:00 2 42
13 2018-08-06 12:00:00 1 56
14 2018-08-06 13:00:00 2 60
15 2018-08-06 14:00:00 2 60
16 2018-08-06 15:00:00 2 60
17 2018-08-06 16:00:00 1 52
18 2018-08-06 17:00:00 1 0
19 2018-08-06 18:00:00 NA NA
20 2018-08-06 19:00:00 NA NA
21 2018-08-06 20:00:00 NA NA
22 2018-08-06 21:00:00 NA NA
23 2018-08-06 22:00:00 NA NA
24 2018-08-06 23:00:00 NA NA
如果绝对必须摆脱NAs
并且您需要将它们设为零,则可以添加另一个类似%>% mutate_at(c(2:3), funs(replace(., is.na(.), 0)))
的管道术语