【发布时间】:2018-03-06 13:50:55
【问题描述】:
我对@987654322@ 的用法感到困惑。查看?setReplaceMethod 并没有提供解释,谷歌搜索也没有什么帮助。
问题:请解释setReplaceMethod(),它的用法和它是如何工作的(最好有一个例子)。
【问题讨论】:
-
是的,
setMethod("$<-")仍然无法解释。
我对@987654322@ 的用法感到困惑。查看?setReplaceMethod 并没有提供解释,谷歌搜索也没有什么帮助。
问题:请解释setReplaceMethod(),它的用法和它是如何工作的(最好有一个例子)。
【问题讨论】:
setMethod("$<-") 仍然无法解释。
这是我发现的。正如@Hong Ooi 在cmets 中指出的那样setReplaceMethod("fun") 与setMethod("fun<-") 相同,因此setReplaceMethod 用于在R 的S4 对象系统中创建通用替换函数的方法。
what-are-replacement-functions-in-r 中解释了什么是替换函数。非常粗略,如果你有一个名为fun<- 的函数,因为它的名字以<- 结尾,你可以写fun(x)<-a,而R 将读为x <- "fun<-"(x,a)。
S4 - Advanced R 中描述了 S4 对象系统。
举个例子,从为 S4 泛型函数创建一个方法开始可能会更容易,这不是替代函数:
## Define an S4 class 'Polygon' and an object of this class
setClass("Polygon", representation(sides = "integer"))
p1 <- new("Polygon", sides = 33L)
## Define a generic S4 function 'sides'
sides <- function(object){ NA }
setGeneric("sides")
## sides returns NA
sides( p1 )
## Define a method for 'sides' for the class 'Polygon'
setMethod("sides", signature(object = "Polygon"), function(object) {
object@sides
})
## Now sides returns the sides of p1
sides( p1 )
为泛型替换函数创建方法类似:
## Define a generic replacement function 'sides<-'
"sides<-" <- function(object, value){ object }
setGeneric( "sides<-" )
## The generic 'sides<-' doesn't change the object
sides( p1 ) <- 12L
sides( p1 )
## Define a method for 'sides<-' for the class 'Polygon',
## setting the value of the 'sides' slot
setMethod( "sides<-", signature(object = "Polygon"), function(object, value) {
object@sides <- value
object
})
## Now 'sides<-' change the sides of p1
sides( p1 ) <- 12L
sides( p1 )
您还询问了$<-。我的猜测是:x$name<-value 被解释为"$"(x,name)<-value,然后被解释为x <- "$<-"(x,name,value)。请注意,泛型函数$<- 已经定义(isGeneric("$<-")),所以我们只为我们的多边形类定义一个方法:
setMethod( "$<-", signature(x = "Polygon"), function(x, name, value) {
if( name=="sides" ){
x@sides <- value
}
x
})
## Nothing changes if we try to set 'faces'
p1$faces <- 3L
p1
## but we can set the 'sides'
p1$sides <- 3L
p1
请注意,参数 x、name 和 value 由泛型决定。
【讨论】:
p1 <- "$<-"(p1,sides,777) 或"$"(x,sides)<-777 会返回错误。我认为您对答案后半部分的解释不正确
sides 被定义为整数,而777 在R 中不是整数!你必须写777L:比较class(777)和class(777L)。事实上p1 <- "$<-"(p1,sides,777L) 和"$"(p1,sides)<-777L 工作。
4+5 产生 9。我想我不明白它什么时候决定一个数字是数字还是其他东西
isGeneric("$<-") 是在哪里定义的?
?isGeneric。
对于$、[ 或names() 等提取方法,$<-、[<- 或names<- 等替换 方法替换会被提取出来。
以列表为例:
example_object <- list(a = 1, b = 2)
# the extract method $, when called with arguments example_object and a,
# extracts and returns the value 1
example_object$a
# [1] 1
# the replace method $<-, when called with arguments example_object, a, and 42,
# replaces the value 1 (at example_object$a) with the value 42
example_object$a <- 42
example_object
# $a
# [1] 42
#
# $b
# [1] 2
因此,对于 S4 类,setMethod("$", ...) 将定义提取方法 $ 的行为,而 setMethod("$<-", ...) 或等效的 setReplaceMethod("$", ...) 将定义替换方法 $<- 的行为。 setReplaceMethod("$") 只是为了比setMethod("$<-") 更具表现力,以明确您正在为$ 定义替换方法。
使用 S4 类的示例:
setClass("MyClass", representation(a = "numeric", b = "numeric"))
setMethod("$", signature = "MyClass",
function (x, name) {
if ( name == "a" ) {
return(x@a)
}
else if ( name == "b" ) {
return(x@b)
}
else {
stop(paste("No slot", name, "for MyClass"), call. = FALSE)
}
}
)
# [1] "$"
my_object <- new("MyClass", a = 1, b = 2)
my_object@a
# [1] 1
my_object$a
# [1] 1
my_object@a <- 42
my_object@a
# [1] 42
my_object$a <- 3.14 # will not work because we have not set the method for $<-
# Error in `$<-`(`*tmp*`, a, value = 3.14) :
# no method for assigning subsets of this S4 class
my_object@a
# [1] 42
setReplaceMethod("$", signature = "MyClass",
function(x, name, value) {
if ( name == "a" ) {
x@a <- value
return(x)
}
else if ( name == "b" ) {
x@b <- value
return(x)
}
else {
stop(paste("No slot", name, "for MyClass"),
call. = FALSE)
}
}
)
# [1] "$<-"
my_object$a <- 3.14
my_object@a
# [1] 3.14
【讨论】:
df<-as.data.frame(cbind(c(1,2,3), c(4,5,6))) 然后colnames(df) <- c("name1", "name2")。这叫什么?
help("colnames<-") 显示行和列名称的帮助文件,用法部分显示提取方法colnames(x, ...) 和替换方法colnames(x) <- value。
setReplaceMethod() 的一般情况?您的回答似乎解决了提取方法的特殊情况。