栅格图像的线性回归 - lm抱怨NAs

时间:2015-10-06 16:39:55

标签: r regression linear-regression raster lm

我确定这可以用几个字节来修复,但我花了好几个小时才完成这个简单的事情并且无法摆脱它。我经常不经常使用R.

我有5个代表5个光栅图像的asciigrid文件。一些像素确实有值,其他像素确实有NA。例如,第一张图片可能类似于:

NA  NA  NA  NA  NA
NA  NA  2   3   NA
NA  0.2 0.3 1   NA
NA  NA  4   NA  NA

,第二个可能是:

NA  NA  NA  NA  NA
NA  NA  5   1   NA
NA  0.1 12  12  NA
NA  NA  6   NA  NA

正如您所看到的,NA位置始终相同,我对此有100%的肯定。我愿意做的事情:

  • 使用read.asciigrid();
  • 阅读文件
  • 使用values()包中的raster获取长数组中的值;
  • 创建一个包含5行的矩阵,每行包含相应地图的值;
  • 线性拟合每列并获得系数。每列将代表一个像素,并且将有5个值对应于5个地图。
  • 使用系数值创建两个新的光栅图像。

我被lm 困住了。具体来说,它说:Error in lm.fit(...): 0 (non-NA) cases。但是,根据我对输入地图的了解,应该有所有 NAs的列或者没有 NA的列,如下所示:

NA   NA   NA   NA   0.2  2    NA  ... (lots of other columns)
NA   NA   NA   NA   2    2.1  NA
NA   NA   NA   NA   3    0.5  NA
NA   NA   NA   NA   12   6    NA
NA   NA   NA   NA   0.4  2    NA

我希望输出为:

NA   NA   NA   NA   ..   ..   NA

所以我可以使用系数创建一个新的光栅图像并保持NA位置。我哪里错了?在下面粘贴我的代码。谢谢。

library(sp)
library(raster)
library(fields)
names = c('...','...','...','...','...')
x = c(10,20,30,40,50)
x = log(x)
y = vector('list',length=length(x))
rasters = vector('list',length=length(x))
for (name in names) {
  ind = which(name == names)
  rasters[ind] = read.asciigrid(name)
  rasters[ind] = raster(rasters[[ind]])
  y[[ind]] = values(rasters[[ind]])
}

y = t(simplify2array(y))
lModel = lm(y ~ x) // Error here!

这是str(y)

的输出
  

num [1:5,1:1260630] NA NA NA NA NA NA NA NA NA NA ...(在某些时候会有数字)

修改

感谢@RobertH,我了解了raster::stackraster::calc。我试过了:

x <- log(c(10,20,30,40,50))
fun <- function(y) { lm(y ~ x)$coefficients }
r <- calc(s, fun)

Cannot use this function电话上模糊.calcTest。我看了raster:::.calcTest没有成功。我尝试管理所有y值为NA的情况,如下所示:

fun = function(y) { 
  if (any(!is.na(y))) { 
    lm(y ~ x)$coefficients
  } else { 
    NA
  }
}
r <- calc(s,fun)

现在它可以工作几分钟,但后来我得到了Error in setValues(out, x) : values must be numeric, integer, logical or factor。但是,将NA设置为栅格值是很常见的!我无法在这里看到错误。

1 个答案:

答案 0 :(得分:4)

这是获取栅格数据的方法

library(raster)
names = c('...','...','...','...','...')
s <- stack(names)
y <- values(s)

你现在可以这样做了。

x <- log(c(10,20,30,40,50))
# need to exclude the rows that are all NA
i <- rowSums(is.na(y)) < ncol(y)
coef <- apply(y[i, ], 1, function(y) lm(y ~ x)$coefficients)
aa <- matrix(NA, ncol=2, nrow=length(i))
aa[i, ] <- coef
b <- brick(s, nl=2)
values(b) <- aa

但你不需要这样做。要做这样的回归,我会做

fun <- function(y) { lm(y ~ x)$coefficients }
r <- calc(s, fun)

但是因为你的单元格只有NA值(跨层),这将失败(如上面的应用)。您需要编写一个函数来捕获这些情况:

funa <- function(y) { 
    if(all(is.na(y))) {
        c(NA, NA)
    } else {
        lm(y ~ x)$coefficients 
    }
}
r <- calc(s, funa)

或者更快的方法

X <- cbind(1, y)
invXtX <- solve(t(X) %*% X) %*% t(X)
quickfun <- function(i) (invXtX %*% i)
m <- calc(s, quickfun) 
names(m) <- c('intercept', 'slope')

参见?raster :: calc