2015-10-17 73 views
1

我有一个data.frame,其中一列包含分类数据,一列包含日期,一列包含数值。为了简单起见,请参见下面的示例:R计算滞后分区的统计量

A  B   C 
1 L 2015-12-01 5.7 
2 M 2015-11-30 2.1 
3 K 2015-11-01 3.2 
4 L 2015-10-05 5.7 
5 M 2015-12-05 1.2 
6 L 2015-11-15 2.3 
7 L 2015-12-03 4.4 

我想,对于A中的每个类别,计算一个滞后平均(例如,在列C中的前30天的值的平均值)。

我不能为我的生活算出这一个。我已经尝试过使用sapply和一个自定义函数,它将类别和日期(或其深层副本)上的data.frame进行子集化并返回统计量(认为是mean或sd),并且对单个值运行正常,但它会返回所有NA从sapply里面。

你可以给任何帮助表示赞赏。

+2

“滞后平均值”是指A中每个组的平均值,包括单个30天的C值范围?或者你的意思是平均跑步速度?目前还不清楚你给出的答案只有7个值。例如,你想从K组(只有一个值)在这里想要什么? –

+0

理想情况下,我希望能够为每一行返回一个值,即B列的平均值为所有其他行的日期在B前30天内的行。例如,如果某行的日期为2015-12-31,类别为K,我希望它会返回类别K的所有值的平均值,日期为2015-12-1和2015-12-30(含)。对不起,我对原始问题并不是很清楚。 – Tyler

回答

1

这可以做得更紧凑,但在这里我已经绘制出来,使其最容易理解。核心是分裂,推翻/应用,然后将其重新组合。它使用日期窗口而不是基于排序的解决方案,因此非常普遍。我还将对象恢复到原来的顺序以启用直接比较。

# set up the data 
set.seed(100) 

# create a data.frame with about a two-month period for each category of A 
df <- data.frame(A = rep(c("K", "L", "M"), each = 60), 
       B = rep(seq(as.Date("2015-01-01"), as.Date("2015-03-01"), by="days"), 3), 
       C = round(runif(180)*6, 1)) 
head(df) 
## A   B C 
## 1 K 2015-01-01 1.8 
## 2 K 2015-01-02 1.5 
## 3 K 2015-01-03 3.3 
## 4 K 2015-01-04 0.3 
## 5 K 2015-01-05 2.8 
## 6 K 2015-01-06 2.9 
tail(df) 
##  A   B C 
## 175 M 2015-02-24 4.8 
## 176 M 2015-02-25 2.0 
## 177 M 2015-02-26 5.7 
## 178 M 2015-02-27 3.9 
## 179 M 2015-02-28 2.8 
## 180 M 2015-03-01 3.6 

# preserve original order 
df$originalOrder <- 1:nrow(df) 
# randomly shuffle the order 
randomizedOrder <- order(runif(nrow(df))) 
df <- df[order(runif(nrow(df))), ] 


# split on A - your own data might need coercion of A to a factor 
df.split <- split(df, df$A) 

# set the window size 
window <- 30 

# compute the moving average 
listD <- lapply(df.split, function(tmp) { 
    apply(tmp, 1, function(x) mean(tmp$C[tmp$B <= as.Date(x["B"]) & tmp$B (as.Date(x["B"]) - window)])) 
}) 

# combine the result with the original data 
result <- cbind(do.call(rbind, df.split), rollingMean = unlist(listD)) 

# and tidy up: 
# return to original order 
result <- result[order(result$originalOrder), ] 
result$originalOrder <- NULL 
# remove the row names 
row.names(result) <- NULL 

result[c(1:5, 59:65), ] 
## A   B C rollingMean 
## 1 K 2015-01-01 1.8 1.800000 
## 2 K 2015-01-02 1.5 1.650000 
## 3 K 2015-01-03 3.3 2.200000 
## 4 K 2015-01-04 0.3 1.725000 
## 5 K 2015-01-05 2.8 1.940000 
## 59 K 2015-02-28 3.6 3.080000 
## 60 K 2015-03-01 1.3 3.066667 
## 61 L 2015-01-01 2.8 2.800000 
## 62 L 2015-01-02 3.9 3.350000 
## 63 L 2015-01-03 5.8 4.166667 
## 64 L 2015-01-04 4.1 4.150000 
## 65 L 2015-01-05 2.7 3.860000 
+1

这工作。谢谢,肯! – Tyler