我正在使用R. 我知道计算移动平均线是这个网站中有几个答案的主题,但我有一些问题让我的问题变得独一无二。
我有一个数据框,包括8784小时浓度(366天* 24小时)的空气污染物(臭氧)。该数据帧包括一些NaN值(缺失值)。 该程序包含以下步骤:
1-计算每小时浓度的8小时移动(滚动)平均值:即每8个浓度应以这种方式平均:平均1至8,平均2至9,平均3至10等。 这导致每天(每24小时)获得24个移动平均线。
每天2-,我想要最多8小时移动平均线:即在24个移动平均线中,应选择最高数量。最后,将选择366个移动平均线(366天)。
3-应创建一个包含366个移动平均线的新数据框。
我知道有一些软件包(opena,动物园,TTR)可以做这样的事情,但有没有办法在没有任何软件包的情况下编写代码?
An Exmaple of my data
ColName
1 18.76
2 12.92
3 8.12
4 NaN
5 12.92
6 3.77
7 18.76
8 9.52
9 94.09
10 18.76
11 14.13
12 8.12
13 2.04
14 12.92
15 9.17
.
.
.
8783 34.58
8784 64.23
主数据框的名称是“每小时”。我试过这些代码:
Hourly1 <- c(0, cumsum(ifelse(is.nan(Hourly), 0, Hourly)))
rsum <- (Hourly1[(Hourly1+1):length(Hourly1)] - Hourly1[1:(length(Hourly1) - 8)]) / 8
但是当我尝试第一行时,会发生以下错误:
Error in is.nan(Hourly) : default method not implemented for type 'list'
更新: 我使用了以下代码,但最多不能计算8小时平均值:
Hourly2<-as.numeric(Hourly$Average)
names(Hourly2) <- rep(seq.Date(as.Date("2017-01-01"), by=1, length.out=366), each=24)
x<-Hourly2
#use cumsum to get the moving average, keep NaNs
cx <- c(0, cumsum(ifelse(is.nan(x), 0, x))) + c(0,x)*0
n <- 8
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]) / n
res <- data.frame(mov_avg=rsum, days=names(rsum))
#select max from each day, ignoring NaN's
mx <- aggregate(mov_avg~days, data=res, max)
我将最终结果(最多8小时平均值366,每年1天)与标准预先批准的数据集进行了比较。在某些日子里,计算出的代码平均值正确,但在其他几天没有!我没有得到它的逻辑。
您可以找到我的原始数据集here!
更新2:
Here is a link to download不同方法产生的最终结果!
UPDATE3:
结果之间的差异是由于计算移动平均线的不同方法。计算移动平均线有三种方法:左,右和中心。这里的人提出的代码遵循“正确”的方法。
答案 0 :(得分:1)
以下是您在缺少值时如何使用cumsum
执行此操作的示例。我会小心考虑它们如何在您的数据中分发,以及您希望如何处理它们。
#create some sample data
set.seed(1)
x <- rnorm(24*366)
names(x) <- rep(seq.Date(as.Date("2017-01-01"), by=1, length.out=366), each=24)
x[sample(100, 1:length(x))] <- NaN #add some missing values
#use cumsum to get the moving average, keep NaNs
cx <- c(0, cumsum(ifelse(is.nan(x), 0, x))) + c(0,x)*0
n <- 8
rsum <- (cx[(n+1):length(cx)] - cx[1:(length(cx) - n)]) / n
res <- data.frame(mov_avg=rsum, days=names(rsum))
#select max from each day, ignoring NaN's
mx <- aggregate(mov_avg~days, data=res, max)
days mov_avg
1 2017-01-01 0.6404849
2 2017-01-02 0.3456389
3 2017-01-03 0.5998888
4 2017-01-04 0.6635502
5 2017-01-05 0.7244289
6 2017-01-06 0.1715349
答案 1 :(得分:0)
我一直在努力工作,并找到了一个使用map2()的解决方案
# create a day of ozone data
o3day <- data.frame(o3hrly = runif(24, 0.04, 0.1))
# 8hr average function
avg_8hr <- function(.x, .y, o3) {
# print(.x)
# print(.y)
# print(o3)
o3 %>% slice(.x:.y) %>% summarize(o38hr = mean(o3hrly))
}
max(unlist(map2(.x = 1:17, .y = 8:24, .f = avg_8hr, o3 = o3day)))