r - 如何通过指定分组计算移动平均线并处理 NA
问题描述
我有一个 data.table 需要对指定分组(ID1,ID2)的前 n 天数据计算移动平均值(为简单起见,我们使用 n=2,不包括当天)。移动平均线应尝试包含每个 ID1-ID2 对的最后 2 天的值。我想计算移动平均值以两种不同的方式处理 NA:1. 仅在有 2 个非 NA 观测值时计算,否则 avg 应该是 NA(例如,ID1-ID2 中的前 2 天总是有 NA)。2. 根据过去 2 天内的任何非 NA 观测值计算移动平均值 (na.rm=TRUE ?)。
我尝试使用 zoo 包和其中的各种功能。我已经解决了以下问题(使用 shift() 来排除在 avg 中考虑的周,以相反的顺序放置日期以突出显示日期并不总是最初排序):
library(zoo)
library(data.table)
DATE = rev(rep(seq(as.Date("2018-01-01"),as.Date("2018-01-04"),"day"),4))
VALUE =seq(1,16,1)
VALUE[16] <- NA
ID1 = rep(c("A","B"),each=8)
ID2 = rep(1:2,2,each=4)
testdata = data.frame (DATE, ID1, ID2, VALUE)
setDT(testdata)[order(DATE), VALUE_AVG := shift(rollapplyr(VALUE, 2, mean,
na.rm=TRUE,fill = NA)), by = c("ID1", "ID2")]
我似乎无法按多列分组。VALUE 以 NA 值开始/结束的分组似乎也会引起问题。我对任何在 data.table 框架中有意义的解决方案持开放态度,尤其是 frollmean(需要更新我的 R + data.table 版本)。我不知道我是否需要结合指定的对齐方式(例如“正确”)对日期进行不同的排序。
我希望我的输出看起来像下面这样,除了每个 ID1-ID2 分组按最旧日期排序:
DATE ID1 ID2 VALUE VALUE_AVG
1: 2018-01-04 A 1 1 2.5
2: 2018-01-03 A 1 2 3.5
3: 2018-01-02 A 1 3 NA
4: 2018-01-01 A 1 4 NA
5: 2018-01-04 A 2 5 6.5
6: 2018-01-03 A 2 6 7.5
7: 2018-01-02 A 2 7 NA
8: 2018-01-01 A 2 8 NA
9: 2018-01-04 B 1 9 10.5
10: 2018-01-03 B 1 10 11.5
11: 2018-01-02 B 1 11 NA
12: 2018-01-01 B 1 12 NA
13: 2018-01-04 B 2 13 14.5
14: 2018-01-03 B 2 14 15.0
15: 2018-01-02 B 2 15 NA
16: 2018-01-01 B 2 NA NA
我的代码似乎大致达到了示例数据的预期结果。然而,当尝试在 ID1 和 ID2 都是整数的 4 周平均值的大型数据集上运行相同的代码时,我收到以下错误:
Error in seq.default(start.at, NROW(data), by = by) :
wrong sign in 'by' argument
对于大多数 ID1-ID2 组合,我的结果似乎是正确的,但在 ID1 的特定情况下,VALUE 具有前导和尾随 NA。我猜这是导致问题的原因,尽管上面的示例没有。
解决方案
使用shift
不必要地使这复杂化。rollapply
已经可以自己处理了。在rollapplyr
指定:
list(-seq(2))
指定它应该作用于偏移量 -1 和 -2 的宽度。partial = TRUE
表示如果之前的行少于 2 行,它将使用那里的任何内容。fill = NA
用 NA 填充空单元格na.rm = TRUE 以删除任何 NA 并仅对剩余的单元格执行平均值。如果先前的单元格都是 NA,则均值给出 NaN。
仅考虑有 2 个先前的非 NA 给出 NA 的情况,否则删除partial = TRUE
andna.rm = TRUE
参数。
第一个案例
如果先前的行较少,则取前 2 行中的非 NA 的平均值或更少的行。
testdata <- data.table(DATE, ID1, ID2, VALUE, key = c("ID1", "ID2", "DATE"))
testdata[, VALUE_AVG :=
rollapplyr(VALUE, list(-seq(2)), mean, fill = NA, partial = TRUE, na.rm = TRUE),
by = c("ID1", "ID2")]
testdata
给予:
DATE ID1 ID2 VALUE VALUE_AVG
1: 2018-01-01 A 1 4 NA
2: 2018-01-02 A 1 3 4.0
3: 2018-01-03 A 1 2 3.5
4: 2018-01-04 A 1 1 2.5
5: 2018-01-01 A 2 8 NA
6: 2018-01-02 A 2 7 8.0
7: 2018-01-03 A 2 6 7.5
8: 2018-01-04 A 2 5 6.5
9: 2018-01-01 B 1 12 NA
10: 2018-01-02 B 1 11 12.0
11: 2018-01-03 B 1 10 11.5
12: 2018-01-04 B 1 9 10.5
13: 2018-01-01 B 2 NA NA
14: 2018-01-02 B 2 15 NaN
15: 2018-01-03 B 2 14 15.0
16: 2018-01-04 B 2 13 14.5
第二种情况
如果前 2 行中的任何一个为 NA,或者如果前 2 行少于 2,则为 NA。
testdata <- data.table(DATE, ID1, ID2, VALUE, key = c("ID1", "ID2", "DATE"))
testdata[, VALUE_AVG :=
rollapplyr(VALUE, list(-seq(2)), mean, fill = NA),
by = c("ID1", "ID2")]
testdata
给予:
DATE ID1 ID2 VALUE VALUE_AVG
1: 2018-01-01 A 1 4 NA
2: 2018-01-02 A 1 3 NA
3: 2018-01-03 A 1 2 3.5
4: 2018-01-04 A 1 1 2.5
5: 2018-01-01 A 2 8 NA
6: 2018-01-02 A 2 7 NA
7: 2018-01-03 A 2 6 7.5
8: 2018-01-04 A 2 5 6.5
9: 2018-01-01 B 1 12 NA
10: 2018-01-02 B 1 11 NA
11: 2018-01-03 B 1 10 11.5
12: 2018-01-04 B 1 9 10.5
13: 2018-01-01 B 2 NA NA
14: 2018-01-02 B 2 15 NA
15: 2018-01-03 B 2 14 NA
16: 2018-01-04 B 2 13 14.5
推荐阅读
- c++ - 当遇到不是来自 STL 的未捕获异常时,有什么方法可以打印其信息?
- object - 错误:无法导入名称 preprocessor_pb2 谷歌云
- reactjs - 在 React 中让孩子进入索引的最有效方法是什么
- python - 运行 python manage.py makemigrations 的问题
- java - 将 0 翻转为 1 的 Java 代码
- java - 在 web 元素中查找动态样式属性
- sql - Oracle 11g:是否可以创建聚集唯一索引?
- python - 错误“Service.py”
- solr - 使用 Solr 进行拼写检查
- java - 如何在 Spring MVC 中使 jsonData 不区分大小写