gpt4 book ai didi

r - 带过滤器 data.table 的笛卡尔积

转载 作者:行者123 更新时间:2023-12-04 12:07:16 26 4
gpt4 key购买 nike

我正在尝试通过 data.table 调用替换 SQL 生成的笛卡尔积。
我在 Assets 和值(value)方面有着悠久的历史,我需要所有组合的一个子集。
假设我有一个表 a,其中 T = [date, contract, value]。在 SQL 中它看起来像

SELECT a.date, a.contract, a.value, b.contract. b.value 
FROM T a, T b
WHERE a.date = b.date AND a.contract <> b.contract AND a.value + b.value < 4

在 R 我现在有以下内容
library(data.table)

n <- 1500
dt <- data.table(date = rep(seq(Sys.Date() - n+1, Sys.Date(), by = "1 day"), 3),
contract = c(rep("a", n), rep("b", n), rep("c", n)),
value = c(rep(1, n), rep(2, n), rep(3, n)))
setkey(dt, date)

dt[dt, allow.cartesian = TRUE][(contract != i.contract) & (value + i.value < 4)]

我相信我的解决方案首先创建所有组合(在本例中为 13,500 行),然后过滤(到 3000)。然而,SQL(我可能是错的)加入子集,更重要的是不要将所有组合加载到 RAM 中。任何想法如何更有效地使用 data.table?

最佳答案

使用 by = .EACHI 功能。在 data.table 中,连接和子集非常紧密地联系在一起;即,连接只是另一个子集 - 使用 data.table - 而不是通常的整数/逻辑/行名称。它们的设计方式考虑到了这些情况。

基于子集的连接允许在连接时合并 j 表达式和分组操作。

require(data.table)
dt[dt, .SD[contract != i.contract & value + i.value < 4L], by = .EACHI, allow = TRUE]

这是惯用的方式(如果您只想将 i.* cols 用于条件,但不返回它们),但是, .SD 尚未优化,并且为每个组评估 j 上的 .SD 表达式代价高昂.
system.time(dt[dt, .SD[contract != i.contract & value + i.value < 4L], by = .EACHI, allow = TRUE])
# user system elapsed
# 2.874 0.020 2.983

Some cases using .SD have already been optimised 。在处理这些情况之前,您可以通过以下方式解决此问题:
dt[dt, {
idx = contract != i.contract & value + i.value < 4L
list(contract = contract[idx],
value = value[idx],
i.contract = i.contract[any(idx)],
i.value = i.value[any(idx)]
)
}, by = .EACHI, allow = TRUE]

这需要 0.045 秒,而不是 0.005 秒。但是 by = .EACHI 每次都会评估 j 表达式(因此内存效率高)。这是你必须接受的权衡。

关于r - 带过滤器 data.table 的笛卡尔积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27059924/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com