我有一分钟的金融时间序列(“酒吧”)。因为我将处理一些大型系列,我正在学习使用data.table
,而我还不习惯以data.table
方式思考。
在我导入data.table
的数据中(为简单起见,我们将其称为DT
),除了与此问题无关的其他内容之外,我还有一个名为Date
的列YYYYMMDD
格式,Time
格式的HH:MM
列,以及名为Price
的列(假设它是该分钟的最终价格),这是一个整数。我正在简化一点,但如果有人能帮助我解决我在这里提出的问题,我可以根据我的数据细节进行调整。这是一个例子:
Date Time Price
20151028 09:00 47675
20151028 09:01 47650
20151028 09:02 47670
20151028 09:03 47685
20151028 09:04 47690
...
我想要做的是,每分钟计算直到那一分钟的Price
的最大值和最小值。我们继续将我想要计算的内容添加为其他列,我将在此处调用DayMax
和DayMin
。结果将如下所示:
Date Time Price DayMax DayMin
20151028 09:00 47675 47675 47675
20151028 09:01 47650 47675 47650
20151028 09:02 47670 47675 47650
20151028 09:03 47685 47685 47650
20151028 09:04 47690 47690 47650
...
我很确定我的by
(我理解为SQL中的GROUP BY
)应该是Date
,而我认为我理解的是如何理解设置我的i
(就像SQL中的WHERE
),主要是因为我不确定如何在语法中使用相同的列两种不同的方式。对于每一行,我想计算最大值(以及“在哪里”,我认为我的意思是WHERE
)Time
小于或等于该特定值中Time
的值行,我在GROUP
(ing)BY
日期,所以它取决于该行在特定日期的时间。如何使用data.table
以快速且符合内存的方式执行此操作?
顺便说一句,谈到“快速和内存效率”,我假设我应该使用:=
运算符来创建新列。如果我错了,请纠正我。
答案 0 :(得分:2)
As suggested by Frank,cummin()
和cummax()
会为您做到这一点。 (在SQL中,这在ORACLE中称为窗口函数或分析函数,我相信)。
DT[order(Date, Time), `:=`(DayMax = cummax(Price), DayMin = cummin(Price)), by = Date]
DT
# Date Time Price DayMax DayMin
#1: 20151028 09:00 47675 47675 47675
#2: 20151028 09:01 47650 47675 47650
#3: 20151028 09:02 47670 47675 47650
#4: 20151028 09:03 47685 47685 47650
#5: 20151028 09:04 47690 47690 47650
为了确保数据的顺序正确,DT
按Date
和Time
排序。如果前面的步骤确保了这一点,则可以跳过此步骤。两个新列在一个表达式中计算,根据请求分别为每个Date
计算。
使用链接,可以将其重写为
res <- DT[order(Date, Time)][, DayMax := cummax(Price), by = Date][, DayMin := cummin(Price), by = Date][]
但缺点是创建DT
的副本而不是DT
通过引用修改,并需要额外的分组操作(感谢Frank用于指出this。
library(data.table)
DT <- fread ("Date Time Price
20151028 09:00 47675
20151028 09:01 47650
20151028 09:02 47670
20151028 09:03 47685
20151028 09:04 47690")