2015-12-21 127 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