我想将洪水事件ID分配给我的流量时间序列,并使用data.table
的分组奇妙聚合(在我的情况下为事件ID)进行进一步分析。在进行任何分析之前,我已经尝试过在一个小的虚拟数据上进行尝试。这是我尝试过的。
加载data.table
库
library(data.table)
为测试创建一个小型数据集
d <- seq.Date(as.Date("1979-03-01"), as.Date("1979-04-30"), 1)
DT <- data.table(Date = d, Value = 1:length(d))
列表DT
:
DT[]
Date Value
1: 1979-03-01 1
2: 1979-03-02 2
3: 1979-03-03 3
4: 1979-03-04 4
5: 1979-03-05 5
---
57: 1979-04-26 57
58: 1979-04-27 58
59: 1979-04-28 59
60: 1979-04-29 60
61: 1979-04-30 61
创建一个包含事件ID的查找表
s <- as.Date(c("1979-03-14", "1979-03-29", "1979-04-16"))
e <- as.Date(c("1979-03-19", "1979-04-11", "1979-04-24"))
look_up <- data.table(Event = paste0("#", 1:3), Start = s, End = e)
print
look_up
data.table:
look_up[]
Event Start End
1: #1 1979-03-14 1979-03-19
2: #2 1979-03-29 1979-04-11
3: #3 1979-04-16 1979-04-24
Strat
和End
列上的设置键:
setkeyv(look_up, c("Start", "End"))
添加一个新列TMP
,其值与DT中的Date
相同:
DT[, TMP := Date]
执行重叠联接以在每个事件ID中生成时间序列:
Z <- foverlaps(DT,
look_up,
by.x = c("Date", "TMP"),
by.y = c("Start", "End"),
type = "within",
nomatch = 0)
删除TMP
列并查看结果:
Z[, TMP := NULL]
Z[]
Event Start End Date Value
1: #1 1979-03-14 1979-03-19 1979-03-14 14
2: #1 1979-03-14 1979-03-19 1979-03-15 15
3: #1 1979-03-14 1979-03-19 1979-03-16 16
4: #1 1979-03-14 1979-03-19 1979-03-17 17
5: #1 1979-03-14 1979-03-19 1979-03-18 18
6: #1 1979-03-14 1979-03-19 1979-03-19 19
7: #2 1979-03-29 1979-04-11 1979-03-29 29
8: #2 1979-03-29 1979-04-11 1979-03-30 30
9: #2 1979-03-29 1979-04-11 1979-03-31 31
10: #2 1979-03-29 1979-04-11 1979-04-01 32
11: #2 1979-03-29 1979-04-11 1979-04-02 33
12: #2 1979-03-29 1979-04-11 1979-04-03 34
13: #2 1979-03-29 1979-04-11 1979-04-04 35
14: #2 1979-03-29 1979-04-11 1979-04-05 36
15: #2 1979-03-29 1979-04-11 1979-04-06 37
16: #2 1979-03-29 1979-04-11 1979-04-07 38
17: #2 1979-03-29 1979-04-11 1979-04-08 39
18: #2 1979-03-29 1979-04-11 1979-04-09 40
19: #2 1979-03-29 1979-04-11 1979-04-10 41
20: #2 1979-03-29 1979-04-11 1979-04-11 42
21: #3 1979-04-16 1979-04-24 1979-04-16 47
22: #3 1979-04-16 1979-04-24 1979-04-17 48
23: #3 1979-04-16 1979-04-24 1979-04-18 49
24: #3 1979-04-16 1979-04-24 1979-04-19 50
25: #3 1979-04-16 1979-04-24 1979-04-20 51
26: #3 1979-04-16 1979-04-24 1979-04-21 52
27: #3 1979-04-16 1979-04-24 1979-04-22 53
28: #3 1979-04-16 1979-04-24 1979-04-23 54
29: #3 1979-04-16 1979-04-24 1979-04-24 55
Event Start End Date Value
计算每个事件的平均值(基于事件ID)并打印结果:
Z[, .(Average = mean(Value)), by = Event][]
Event Average
1: #1 16.5
2: #2 35.5
3: #3 51.0
上述小型虚拟数据集的结果正是我实际流量时间序列所需要的。但是,使用实际数据遇到了一些意外的结果。让我通过尝试一小部分真实流量数据来说明我的问题。可以从我的保管箱下载该数据集(格式为data.frame
的常规rds
)(文件大小:15K)20-minute flow data
一旦此flow_data.rds
位于工作文件夹中,我可以通过以下方式加载它:
flow_data <- readRDS("flow_data.rds")
将data.frame
转换为data.table
对象:
setDT(flow_data)
对于此数据集,我已经确定了三个流事件(流值大于180),并且可以以data.table
格式手动创建查找表:
event_id <-
data.table(
Event = paste0("#", 1:3),
Start = as.POSIXct(
c(
"1968-04-19 15:20:00",
"1968-04-25 15:40:00",
"1968-06-07 15:00:00"
),
tz = "Etc/GMT-12",
format = "%Y-%m-%d %H:%M:%S"
),
End = as.POSIXct(
c(
"1968-04-24 07:20:00",
"1968-04-27 05:40:00",
"1968-06-10 21:20:00"
),
tz = "Etc/GMT-12",
format = "%Y-%m-%d %H:%M:%S"
)
)
显示此event_id
数据表。
event_id[]
Event Start End
1: #1 1968-04-19 15:20:00 1968-04-24 07:20:00
2: #2 1968-04-25 15:40:00 1968-04-27 05:40:00
3: #3 1968-06-07 15:00:00 1968-06-10 21:20:00
在flow_data中添加与“时间”列具有相同值的新列:
flow_data[, TMP := Time]
设置event_id
data.table
的键:
setkeyv(event_id, c("Start", "End"))
使用event_id
重叠加入flow_data
并仅将流时间序列(行)保持在每个事件ID周期内:
flood_timeseries = foverlaps(flow_data,
event_id,
by.x = c("Time", "TMP"),
by.y = c("Start", "End"),
type = "within",
nomatch = 0)
删除不需要的TMP列:
flood_timeseries[, TMP := NULL]
现在,我得到了一些意外的结果。通过检查flood_timeseries
data.table,我发现:
flood_timeseries[1:435]
Event Start End Time Flow
1: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 15:20:00 180.595
2: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 15:40:00 184.468
3: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 16:00:00 188.342
4: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 16:20:00 192.215
5: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 16:40:00 196.088
---
431: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-25 14:40:00 174.323
432: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-25 15:00:00 176.366
433: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-25 15:20:00 178.410
434: #2 1968-04-25 15:40:00 1968-04-27 05:40:00 1968-04-25 15:40:00 180.454
435: #2 1968-04-25 15:40:00 1968-04-27 05:40:00 1968-04-25 16:00:00 182.498
我的第一个事件应该以{{1}}结束,而不是如上所述的1968-04-24 07:20:00
。
同样,#2事件的结束时间也是错误的;事件2的结束时间应为1968-04-25 15:20:00
,而不是1968-04-27 05:40:00
,如下所示:
1968-06-07 14:40:00
所有三个事件的开始时间似乎都可以,但是事件1和2的情况并非如此(事件3的结束时间似乎可以)。
我列出了虚拟数据和真实数据子集之间的主要区别:
flood_timeseries[1:3529]
Event Start End Time Flow
1: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 15:20:00 180.595
2: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 15:40:00 184.468
3: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 16:00:00 188.342
4: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 16:20:00 192.215
5: #1 1968-04-19 15:20:00 1968-04-24 07:20:00 1968-04-19 16:40:00 196.088
---
3525: #2 1968-04-25 15:40:00 1968-04-27 05:40:00 1968-06-07 14:00:00 170.283
3526: #2 1968-04-25 15:40:00 1968-04-27 05:40:00 1968-06-07 14:20:00 174.938
3527: #2 1968-04-25 15:40:00 1968-04-27 05:40:00 1968-06-07 14:40:00 178.622
3528: #3 1968-06-07 15:00:00 1968-06-10 21:20:00 1968-06-07 15:00:00 182.292
3529: #3 1968-06-07 15:00:00 1968-06-10 21:20:00 1968-06-07 15:20:00 185.963
用于我的真实数据,而不是虚拟数据集的POSIXct
类Date
)我想通过应用NA
函数为我的流程时间序列分配事件ID时做错了什么。我有非常大的数据集,其中包含多个流场数据。如果可能,使用data.table::foverlaps()
比foverlaps
循环快得多。有人可以帮我吗?
我正在使用for
上运行的data.table 1.12.0
。
非常感谢。