R data.table 合并/完全外连接与 na.fill / nomatch 基于公式

Posted

技术标签:

【中文标题】R data.table 合并/完全外连接与 na.fill / nomatch 基于公式【英文标题】:R data.table merge / full outer join with na.fill / nomatch based on formula 【发布时间】:2013-08-21 07:23:57 【问题描述】:

我需要的是使用某种智能 na.fill / nomatch 以有效的方式执行完全外连接。我已经使用循环完成了它,但我想使用矩阵代数或 data.table 操作来加快这个过程。

下面的数据是股票未结订单信息的样本,在询价未结订单和投标未结订单数据集之间执行完全外连接。 A 数据集是询价,B 是出价。两个数据集都存储原子顺序及其累积和。任务是按累计值将所有卖单与买单匹配,反之亦然。 填充示例数据:

price = c(11.25,11.26,11.35,12.5,14.2)
amount = c(1.2,0.4,2.75,6.5,15.2)
A <- data.table(ask_price = price, ask_amount = amount, ask_cum_amount = cumsum(amount), cum_value = cumsum(price*amount), ask_avg_price = cumsum(price*amount)/cumsum(amount))
price = c(11.18,11.1,10.55,10.25,9.7)
amount = c(0.15,0.6,10.2,3.5,12)
B <- data.table(bid_price = price, bid_amount = amount, bid_cum_amount = cumsum(amount), cum_value = cumsum(price*amount), bid_avg_price = cumsum(price*amount)/cumsum(amount))

常规全外连接及其结果:

setkey(A, cum_value)
setkey(B, cum_value)
C <- merge(A,B,all=TRUE)
print(C)

na.fill / nomatch 伪代码公式,对于 cum_value 不匹配的每一行(询问或出价)(请记住,除 cum_value 之外的所有其他字段都与询问或出价有关):

avg_price["current NA"] <- cum_value["last non NA"]/cum_value["current NA"] * avg_price["last non NA"] + (1-cum_value["last non NA"]/cum_value["current NA"]) * price["next non NA"]
cum_amount["current NA"] <- cum_value["current NA"] / avg_price["current NA"]

预期结果:

D <- data.table(
  cum_value = c(1.677,8.337,13.5,18.004,49.2165,115.947,130.4665,151.822,268.222,346.3065),
  ask_price = c(NA,NA,11.25,11.26,11.35,NA,12.5,NA,NA,14.2),
  ask_amount = c(NA,NA,1.2,0.4,2.75,NA,6.5,NA,NA,15.2),
  ask_cum_amount = c(0.149066666666667,0.741066666666667,1.2,1.6,4.35,9.66496172396059,10.85,12.3126600707381,20.4097766460076,26.05),
  ask_avg_price = c(11.25,11.25,11.25,11.2525,11.31414,11.9966331281534,12.02456,12.3305605066459,13.1418390633132,13.29392),
  bid_price = c(11.18,11.1,NA,NA,NA,10.55,NA,10.25,9.7,NA),
  bid_amount = c(0.15,0.6,NA,NA,NA,10.2,NA,3.5,12,NA),
  bid_cum_amount = c(0.15,0.75,1.23858478466587,1.66517233847558,4.6230572556498,10.95,12.3652404387114,14.45,26.45,NA),
  bid_avg_price = c(11.18,11.116,10.8995364444444,10.8120940902022,10.6458772362927,10.58877,10.5510685899445,10.50671,10.14072,NA)
)
print(D)

请注意,在预期结果中最后一个 NA 仍为 NA,这是因为市场深度不足以完成任何价格的订单,无法匹配相反的订单。

是否有可能使用矩阵代数或 data.table 操作或任何其他有效的方法来避免循环整个数据集?

提前致谢

【问题讨论】:

您的公式使用了avg_priceprice,您的任何data.tables 中都不存在这两个。你能澄清一下吗? @Arun,计算 ask_avg_price 的公式使用 ask_,计算 bid_avg_price 的公式使用 bid_,只有 cum_value 字段对两个集合都是通用的,不应以 ask/bid in 作为前缀公式。 【参考方案1】:

再次将其与ABroll 合并,以查找最后/下一个非北美价格。

例如查看这两个合并的bid_avg_price 的输出值:

B[merge(A, B, all = T), roll = Inf]
B[merge(A, B, all = T), roll = -Inf]

这应该为您提供计算这些数量所需的所有信息。

【讨论】:

谢谢您,使用您的建议,我能够:1. 使用 unique(c(A_key,B_key)) 连接 A 和 B,2. 为 A 和 B 执行自连接以获得 prev non -NA 和下一个非 NA,3. 合并已经 NA 填充的 A 和 B 并获得预期结果。 Cpu时间非常出色。代码是第 15 行,看起来不够可读。我觉得还是可以改进的。休息几周后,阅读起来会很困难。无论如何,谢谢,获得了一些新技能! @MusX 例如,如果订单簿被交叉(如在拍卖中)并且您正在找到最大化成交量的价格(未交叉价格),我会理解此操作。但是在这个例子中,这本书没有被交叉:最好的出价 @MatthewDowle,如示例中所示,订单簿中的要价/出价没有交叉,如果它们被交叉,它们将不会列在订单簿中,而是在过去的交易中列出(已完成的订单)。该操作的重点是将要价与出价和出价与要价通过其 cum 值进行匹配。此操作的结果是 avg_price(cum_value) 公式 (ask_avg_price(cum_value)+bid_avg_price(cum_value))/2,这个 avg_price 显示了未结订单在其累积值中的分布。我很高兴听到关于我的逻辑的评论,这是一种没有金融知识背景的 DIY。 @MusX 是的,每天都有可能并观察到交叉书(出价>要价)......在拍卖中(当日拍卖通常针对流动性较低的股票,或所有股票的收盘拍卖,取决于市场上)。我想我明白你想做什么,但我不明白你为什么要这样做。拍卖的收盘价(未交叉价格)与您所描述的非常相似(但在拍卖中图书的交叉部分)。你确定不想这样做吗? @MatthewDowle,1. 我的假设是交叉账本是不可能的(我无法在比特币市场上观察到这种情况 - 一种外汇货币兑换)。 2. 为什么:我想使用 avg_price(cum_value) 作为买入/卖出信号的指标/因素。下图与我的逻辑密切相关:i.imgur.com/jnOenMx.png X 轴:价格,Y 轴:cum value,橙线:bid_avg_price,蓝线:ask_avg_price,绿线:过去的交易 - 忽略这个,图上只有 ask_avg_price 和bid_avg_price 两者都没有 avg_price。

以上是关于R data.table 合并/完全外连接与 na.fill / nomatch 基于公式的主要内容,如果未能解决你的问题,请参考以下文章

在双错误类型的连接列中使用 NA 的 data.table 内部/外部连接?

在双错误类型的连接列中使用 NA 的 data.table 内部/外部连接?

使用 data.table 存储为列表元素的多个数据帧的完全外连接

R data.table-删除与给定边距相对应的行

R语言dataframe(data.table)使用用最近的前一个非NA值向前填充缺失值NA实战

从R中的data.table中删除带有NA的行[重复]