简体   繁体   English

如何将 R 代码从旧包的功能转换为当前 R 版本中的工作功能

[英]How can I turn R code from an old package's function into a working function in the current version of R

I typically use Matlab and am only an amateur when it comes to R. I have been trying to use someone elses code from 2011 and it is calling for a function called 'xyValues'.我通常使用 Matlab 并且在 R 方面只是一个业余爱好者。我一直在尝试使用 2011 年以来其他人的代码,它正在调用一个名为“xyValues”的函数。 I have found that this used to be function within the Raster package (version 1.5.8) but no longer appears in the current version.我发现这曾经在 Raster 包(版本 1.5.8)中起作用,但不再出现在当前版本中。 The old raster package is incompatible with newer versions of R. I have tried downgrading R but then that causes other issues.旧的光栅包与较新版本的 R 不兼容。我曾尝试降级 R,但这会导致其他问题。

I have downloaded the tar.gz file and extracted the code for the xyValues function.我已经下载了 tar.gz 文件并提取了 xyValues 函数的代码。 I tried to paste it into my newer version of the Raster package, but unsurprisingly, it didn't work.我试图将它粘贴到我较新版本的 Raster 包中,但不出所料,它不起作用。 Is there an easy way for me to turn the code for this function into an actual function that I can save and then use (as if I wrote the function myself)?有没有一种简单的方法可以将这个函数的代码转换成一个我可以保存然后使用的实际函数(就像我自己编写的函数一样)? I could do this easily in matlab, but it seems the process for writing a function is a little different in R and I don't really know where to start?我可以在 matlab 中轻松做到这一点,但在 R 中编写函数的过程似乎有些不同,我真的不知道从哪里开始? I see some variations of this question on this site, but I'm wondering if it is possible for a new user of R (like me) to be able to do what I am suggesting.我在这个网站上看到了这个问题的一些变体,但我想知道 R 的新用户(像我一样)是否能够按照我的建议去做。 Perhaps it is only possible if you have a lot of knowledge regarding R. This is the code I extracted:也许只有当您对 R 有很多了解时才有可能。这是我提取的代码:

# Author: Robert J. Hijmans
# contact: r.hijmans@gmail.com
# Date : November 2008
# Version 0.9
# Licence GPL v3


if (!isGeneric("xyValues")) {
  setGeneric("xyValues", function(object, xy, ...)
    standardGeneric("xyValues"))
}   


setMethod("xyValues", signature(object='Raster', xy='SpatialPoints'), 
          function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE,...) { 
            callGeneric(object, coordinates(xy),  method, buffer, fun, na.rm, ...)
          } 
)


setMethod("xyValues", signature(object='Raster', xy='data.frame'), 
          function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE,...) { 
            callGeneric(object, as.matrix(xy), method, buffer, fun, na.rm, ...)
          } 
)


setMethod("xyValues", signature(object='Raster', xy='vector'), 
          function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE, ...) { 
            if (length(xy) == 2) {
              callGeneric(object, matrix(xy, ncol=2), method, buffer, fun, na.rm,  ...)
            } else {
              stop('xy coordinates should be a two-column matrix or data.frame, or a vector of two numbers.')
            }
          } )


setMethod("xyValues", signature(object='RasterLayer', xy='matrix'), 
          function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE, ...) { 

            if (dim(xy)[2] != 2) {
              stop('xy has wrong dimensions; it should have 2 columns' )
            }

            if (! is.null(buffer)) {
              if (method != 'simple') { warning('method argument is ignored when a buffer is used') }
              return( .xyvBuf(object, xy, buffer, fun, na.rm=na.rm) )
            }

            if (method=='bilinear') {
              return(.bilinearValue(object, xy))
            } else if (method=='simple') {
              cells <- cellFromXY(object, xy)
              return(.readCells(object, cells))
            } else {
              stop('invalid method argument. Should be simple or bilinear.')
            }
          } 
)   


setMethod("xyValues", signature(object='RasterStack', xy='matrix'), 
          function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE, ...) { 
            .xyvStackBrick(object, xy, method, buffer, fun, na.rm, ...)
          } )

