Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance “复制单元格值的惯用方法”;“向下”;在R向量中_Performance_R_Loops_Vectorization_Idioms - Fatal编程技术网

Performance “复制单元格值的惯用方法”;“向下”;在R向量中

Performance “复制单元格值的惯用方法”;“向下”;在R向量中,performance,r,loops,vectorization,idioms,Performance,R,Loops,Vectorization,Idioms,可能重复: 有没有一种惯用的方法在R向量中“向下”复制单元格值?“向下复制”是指用最接近的先前非NA值替换NAs 虽然我可以用for循环非常简单地实现这一点,但它运行得非常慢。任何关于如何矢量化的建议都将不胜感激 # Test code # Set up test data len <- 1000000 data <- rep(c(1, rep(NA, 9)), len %/% 10) * rep(1:(len %/% 10), each=10) head(data, n=25)

可能重复:

有没有一种惯用的方法在R向量中“向下”复制单元格值?“向下复制”是指用最接近的先前非NA值替换NAs

虽然我可以用for循环非常简单地实现这一点,但它运行得非常慢。任何关于如何矢量化的建议都将不胜感激

# Test code
# Set up test data
len <- 1000000
data <- rep(c(1, rep(NA, 9)), len %/% 10) * rep(1:(len %/% 10), each=10)
head(data, n=25)
tail(data, n=25)

# Time naive method
system.time({
  data.clean <- data;
  for (i in 2:length(data.clean)){
    if(is.na(data.clean[i])) data.clean[i] <- data.clean[i-1]
  }
})

# Print results
head(data.clean, n=25)
tail(data.clean, n=25)
#测试代码
#设置测试数据
伦恩
>#时间朴素方法
>系统时间({
+data.clean#打印结果
>压头(data.clean,n=25)
[1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3
>尾部(data.clean,n=25)
[1]  99998  99998  99998  99998  99998  99999  99999  99999  99999  99999
[11]  99999  99999  99999  99999  99999 100000 100000 100000 100000 100000
[21] 100000 100000 100000 100000 100000
> 

使用
zoo::na.locf

在函数
f
中包装代码(包括返回
数据。最后清理
):


使用
zoo::na.locf

在函数
f
中包装代码(包括返回
数据。最后清理
):


我不知道惯用语,但这里我们确定了非NA值(
idx
),以及最后一个非NA值的索引(
cumsum(idx)


na.rm=FALSE
时,这似乎增加了约30%的时间。想必
na.locf
还有其他优点,可以捕获更多的角落案例,并允许填充而不是填充(无论如何,这在
cumsum
世界中是一个有趣的练习)。很明显,我们至少分配了五个可能较大的数据--
idx
(实际上,我们计算
is.na()
及其补码),
cumsum(idx)
x[idx]
,以及
x[idx][cumsum(idx)]
--因此还有进一步改进的余地,例如,在C

中,我不知道惯用语,但这里我们确定了非NA值(
idx
),以及最后一个非NA值的索引(
cumsum(idx)


na.rm=FALSE
时,这似乎增加了约30%的时间。想必
na.locf
还有其他优点,可以捕获更多的角落案例,并允许填充而不是填充(无论如何,这在
cumsum
世界中是一个有趣的练习)。很明显,我们至少分配了五个可能较大的数据--
idx
(实际上,我们计算
is.na()
及其补码),
cumsum(idx)
x[idx]
,以及
x[idx][cumsum(idx)]
——因此还有进一步改进的余地,例如,在C中,我称之为惯用。非常好。比我的系统上的na.locf快7倍。我称之为惯用。非常好。比我的系统上的na.locf快7倍。
> # Set up test data
> len <- 1000000
> data <- rep(c(1, rep(NA, 9)), len %/% 10) * rep(1:(len %/% 10), each=10)
> head(data, n=25)
 [1]  1 NA NA NA NA NA NA NA NA NA  2 NA NA NA NA NA NA NA NA NA  3 NA NA NA NA
> tail(data, n=25)
 [1]     NA     NA     NA     NA     NA  99999     NA     NA     NA     NA
[11]     NA     NA     NA     NA     NA 100000     NA     NA     NA     NA
[21]     NA     NA     NA     NA     NA
> 
> # Time naive method
> system.time({
+   data.clean <- data;
+   for (i in 2:length(data.clean)){
+     if(is.na(data.clean[i])) data.clean[i] <- data.clean[i-1]
+   }
+ })
   user  system elapsed 
   3.09    0.00    3.09 
> 
> # Print results
> head(data.clean, n=25)
 [1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3
> tail(data.clean, n=25)
 [1]  99998  99998  99998  99998  99998  99999  99999  99999  99999  99999
[11]  99999  99999  99999  99999  99999 100000 100000 100000 100000 100000
[21] 100000 100000 100000 100000 100000
> 
library(rbenchmark)
library(zoo)

identical(f(data), na.locf(data))
## [1] TRUE

benchmark(f(data), na.locf(data), replications=10, columns=c("test", "elapsed", "relative"))
##            test elapsed relative
## 1       f(data)  21.460   14.471
## 2 na.locf(data)   1.483    1.000
f1 <- function(x) {
    idx <- !is.na(x)
    x[idx][cumsum(idx)]
}
f2 <- function(x, na.rm=TRUE) {
    idx <- !is.na(x)
    cidx <- cumsum(idx)
    if (!na.rm)
        cidx[cidx==0] <- NA_integer_
    x[idx][cidx]
}