根据唯一的开始和结束日期 [R] 从时间序列中过滤列(将第 1 行标准化为每个列的第一天)

Filtering columns from a timeseries based on unique start and end dates [R] (to standardize row 1 as day one for each)

我正在尝试标准化 table timeseries 中列的开始日期,以便每个列都根据我在另一个 table StartEnd 中的预定义值开始. timeseries 中的 datetime 与此问题中的所有日期值一样采用 POSIXct 格式。

我如何创建一个数据框,其中每列的第一行都以 Start 处的值开头,同时还删除 End 处的 0 个值?这是在对堆叠数据集进行 spread() 之后:

timeseries <- spread(timeseries, ID, Count , fill = "0")

我研究过过滤器,但我不确定 dplyr 是否适合这里。我认为某种功能可以解决,但以我有限的知识,我不知道在这种情况下一个人的结构会是什么样子。 Jfyi 我是自学 R 的,除了一些 Coursera 课程外,没有接受过正规的编码教育。

timeseries:

    datetime          ID1 ID2 ID3 ID4 ID5 ID6 ID7
1   01/01/19 00:00:00   0   0   7   1   1   0   0
2   01/01/19 01:00:00   0   0   11  2   2   0   0
3   01/01/19 02:00:00   0   0   6   3   3   0   0
4   01/01/19 03:00:00   3   0   10  0   4   0   0
5   01/01/19 04:00:00   4   0   3   0   5   0   0
6   01/01/19 06:00:00   5   1   1   0   6   0   1
7   01/01/19 07:00:00   6   2   1   0   7   0   3
8   01/01/19 09:00:00   0   3   2   0   0   1   0
9   01/01/19 10:00:00   1   4   3   0   0   2   1

StartEnd:

SomeID   Start              End
ID1      01/01/19 03:00:00  01/01/19 10:00:00 
ID2      01/01/19 06:00:00  01/01/19 10:00:00
ID3      01/01/19 00:00:00  01/01/19 10:00:00 
ID4      01/01/19 00:00:00  01/01/19 02:00:00
ID5      01/01/19 00:00:00  01/01/19 07:00:00
ID6      01/01/19 09:00:00  01/01/19 10:00:00
ID7      01/01/19 06:00:00  01/01/19 10:00:00

预期输出:

    ID1 ID2 ID3 ID4 ID5 ID6 ID7
1   3   1   7   1   1   1   1
2   4   2   11  2   2   2   3
3   5   3   6   3   3       0
4   6   4   10      4       1
5   0       3       5       
6   1       1       6       
7           1       7       
8           2               
9           3               

我们可以得到 timeseries 的长格式,将其与 StartEnd 数据框连接,将日期时间列转换为 POSIXct 格式,filter [=] 之间的值15=] 和 End 并以宽格式获取数据。

library(dplyr)
library(tidyr)

timeseries %>%
  pivot_longer(cols = -datetime, names_to = 'SomeID') %>%
  left_join(StartEnd, by = 'SomeID') %>%
  mutate_at(vars(datetime, Start, End), lubridate::dmy_hms) %>%
  filter(datetime >= Start & datetime <= End) %>%
  select(SomeID, value) %>%
  group_by(SomeID) %>%
  mutate(row = row_number()) %>%
  pivot_wider(names_from = SomeID, values_from = value) %>%
  select(-row) %>%
  select(paste0("ID", 1:7))

# A tibble: 9 x 7
#    ID1   ID2   ID3   ID4   ID5   ID6   ID7
#  <int> <int> <int> <int> <int> <int> <int>
#1     3     1     7     1     1     1     1
#2     4     2    11     2     2     2     3
#3     5     3     6     3     3    NA     0
#4     6     4    10    NA     4    NA     1
#5     0    NA     3    NA     5    NA    NA
#6     1    NA     1    NA     6    NA    NA
#7    NA    NA     1    NA     7    NA    NA
#8    NA    NA     2    NA    NA    NA    NA
#9    NA    NA     3    NA    NA    NA    NA