R:如何使用for循环计算和排序两个变量

时间:2016-08-23 09:07:38

标签: r sorting for-loop

我想执行IDW交叉验证,并找出哪个“power”值给出最小的RMSE。为了做到这一点,我想将“power”和“RMSE”值存储在一个列表中,并按最小的RMSE排序,例如

我想要这样的事情:

     RMSE    Power
[1,] 1.230   2.5
[2,] 1.464   1.5
[3,] 1.698   2.0
[4,] 1.932   3.0

到目前为止我所拥有的是:

require(sp)
require(gstat)
data("meuse")

#### create grid:
pixels <- 500 #define resolution
#define extent
raster.grd <- expand.grid(x=seq(floor(min(x=meuse$x)),
                            ceiling(max(x=meuse$x)),
                            length.out=pixels),
                      y=seq(floor(min(y=meuse$y)),
                            ceiling(max(y=meuse$y)),
                            length.out=pixels))
# convert the dataframe to a spatial points and then to a spatial pixels
grd.pts <- SpatialPixels(SpatialPoints((raster.grd)))
grd <- as(grd.pts, "SpatialGrid")
gridded(grd) = TRUE

#### perform IDW and loop through different power-values
power = seq(from = 1.5, to = 3, by = 0.5)
results=list()
results.cv=list()
for(i in power) {
    results[[paste0(i,"P")]] <- gstat::idw(meuse$zinc ~ 1, meuse, grd, idp = i)
    results.cv[[paste0(i,"P")]] <- krige.cv(zinc ~ 1, meuse, nfold = nrow(meuse),set = list(idp = i))
    }

现在我尝试使用for循环计算和存储RMSE:

results_rmse <- list()
pwr <- names(results.cv)

for(i in results.cv){ #for each Element (1.5P, 2P, etc) in results.cv
    for(j in 1:length(pwr)){ #for each Power
       results_rmse <- sqrt(mean(i$residual^2))
       print(pwr[j])
       }
   print(paste("RMSE",results_rmse))
   } 

但是通过这个循环,它可以单独打印每个RMSE。所以我改变了这样的代码

results_rmse[[i]] <- sqrt(mean(i$residual^2))

但后来我收到错误

Error in results_rmse[[i]] <- sqrt(mean(i$residual^2)) :  invalid subscript type 'S4'

我尝试了几个版本的for循环,但我甚至无法弄清楚如何将值存储在列表中,更不用说用最小的RMSE对它们进行排序。

1 个答案:

答案 0 :(得分:0)

在RMSE计算中有一个j的额外循环,就我理解的问题而言,这是不需要的。此外,我重新安排循环,使其循环遍历一系列元素,而不是按名称调用它们。

# Data, because your script doesn't run for me. The rest is identical from your code
for(i in power) {
    results.cv[[paste0(i,"P")]]$residual <- rnorm(50)
}

# Fixed loop
for(i in 1:length(results.cv)){ 
    results_rmse[[i]] <- sqrt(mean(results.cv[[i]]$residual^2))
}
names(results_rmse) <- names(results.cv)

或者,使用for函数可以避免apply循环。结果是与输入名称对应的命名列表,因此可以省略最后一行以实现相同的results_rmse

results_rmse <- lapply(results.cv, function(x) sqrt(mean(x$residual^2)))

要打印您在问题中显示的数据:

cbind(RMSE=unlist(results_rmse), Power=power)