setMethod("xyValues", signature(object='RasterBrick', xy='matrix'), 
          function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE, ...) { 
            .xyvStackBrick(object, xy, method, buffer, fun, na.rm, ...)
          } )


.xyvStackBrick <- function(object, xy, method='simple', buffer=NULL, fun=NULL, na.rm=TRUE, ...) { 

  dots <- list(...)
  layer <- dots$layer
  n <- dots$nl
  nls <- nlayers(object)

  if (is.null(layer)) { layer <- 1 } 
  if (is.null(n)) { n <- nls } 
  layer <- min(max(1, round(layer)), nls)
  n <- min(max(1, round(n)), nls-layer+1)

  if (dim(xy)[2] != 2) {
    stop('xy has wrong dimensions; there should be 2 columns only' )
  }

  if (! is.null(buffer)) {
    if (method != 'simple') { warning('method argument is ignored when a buffer is used') }
    return( .xyvBuf(object, xy, buffer, fun, na.rm, layer=layer, n=n) )
  }

  if (method == 'bilinear') {
    result <- .bilinearValue(object, xy, layer=layer, n=n)
    return(result)      

  } else if (method=='simple') {

    cells <- cellFromXY(object, xy)
    return( cellValues(object, cells, layer=layer, n=n) )

  } else {
    stop('invalid method argument. Should be simple or bilinear.')
  }
}

