2015-12-21 68 views
0

举一个简单的例子,我需要创建下表中的R列的递推更新(这是我想要的结果):data.table

library(data.table) 
DT <- data.table(A= c(2,5,4,-2,4), 
        B= c(1000,1100,1375,1650,1485), 
        C= c(50,55,68.75,82.5,74.25), 
        D= c(100,275,275,-165,297)) 
DT 

这是我的尝试,到目前为止这是不工作:

DT.2 <- data.table(A= c(2,5,4,-2,4)) 
DT.2[, B := 1000 ] # B should begin at 1000, then cumulatively add column D 
DT.2[, C := B * 0.05 ] 
DT.2[, D := A * C ] 
DT.2[, B := 1000 + cumsum(shift(D, type= "lag", fill=FALSE)) ] 
DT.2 

正如您所看到的,列不会正确更新,因为每列都依赖于其他列的结果。在Excel中这是一个非常简单的计算,我只需要了解如何使其适应R. 谢谢

+1

这是奇怪的递归 - 你初始化'B'为'1000'。那么'C'依赖于'B','D'依赖于'C',并且'B'被重新定义为依赖于'D'。似乎通告。 – Gregor

+0

你能解释一下如何获得你想要的结果(即应用了什么变换)? – fishtank

+0

我在Excel中创建了这个例子。 B列从1000开始,然后依靠其他列的结果。我可以想象它需要一个循环函数或应用系列,但是我无法做到这一点。 – user3740289

回答

3

就我所知,您需要一个循环。这里是我的输入数据:

DT <- data.table(A = c(2, 5, 4, -2, 4), 
       B = c(1000, rep(NA, 4)), 
       C = numeric(5), 
       D = numeric(5)) 

,循环使用:

#initial row 
DT[1, c("C", "D") := .(.05 * B, .05 * A * B)] 

#subsequent rows 
for (nn in 2:nrow(DT)){ 
    new_B <- DT[nn - 1L, B + D] 
    DT[nn, c("B", "C", "D") := .(new_B, .05 * new_B, .05 * A * new_B)] 
} 

也很容易被转换为sapply,所以你不必nn坐在你的命名空间周围(但现在它会打印无意义的东西到控制台):

sapply(2:nrow(DT), function(nn){ 
    (same as before)}) 

是的,我能想象这将在Excel中看起来更简单,因为它自动更新为为你点击+拖动鼠标。

+0

是的@MichaelChirico,这正是我需要的。非常感谢你!为了让我更好地理解这一点,我应该如何更好地表达这个问题?即。如果我在网上搜索这种类型的应用程序,我会寻找什么? – user3740289

+1

@ user3740289我认为给你的“初始”数据,正如我在答案中所做的那样,对于读者来说会更少困惑 - 一旦你意识到你只知道B [1]'_ex ante_,就会更清楚地知道发生了什么。除此之外,您可能会更清楚地理解列的生成方式(而不是_interdependently_,_recursively_),或者更清楚地说明方法。 – MichaelChirico

+0

@ user3740289我同意迈克尔。我认为有几个人错过了你以期望的结果领导的事实 - 在问题的最后看到这种情况更为常见。关于投入的明确要求是很重要的。当你显示'B:= 1000'时,它将'B'的每行**设置为1000,但你只希望第一行设置为1000. – Gregor

1

我认为你真正想要的功能,我猜测,它将使更多类似这样的感觉:

fun <- function(id, ## not sure what this is, probably an id 
       start = 1000, 
       rate = .05, 
       gain_or_loss){ 
    require(data.table) 

    cnt <- length(id) 
    ret <- data.table(ID = c(id, NA), 
         bal = cumsum(c(start, gain_or_loss)), 
         fixed_change = rep(NA_real_, cnt + 1), 
         total_change = c(gain_or_loss, NA_real_)) 
    ret[ , fixed_change := bal * 0.05 ] 
    ret <- ret[] ## needed because of a data.table quirk 
    return(ret) 
} 

这将使:

fun(id = c(2,5,4,-2,4), 
    gain_or_loss = c(100,275,275,-165,297)) 

# ID bal fixed_change total_change 
# 1: 2 1000  50.00   100 
# 2: 5 1100  55.00   275 
# 3: 4 1375  68.75   275 
# 4: -2 1650  82.50   -165 
# 5: 4 1485  74.25   297 
# 6: NA 1782  89.10   NA 

我还想以后添加代码requireif (length(id) != length(gain_or_loss)) stop("id and gain_or_loss need to be of the same length")

+0

谢谢@geneorama,我正在测试每个选项。 – user3740289

+0

我的主要观点是,使用更多描述性变量名称会使问题变得更容易,并且使用函数时答案变得更加简单。 – geneorama