2017-04-12 88 views
3

我有一个data.table具有以下布局如何在data.table使用移位计算,累计值中的R

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)) 

股票值应为具有下式的累积值来计算:

如果库存(上一行)减去点播(当前行)小于或大于阈值等于 ,比用在“高达”的 值更新股票的当前小区。否则使用库存(前一行)减去需求(当前行)更新库存(当前行)的值。

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

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每次瓦结束。库存中的第一个值是手动设置的初始值。谢谢!

+1

我觉得既然每次迭代依赖于前面的迭代(前一天的股票) –

+0

@docendodiscimus是啊,我觉得需要一个循环,因为有一个复位规则的值(与累积您可能需要为这样的循环需求在触及80后一行之后重新开始)。 – Frank

回答

2

如果你可以住在一个循环解决方案。我认为这不适用于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"] 
    } 
} 
+0

您可以在循环的每次迭代中将'TestData [i-1,“Stock”] - TestData [i,“Demand”]'作为临时变量存储,否则可能会在某些迭代中计算两次。 '剩余= TestData [i-1,“股票”] - TestData [i,“需求”]; TestData [i,“Stock”] < - if(剩余<= TestData [i,“Threshold”])TestData [i-1,“Upto”] else remaining' – Frank

+0

谢谢大家。我选择这个作为答案,因为它最适合我的真实问题。 – Sven

2

是一个棘手的问题。有一个做,而原则做到了:

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 
3

这里是一个data.table解决方案。创新在by分组。请张贴任何此解决方案失败的边界案例。

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