【发布时间】:2019-08-26 05:41:54
【问题描述】:
我想出了一些代码来计算面板数据的滚动平均值(数据中的一行包含一天中一个主题的值)。由于我有一些更具体的要求,代码变得相当复杂。在我看来,对于一个不太罕见的应用程序来说太复杂了。
这是我需要的:
滚动平均值((a) 前 3 天不包括“当前”日的值的平均值,(b) 仅在有此窗口中至少有 2 个非缺失值)
尊重面板结构
不会太复杂吧?
对于 1. 我决定使用 rollapplyr() 和 mean( , na.rm = T) 来排除当天 (a) 我决定使用自制的滞后函数和 (b) if 语句。对于 2。我将所有内容都包裹在 tapply()(与 unlist())中,以尊重面板结构。
代码示例如下:
library(zoo)
# example data (with missings)
set.seed(1)
df = data.frame(subject = rep(c("a", "b"), each = 10), day = rep(1:10, 2), value = rnorm(20))
df$value[15:17] = NA
# lag function (sensitive to "single day" subjects)
lag <- function(x, l = 1) {
if (length(x) > 1) (c(rep(NA, l), x[1:(length(x)-l)])) else (NA)
}
# calculate rolling mean
df$roll_mean3 = unlist(tapply(df$value, df$subject,
FUN = function(x) lag(rollapplyr(x, width = 3, fill = NA, partial = T,
FUN = function(x) ifelse(sum(!is.na(x)) > 1, mean(x, na.rm = T), NA)))))
df
正如我所说,对于我认为并不遥远的情况,这种解决方案似乎过于复杂。
您对如何以更简单(不易出错)的方式执行此操作有什么建议吗? 我是否错过了一些可以更轻松地处理面板数据的基本功能?
为了说明,我的代码的输出是:
subject day value roll_mean3
1 a 1 -0.6264538 NA
2 a 2 0.1836433 NA
3 a 3 -0.8356286 -0.221405243
4 a 4 1.5952808 -0.426146366
5 a 5 0.3295078 0.314431838
6 a 6 -0.8204684 0.363053321
7 a 7 0.4874291 0.368106730
8 a 8 0.7383247 -0.001177187
9 a 9 0.5757814 0.135095124
10 a 10 -0.3053884 0.600511703
11 b 1 1.5117812 NA
12 b 2 0.3898432 NA
13 b 3 -0.6212406 0.950812202
14 b 4 -2.2146999 0.426794608
15 b 5 NA -0.815365744
16 b 6 NA -1.417970234
17 b 7 NA NA
18 b 8 0.9438362 NA
19 b 9 0.8212212 NA
20 b 10 0.5939013 0.882528703
【问题讨论】:
-
您能否修改您的帖子以包含可重现的样本数据(使用
set.seed表示固定的随机种子)和相应的预期输出?这听起来像rollapply和dplyr::group_by可能会完成这项工作,但您的预期输出将有助于更好地理解您的问题。此外,dplyr已经有一个lag函数(并且data.table有一个等效的shift函数)。 -
我在问题中添加了种子语句和预期输出。
-
嗯。我不确定我是否理解您的预期输出。您想计算 (a) 前 3 天(不包括“当前”天)的值的 “平均值”。主题
"a"的第一个非NA值不会从第4 行开始吗?为什么你在第 3 行有一个值? -
因为一旦滚动窗口中有 2 个非缺失值,就会计算平均值。
-
但根据您的描述,您想计算 前 3 天(不包括当天)的
value的平均值。这与计算平均值 “只要滚动窗口中有 2 个非缺失值” 有什么关系?似乎是两个不同的目标。
标签: r lag moving-average panel-data tapply