As a followup to this question, initially, when I wanted to see if this function was in my raster package I tried typing help(xyValues) and nothing came up (because it didn't exist).作为这个问题的后续,最初,当我想查看这个函数是否在我的光栅包中时,我尝试输入help(xyValues)并没有出现任何结果(因为它不存在)。 However, when I try this for functions that DO exist within the package, they too, are not showing up.但是,当我对包中确实存在的函数尝试此操作时,它们也没有出现。 Does this mean my raster package isn't loaded correctly?这是否意味着我的光栅包没有正确加载?

The piece of code I am using with the function in it is:我在函数中使用的一段代码是:

elevgrid <- xyValues(elev,cbind(xygrid[,2],xygrid[,1]))

where elev is a Formal class Rasterlayer of size 920x1000 and xygrid is 4800 obs of 2 variables (xy coordinates)其中elev是大小920x1000一个正式的类Rasterlayer和xygrid是2个变量(xy坐标)的4800个OBS

I tried using:我尝试使用:

> source("C:/Users/Documents/raster/R/xyValues.R")

but I got all these errors:但我遇到了所有这些错误:

in method for ‘xyValues’ with signature ‘object="Raster",xy="data.frame"’: no definition for class “Raster”
in method for ‘xyValues’ with signature ‘object="Raster",xy="vector"’: no definition for class “Raster”
in method for ‘xyValues’ with signature ‘object="RasterLayer",xy="matrix"’: no definition for class “RasterLayer”
in method for ‘xyValues’ with signature ‘object="RasterStack",xy="matrix"’: no definition for class “RasterStack”
in method for ‘xyValues’ with signature ‘object="RasterBrick",xy="matrix"’: no definition for class “RasterBrick”
Warning message:
in method for ‘xyValues’ with signature ‘object="Raster",xy="SpatialPoints"’: no definition for classes “Raster”, “SpatialPoints” 

I tried the getvalues and approxNA functions and got this:我尝试了getvaluesapproxNA函数并得到了这个:

> elevgrid <- getValues(elev,cbind(xygrid[,2],xygrid[,1]))
Error in (function (classes, fdef, mtable)  : 
  unable to find an inherited method for function ‘getValues’ for signature ‘"RasterLayer", "matrix", "missing"’
> elevgrid <- approxNA(elev)
Error in (function (classes, fdef, mtable)  : 
  unable to find an inherited method for function ‘approxNA’ for signature ‘"RasterLayer"’

Couple of ways you can address this issue.您可以通过多种方式解决此问题。

First and foremost:首先也是最重要的:

Do you actually need the old function to do the work, or can it be done with a newer generation function?你真的需要旧函数来完成这项工作,还是可以用更新一代的函数来完成? I'm not really clear what you're trying to do, so I can't suggest a better function.我不太清楚你要做什么,所以我不能建议更好的功能。

Based on my assumptions through what you're doing and the help documentation for xyValues() this is my guess.根据我对您所做的事情的假设以及xyValues()的帮助文档,这是我的猜测。 First you need to use approxNA() ( requires stack ) this performs the interpolation as it would in xyValues() to fill in NA s in your raster.首先,您需要使用approxNA()需要堆栈),它执行插值,就像在xyValues()中填充光栅中的NA Then you need to turn it into a data.frame or a vector of values.然后您需要将其转换为data.frame或值vector This can be done with either as.data.frame() or getValues() .这可以通过as.data.frame()getValues() If you do not have NAs you need to fill, you can just pull the values with getValues() or as.data.frame()如果您没有需要填充的 NA,则可以使用getValues()as.data.frame()提取值

dat.r <- raster(matrix(nrow = 100,ncol = 100,sample(x = 1:1000,size = 10000,replace = T)))
dat.vector <- getValues(dat.r)
dat.dataframe <- as.data.frame(dat.r)

If you do have NAs - I found a suggestion here: Fill in gaps (eg not single cells) of NA values in raster using a neighborhood analysis如果您确实有 NA - 我在这里找到了一个建议: 使用邻域分析填充栅格中 NA 值的间隙(例如,不是单个单元格)

## Add in some NAs
dat.r[sample(1:10000,1000)] <- NA
fill.na <- function(x) {
  center = 0.5 + (width*width/2) 
  if( is.na(x)[center] ) {
    return( round(mean(x, na.rm=TRUE),0) )
  } else {
    return( round(x[center],0) )
  }
}  
  
width = 9
r2 <- focal(dat.r, w = matrix(1,width,width), fun = fill.na, 
            pad = TRUE, na.rm = FALSE)
dat.vector <- getValues(r2)
dat.dataframe<- as.data.frame(r2)

Second:第二:

You can just source everything you need from the unpacked tar.您可以从解压缩的 tar 中获取所需的一切。

source("~/raster_1.5-8/raster/R/xyValues.R")
source("~/raster_1.5-8/raster/R/xyValuesBuffer.R")
source("~/raster_1.5-8/raster/R/bilinearValue.R")
source("~/raster_1.5-8/raster/R/readCells.R")

~ is the directory to where you have unpacked raster_1.5-8 A quick noted on why there are 4 scripts and not just the 1 you are after. ~ 是您解压 raster_1.5-8 的目录 快速说明为什么有 4 个脚本,而不仅仅是您想要的 1 个。 Any function with a leading .任何带有前导 . is a hidden function that gets loaded with the package but is not explictly executable.是一个隐藏的函数,它随包一起加载但不是显式可执行的。 As you are not instantiating the package, you need these helper functions.由于您没有实例化包,因此您需要这些辅助函数。

Third Not Recommended :第三个不推荐

You can attempt to install and older version of the package following the instructions here.您可以按照此处的说明尝试安装旧版本的软件包。 https://support.rstudio.com/hc/en-us/articles/219949047-Installing-older-versions-of-packages The code you would need is: https://support.rstudio.com/hc/en-us/articles/219949047-Installing-older-versions-of-packages您需要的代码是:

require(devtools)
install_version("raster", version = "1.5-8", repos = "http://cran.us.r-project.org/")

This may result in problems down the line if you are trying to use current generation functions, so I would not recommend this method如果您尝试使用当前生成函数,这可能会导致问题,所以我不推荐这种方法

the xyValyes method extracted values from a raster using points (xy coordinates). xyValyes 方法使用点(xy 坐标)从栅格中提取值。 This function has been replaced with extract .此功能已替换为extract So instead of所以代替

library(raster)
xyValues(x, xy, ...)

You should be able to do你应该能够做到

extract(x, xy, ...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM