4

我正在尝试递归替换 NA 和零值。我正在研究时间序列数据,其中 NA 或零最好用前一周的值替换(每 15 分钟测量一次,因此后退 672 步)。我的数据包含约两年的 15 分钟值数据,因此这是一个很大的集合。预计不会有太多的 NA 或零,也不会出现相邻的零系列或 NA > 672。

我发现这个线程(R 中的递归替换)显示了递归方式,使其适应了我的问题。

load[is.na(load)] <- 0
o <- rle(load)
o$values[o$values == 0] <- o$values[which(o$values == 0) - 672]
newload<-inverse.rle(o)

现在这是“最好的”还是优雅的方法?当前 672 个值中出现零值时,我将如何保护我的代码免受错误?

我曾经使用 matlab,我会在其中执行以下操作:

% Replace NaN with 0
Load(isnan(Load))=0;
% Find zero values
Ind=find(Load==0);
for f=Ind
    if f>672
    fprintf('Replacing index %d with the load 1 day ago\n', Ind)
    % Replace zero with previous week value
    Load(f)=Load(f-672);
    end
end

由于我对 R 不熟悉,我将如何设置这样的 if else 循环?

一个可重现的示例(更改代码,因为其他线程使用的示例无法处理相邻的零):

day<-1:24
load<-rep(day, times=10)
load[50:54]<-0
load[112:115]<-NA
load[is.na(load)] <- 0
load[load==0]<-load[which(load == 0) - 24]

这给出了没有零和NA的原始负载数据帧。当前 24 个值中存在零时,这会出错,因为没有值可以替换为:

loadtest[c(10,50:54)]<-0 # instead of load[50:54]<-0 gives:

Error in loadtest[which(loadtest == 0) - 24] : 
only 0's may be mixed with negative subscripts

现在要解决这个问题,可以使用 if else 语句,但我不知道如何应用。就像是:

day<-1:24
loadtest<-rep(day, times=10)
loadtest[c(10,50:54)]<-0
loadtest[112:115]<-NA
loadtest[is.na(loadtest)] <- 0 
if(INDEX(loadtest[loadtest==0])<24) {
     # nothing / mean / standard value
    } else {
      loadtest[loadtest==0]<-loadtest[which(loadtest == 0) - 24]
    } 

Ofcourse INDEX 不是有效的代码..

4

2 回答 2

1

您可以使用此示例:

set.seed(42)

x <- sample(c(0,1,2,3,NA), 100, T)

stepback <- 6

x_old <- x
x_new <- x_old

repeat{
    filter <- x_new==0 | is.na(x_new)
    x_new[filter] <- c(rep(NA, stepback), head(x_new, -stepback))[filter]
    if(identical(x_old,x_new)) break
    x_old <- x_new
}

x
x_new

结果:

> x
  [1] NA NA  1 NA  3  2  3  0  3  3  2  3 NA  1  2 NA NA  0  2  2 NA  0 NA NA  0
 [26]  2  1 NA  2 NA  3 NA  1  3  0 NA  0  1 NA  3  1  2  0 NA  2 NA NA  3 NA  3
 [51]  1  1  1  3  0  3  3  0  1  2  3 NA  3  2 NA  0  1 NA  3  1  0  0  1  2  0
 [76]  3  0  1  2  0  2  0  1  3  3  2  1  0  0  1  3  0  1 NA NA  3  1  2  3  3
> x_new
  [1] NA NA  1 NA  3  2  3 NA  3  3  2  3  3  1  2  3  2  3  2  2  2  3  2  3  2
 [26]  2  1  3  2  3  3  2  1  3  2  3  3  1  1  3  1  2  3  1  2  3  1  3  3  3
 [51]  1  1  1  3  3  3  3  1  1  2  3  3  3  2  1  2  1  3  3  1  1  2  1  2  3
 [76]  3  1  1  2  2  2  3  1  3  3  2  1  3  1  1  3  2  1  3  1  3  1  2  3  3

请注意,有些值仍然是NA,因为没有先验信息可用于它们。如果您的数据有足够的先验信息,则不会发生这种情况。

于 2013-09-17T15:27:35.813 回答
1

一种选择是将向量包装成一个有 672 行的矩阵:

load2 <- matrix(load, nrow=672)

然后将最后的观察结果(来自动物园,或上述方法,或...)应用于矩阵的每一行:

load3 <- apply( load2, 1, locf.function )

然后将得到的矩阵带回具有正确长度的向量:

load4 <- t(load3)[ seq_along(load) ]
于 2013-09-17T19:01:32.070 回答