使用另一个函数中的“subset”函数对自定义 S4 类进行子集化

DoD*_*Dx9 5 methods environment r subset r-s4

我正在尝试为我的自定义 S4 类定义一个subset方法。虽然当我直接向 提供子集标准时subset,子集按预期工作,但每当我在另一个函数中调用该方法时,该方法都会失败,其中子集标准从该函数传递到subset该函数。

S4 类myClass包含一个data.frame

# Define class
setClass("myClass", slots = c(data = "data.frame"))

# Initiate a myClass object
dat <- new("myClass", data = data.frame(Letter = c("A", "A", "B"), Number = c(1, 2, 3)))
Run Code Online (Sandbox Code Playgroud)

为了能够根据data.frameslot 中的内容对类进行子集化data,我定义了以下subset方法:


setMethod("subset", signature(x = "myClass"), function(x, ...) {
  x@data <- subset(x@data, ...)
  return(x)
})
Run Code Online (Sandbox Code Playgroud)

该方法在调用时按预期工作,如下所示:

# Assume we only want to retain entries containing the letter "A"
whichletter <- "A"

# Subset (does work)
subset(dat, Letter %in% whichletter)
Run Code Online (Sandbox Code Playgroud)
An object of class "myClass"
Slot "data":
  Letter Number
1      A      1
2      A      2
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试subset在另一个函数中运行时,其中子集标准是通过该函数的参数提供的,子集将不起作用:

# Random function that takes a letter `let`as argument
randomFunction <- function(object, let) {
  object_subsetted <- subset(object, Letter %in% let)
  return(object_subsetted)
}

# Subset (does not work)
randomFunction(object = dat, let = whichletter)
Run Code Online (Sandbox Code Playgroud)
Error in Letter %in% let: object 'let' not found
Run Code Online (Sandbox Code Playgroud)

这似乎是环境问题,但我无法弄清楚到底出了什么问题。有谁有如何避免此错误的建议?

DoD*_*Dx9 2

我刚刚发现这个这个似乎一起回答了我的问题。该问题与 S4 类的使用无关,而是由subset变量作用域的方式引起的。最初,我的定义是在对象内部subset寻找。通过专门定义在范围内计算表达式,但允许将范围扩展到(变量所属的),可以解决错误并允许我根据需要进行子集化。letx@datax@dataparent.frame()let

这是完整的代码:

# Define class
setClass("myClass", slots = c(data = "data.frame"))

# Initiate a myClass object
dat <- new("myClass", data = data.frame(Letter = c("A", "A", "B"), Number = c(1, 2, 3)))

# Define a subset method
setMethod("subset", signature(x = "myClass"), function(x, ...) {
  condition <- substitute(...)
  indices <- eval(condition, x@data, parent.frame())
  x@data <- x@data[indices, ]
  return(x)
})

# Suppose we want to subset to only retain entries with "A"
whichletter <- "A"

# What if we have a function that should pass the subsetting value to the subset
# function?
randomFunction <- function(object, let) {
  object_subsetted <- subset(object, Letter %in% let)
  return(object_subsetted)
}

# Test it (works now)
randomFunction(object = dat, let = "A")
randomFunction(object = dat, let = "B")
Run Code Online (Sandbox Code Playgroud)
An object of class "myClass"
Slot "data":
  Letter Number
1      A      1
2      A      2

An object of class "myClass"
Slot "data":
  Letter Number
3      B      3
Run Code Online (Sandbox Code Playgroud)

然而,正如 @JDL 所强调的,定义一个[方法可能更明智。