отфильтруйте скользящие средние результаты с ограниченными данными

#r #filter #time-series #rollapply

#r #Фильтр #временные ряды #rollapply

Вопрос:

Я пытаюсь вычислить скользящее среднее значение временного ряда. У меня нет проблем с вычислением, однако, глядя на результаты, вдоль временного ряда есть места, где скользящее среднее значение происходит на основе одного или двух значений, окруженных длинным рядом пропущенных значений. Я бы хотел, чтобы скользящее среднее значение возникало только тогда, когда выполняется более 50% данных в пределах интервала времени для с скользящим средним. Если доступно менее 50% данных, то результат для этого индекса должен быть NaN .

Я написал несколько примеров кода, чтобы, надеюсь, продемонстрировать, чего я пытаюсь достичь.

 #Create example data
set.seed(12)
dat1=runif(20,min=0,max=10)
dat2=dat1
ind=which(dat2 %in% sample(dat2,5))
#in this case ind=c(4, 7, 8, 13, 16)
dat2[ind]=NA

dat3=dat1
ind2=which(dat3 %in% sample(dat3,12))
#in this case ind2=c(2, 5, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18)
dat3[ind2]=NA

#create a time series
now <- Sys.time()
tseq <- seq(from = now, length.out = 20, by = "mins")

#data in zoo format
dat1=zoo(dat1,tseq)
dat2=zoo(dat2,tseq)
dat3=zoo(dat3,tseq)

#rolling mean using roll apply
dat1rollmean=rollapply(dat1,width=5,align='center',FUN=function(x) mean(x,na.rm=T))
dat2rollmean=rollapply(dat2,width=5,align='center',FUN=function(x) mean(x,na.rm=T))
dat3rollmean=rollapply(dat3,width=5,align='center',FUN=function(x) mean(x,na.rm=T))

#doesn't work
dat3newrollmean=rollmean(dat3,5)

#desired rolling mean result
dat2des=dat2rollmean
dat2des[4]=NaN

dat3des=dat3rollmean
dat3des[c(4:14)]=NaN
 

В этом примере dat1 представляет собой полный набор данных, для которого моя функция rollapply (ширина 5) работает хорошо, dat2 и dat3 имеют разные уровни отсутствующих данных. Я бы хотел, чтобы мой результат в этом случае заменял любые точки, в которых rollapply выполняется для менее чем 2 точек данных NaN . Это будет индекс 4 для dat2rollmean и индексы 4-14 для dat3rollmean . Как бы я написал функцию для поиска этих случаев недостаточных данных и замены результирующего скользящего среднего результата на NaN ?

Ответ №1:

Используйте Mean , определенные ниже:

 Mean <- function(x) if (sum(is.na(x)) < length(x) / 2) mean(x, na.rm = TRUE) else NaN

res1 <- rollapply(dat1, 5, Mean)
identical(res1, dat1rollmean)
## [1] TRUE

res2 <- rollapply(dat2, 5, Mean)
identical(res2, dat2des)
## [1] TRUE

res3 <- rollapply(dat3, 5, Mean)
identical(res3, dat3des)
## [1] TRUE