2012-05-23 46 views
2

我有一個顯示日期,項目和值的數據框,我想添加一列顯示其先前50個條目的平均值(如果NA沒有50 )例如該表可能是R中最近的50個條目的平均值

 data 
date  item value 
01/01/01 a 2 
01/01/01 b 1.5 
04/01/01 c 1.7 
05/01/01 a 1.9 
...... 

和它的一部分可能會成爲

date  item value last_50_mean 
........ 
11/09/01 a 1.2 1.1638 
12/09/01 b 1.9 1.5843 
12/09/01 a 1.4 1.1621 
13/09/01 c 0.9 NA 
........ 

所以在這種情況下,一個在50個條目平均前01年11月9日是1.1638和c一直沒有13/09/01前50項,以便返回NA

我目前做這個使用下面的函數

data[, 'last_50_mean'] <- sapply(1:nrow(data), function(i){ 
     prevDates <- data[data$date < data$date[i] & data$item == data$item[i], ] 
     num  <- nrow(prevGames) 
     if(nGames >= 50){ 
      round(mean(prevDates[(num- 49):num, ]$value), 4) 
     } 
     } 
) 

但是我的數據框很大,需要很長時間(事實上,我並不是100%確定它仍然在運行......有沒有人知道這樣做的最佳方式?

+0

'library(xts); ?rollmean'。另請參閱[此處](http://r.789695.n4.nabble.com/Calculating-rolling-mean-by-group-td4280511.html)查看相關問題。最後,請查看[這個問題](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)讓您的問題可重現,以便其他人可以輕鬆地嘗試和幫助您。 – Chase

+0

你是否說你的數據幀很大?試試[這個最近的答案](http://stackoverflow.com/questions/10721180/how-do-i-speed-up-this-for-loop-with-data-table-lapply)。 –

回答

4

N個觀測數據的平均值可以從累計總數和第一個和最後一個數值之差diff(cumsum(x), lag=N - 1)中計算出來。您的問題需要填充第一個N - 1值,因此

meanN <- function(x, N=50) 
    ## mean of last N observations, padded in front with NA 
{ 
    x0 <- x[seq_len(length(x) - N + 1)] 
    x1 <- (x0 + diff(cumsum(x), lag=N-1))/N 
    c(rep(NA, N - 1), x1) 
} 

您希望爲多個組執行此操作。對於這樣做的data.frame

df <- data.frame(item=sample(letters[1:3], 1000, TRUE), 
       value=runif(1000, 1, 3), 
       last_50_mean=NA) 

一種方法是

split(df$last_50_mean, df$item) <- lapply(split(df$value, df$item), meanN) 

導致例如

> tail(df) 
    item value last_50_mean 
995  c 1.191486  2.037707 
996  c 2.899214  2.073022 
997  c 2.019375  2.054914 
998  c 2.737043  2.066389 
999  a 1.703752  1.923234 
1000 c 1.602442  2.043517 

這是假設你的數據幀按時間排序。一個潛在的問題是當長向量溢出時cumsum;人們可以通過集中value來解決這個問題,所以期望cumsum不會偏離零。最近的一個問題解決了split<-的替代方案,並刪除了最後的N個觀測值。

+0

非常感謝馬丁,這是工作。只有輕微的一點是平均值包含了我不希望它做的當前值,所以我將meanN函數的結尾改爲c(rep(NA,N),x1 [1:(length(x1) - 1 )])來解決這個問題 – user1165199