【发布时间】:2020-11-22 05:25:34
【问题描述】:
所以我正在处理具有多个数据表的项目,这些数据表按月份分隔,我需要对其进行迭代。速度在这里至关重要,除非我通过数据表函数进行大量交叉连接,否则我似乎无法将时间缩短到合理的水平。所以这是我的表:
表 1
Product Date Cost
A 8/1/2020 10
A 8/2/2020 20
A 8/3/2020 30
B 8/4/2020 15
B 8/5/2020 25
B 8/6/2020 35
和表 2:
Product Date Price
A 9/1/2020 20
A 9/2/2020 30
A 9/3/2020 40
B 9/4/2020 27
B 9/5/2020 33
B 9/6/2020 42
所以我需要遍历表 2 价格 - 表 1 成本的每个组合,并按产品进行。所以输出将是:
新表
Product Date1 Date2 Profit
A 8/1/2020 9/1/2020 10
A 8/1/2020 9/2/2020 20
...
编辑:为了澄清,新表应该继续。产品 A 应该有 27 个不同的利润(A x 3 折扣率下的 3 个日期)假设它们都高于 0。如果任何利润低于 0,那么我不希望它们作为新的一部分表。
我还有一个折扣因子,我需要将其应用于价格的每个排列,因为我们提供了相当多的折扣
Discount = c(10%,12%,18%)
我尝试过使用循环和各种使用 apply 的方式,但循环需要很长时间才能完成(几个小时,有些永远不会)。这些组合导致数百万行,但我只想保留有利可图的行,其中价格 * 折扣 > 成本,数量可能只有 10,000。
我的解决方案是交叉连接数据表以创建一个我可以对其进行矢量化的大型表,这要快得多(大约 1 分钟),但对于一些较大的表,我很快就会遇到内存限制,但事实并非如此非常可扩展。
CTbl =setkey(CTbl[,c(k=1,.SD)],k)[Price[,c(k=1,.SD)],allow.cartesian=TRUE][,k:=NULL]
CTbl[,Profit:=(Discount*Price - Cost]
CTbl = setDT(CTbl)[, .SD[Price > Cost ]]
DT = CTbl[,list(MinProfit = min(Profit)),by = Product]
当然,这非常快,但是当我真正想要的是有利可图的行时,这会浪费大量内存,当然还有持续的内存问题。
有人可以帮忙吗?我问过一些工作中的 R 用户,但他们似乎也很困惑,他们制作的循环无法接近运行上述程序所需的不到 5 分钟。如果这意味着我可以扩大规模,我不介意多花一点时间。
谢谢!
【问题讨论】:
-
为什么你只有两个日期? A 有三个成本值和三个价格,所以新表应该有三个利润。那正确吗?还有三个日期是正确的吗?
-
只有数百万行的结果需要这么长时间,这有点奇怪——R 是为处理这种大小甚至更大的数据而构建的。您是否尝试过并行化其中一些 for 循环?将它们转换为
foreach语法通常不会太。困难 -
它应该遍历表1中的日期和表2中的日期并获得每个组合,然后查看产品组的利润。所以到最后,产品 A 应该有 27 个总利润记录(8/1/2020 和 9/1/2020、8/1/2020 和 9/2/2020...到...8/6/ 2020 年和 2020 年 9 月 6 日适用于 3 个折扣率中的每一个)。如果任何利润
-
@WalkerHarrison 我已经尝试过了,但它仍然比上面的数据表解决方案花费了更长的时间。也许我的数据表循环效率低下?我做了DT[[i]]类型的循环语法,有没有更DT的方法呢?
-
也许尝试使用非 equi 连接来限制结果的数量。例如
DT2[, paste0("Disc", 1L:length(Discount)) := lapply(Discount, function(k) Price * k)] ;rbindlist(lapply(paste0("Cost<Disc", 1L:length(Discount)), function(x) DT1[DT2, on=c("Product", x)]), use.names=TRUE, fill=TRUE)。但由于它的排列,我认为你不能将结果的数量减少很多
标签: r loops data.table combinations nested-loops