我有一个较大的栅格数据(X),其尺寸为32251 * 51333。 X的值是另一个数组(Y)的重复,其大小为3 * 10 ^ 6。 现在,我想通过将X的值与Y的每个值进行匹配来更改X的值,例如,我可以像这样编程
for (i in 1:length(Y)){
X[X==Y[i]] = Z[i] #Z is just another array with the same size as Y
}
问题在于,首先匹配X[X==Y[i]] = Z[i]
的索引不起作用,因为X太大。几分钟后,程序会通过给出错误"Error: cannot allocate vector of size 6.2 Gb".
来停止
其次,即使Y的大小为10 ^ 6,从1到length(Y)的循环也可能需要“永远”才能完成。
我想到的一种方法是将X分成小块,然后对每个块进行索引匹配。但是我觉得这仍然需要很多时间。
是否有更好的方法来实现上述目标?
由于@Lyngbakr提供的示例,我将进一步阐述这个问题。由于我使用的栅格很大(32251 * 51333),因此似乎无法上传。 @Lyngbakr给出的示例与我想要的非常相似,除了创建的栅格太小之外。现在,按照该示例,我通过生成尺寸为3000 * 2700的更大的栅格进行了两次测试。参见下面的代码。
#Method 1: Use subs
start_time <- Sys.time()
Y <- 1:9
Z <- 91:99
X <- raster(matrix(rep(Y, 3), nrow=3000,ncol = 2700))
df <- data.frame(Y, Z)
X <- subs(X, df)
end_time <- Sys.time()
end_time - start_time
#Time difference of 2.248908 mins
#Method 2: Use for loop
start_time <- Sys.time()
Y <- 1:9
Z <- 91:99
X <- raster(matrix(rep(Y, 3), nrow=3000,ncol = 2700))
for (i in 1:length(Y)){
X[X==Y[i]]=Z[i] #this indexing of R seems not efficient if X becomes large
}
end_time <- Sys.time()
end_time - start_time
#Time difference of 10.22717 secs
如您所见,简单的 for 循环比subs函数更有效。请记住,示例中显示的栅格仍然比我使用的栅格小(大约小100倍)。此外,示例中的数组Y非常小。现在的问题可能是,如何加快方法2(这只是一个简单的for循环)?
答案 0 :(得分:0)
您正在寻找subs
函数。我不知道它是否适用于大型栅格,但是您可以尝试以下方法。
我加载了raster
包并创建了一些虚拟数据。 (如果您在问题中提供数据,这将真的会有所帮助。)然后,我绘制结果。
# Load library
library(raster)
#> Loading required package: sp
# Z holds values that will replace Y
Y <- 1:9
Z <- 91:99
# Create dummy raster
X <- raster(matrix(rep(Y, 3), ncol = 9))
# Examine raster
plot(X)
如您所见,X
只是一堆Y
个矢量修补在一起。接下来,我将Y
和Z
绑定到一个数据帧df
中。
# Combine y & z into a data frame
df <- data.frame(Y, Z)
最后,我使用subs
将Y
的值替换为Z
的值。
# Substitute Z for Y in X
X <- subs(X, df)
快速浏览一下栅格,表明值已正确替换。
# Examine raster
plot(X)
由reprex package(v0.2.1.9000)于2019-06-25创建
Rcpp
确实很有帮助。下面,我比较三种方法:
subs
Rcpp
在C ++中循环顺便说一句,Sys.time()
并不是检查性能的好方法,因此我建议使用microbenchmark
。
# Load library
library(raster)
# Define vectors and raster
Y <- 1:9
Z <- 91:99
X <- raster(matrix(rep(Y, 3), nrow = 3000, ncol = 2700))
method_1
是subs
函数。
# Using subs function
method_1 <- function(){
df <- data.frame(Y, Z)
X <- subs(X, df)
}
method_2
是您的原始循环方法。
# Using R loop
method_2 <- function(){
for (i in 1:length(Y)){
X[X==Y[i]]=Z[i]
}
X
}
method_3
是用C ++实现的循环方法。
# Using Rcpp loops
src <-
"Rcpp::NumericMatrix subs_cpp(Rcpp::NumericMatrix X, Rcpp::NumericVector Y, Rcpp::NumericVector Z){
for(int i = 0; i < Y.length(); ++i){
for(int j = 0; j < X.ncol(); ++j){
for(int k = 0; k < X.nrow(); ++k){
if(X(k, j) == Y(i)){
X(k, j) = Z(i);
}
}
}
}
return X;
}"
Rcpp::cppFunction(src)
method_3 <- function(){
subs_cpp(as.matrix(X), Y, Z)
}
在这里,我对这些方法进行基准测试。
# Run benchmarking
microbenchmark::microbenchmark(method_1(), method_2(), method_3(), times = 10)
# Unit: milliseconds
# expr min lq mean median uq max neval
# method_1() 16861.5447 17737.2124 19321.5674 18628.8573 20117.0159 25506.208 10
# method_2() 671.2223 677.6029 1111.3935 738.6216 1657.0542 2163.137 10
# method_3() 316.9810 319.1484 481.3548 320.2337 326.7133 1477.454 10
如您所见,Rcpp
方法是迄今为止最快的方法。
您还可以比较输出,以确保它们使用较小的栅格产生相同的结果。
# Examine all three outputs with smaller raster
X <- raster(matrix(rep(Y, 3), ncol = 9))
plot(method_1(), main = "Method 1")
plot(method_2(), main = "Method 2")
plot(raster(method_3()), main = "Method 3") # Needs to converted into a raster
它们看起来都一样。请注意,对于第三种方法,需要将结果从矩阵转换回栅格。