如何在 R 中的 data.table 中使用具有累积值的移位计算

How to use a shift calculation with a cumulative value in a data.table in R

我有一个 data.table 具有以下布局

TestData <- data.table(Threshold = 20,
                       Upto = 100,
                       Demand = c(0,0,5,0,50,10,10,10,10,50,20,60),
                       Stock  = c(100,0,0,0,0,0,0,0,0,0,0,0))

股票价值应使用以下公式计算为累计值:

If Stock (previous row) minus Demand (current row) is less or equal than the threshold, than update the current cell in Stock with the value in "Upto". Else update the value of stock (current row) with stock (previous row) minus demand (current row).

然后程序应该重新开始。结果应如下所示:

TestData <- data.table(Threshold = 20,
                       Upto = 100,
                       Demand = c(0,0,5,0,50,10,10,10,10,50,20,60),
                       Stock = c(100,100,95,95,45,35,25,100,90,40,100,40))

    Threshold Upto Demand Stock
 1:        20  100      0   100
 2:        20  100      0   100
 3:        20  100      5    95
 4:        20  100      0    95
 5:        20  100     50    45
 6:        20  100     10    35
 7:        20  100     10    25
 8:        20  100     10   100
 9:        20  100     10    90
10:        20  100     50    40
11:        20  100     20   100
12:        20  100     60    40

我所做的如下:

TestData[, Stock:= ifelse(cumsum(shift(Stock, 0, type="lead") - Demand) <= Threshold,
                     Upto,
                     cumsum(shift(Stock, 0, type="lead") - Demand))]

但在第一次更新后计算停止,每次平铺结束时显示 100。库存中的第一个值是我手动设置的初始值。谢谢!

如果您可以接受循环解决方案。我不认为这对 dplyr(或 data.table)可行,但我希望有人能证明我错了。

for (i in 2:nrow(TestData)) {
  # If stock - demand <= threshold, restock
  if ((TestData[i-1, "Stock"] - TestData[i, "Demand"]) <= TestData[i, "Threshold"]) 
  {
    TestData[i, "Stock"] <- TestData[i-1, "Upto"]
  }
  # Else update stock with stock - demand
  else 
  {
    TestData[i, "Stock"] <- TestData[i-1, "Stock"] - TestData[i, "Demand"]
  }
}

是一个棘手的问题。用do-while原则做的:

upVal     = 100
threshVal = 20
cumVals   <- TestData$Demand
cumMaster <- cumsum(cumVals) 


repeat{
    IND <- cumMaster>=upVal-threshVal
    cumVals[min(which(IND == TRUE))] <- 0
    cumMaster[IND] <- cumsum(cumVals[IND])
    if(all(cumMaster<upVal-threshVal)){
        break
    }
}

TestData$Stock <- 100 - cumMaster

结果

TestData$Stock

这里有一个 data.table 解决方案。创新点在 by 组。请执行 post 此解决方案失败的任何边界情况。

TestData <- data.table(Threshold = 20,
                       Upto = 100,
                       Demand = c(0,0,5,0,50,10,10,10,10,50,20,60),
                       Stock  = c(100,0,0,0,0,0,0,0,0,0,0,0))

#to see by grouping
#TestData[,trunc(cumsum(Demand)/(Threshold - Upto))]

TestData[, Stock2 := c(Upto[1], Upto[1] - cumsum(Demand[-1])),
    by=trunc(cumsum(Demand)/(Threshold - Upto))]
TestData