tl;dr:subset 函数调用不同的函数(具有不同的方法),具体取决于它所提供的对象类型。在上面的例子中,subset(numbers, ) 使用subset.default 而subset(frame, ) 使用subset.data.frame。
R 内置了几个面向对象的系统。最简单和最常见的称为 S3。这种 OO 编程风格实现了 Wickham 所说的“通用函数 OO”。在这种 OO 风格下,称为泛型函数的对象查看对象的类,然后将适当的方法应用于对象。如果不存在直接方法,则始终有可用的默认方法。
要更好地了解 S3 和其他 OO 系统的工作原理,您可以查看Advanced R 站点的相关部分。为对象找到正确方法的过程称为方法分派。您可以在帮助文件?UseMethod 中阅读更多相关信息。
如?subset 的详细信息部分所述,subset 函数“是一个通用函数”。这意味着subset 在第一个参数中检查对象的类,然后使用方法分派将适当的方法应用于对象。
泛型函数的方法编码为
.
可以使用methods(<generic function name>) 找到。对于subset,我们得到
methods(subset)
[1] subset.data.frame subset.default subset.matrix
see '?methods' for accessing help and source code
表示如果对象有data.frame类,那么subset调用subset.data.frame的方法(函数)。定义如下:
subset.data.frame
function (x, subset, select, drop = FALSE, ...)
{
r <- if (missing(subset))
rep_len(TRUE, nrow(x))
else {
e <- substitute(subset)
r <- eval(e, x, parent.frame())
if (!is.logical(r))
stop("'subset' must be logical")
r & !is.na(r)
}
vars <- if (missing(select))
TRUE
else {
nl <- as.list(seq_along(x))
names(nl) <- names(x)
eval(substitute(select), nl, parent.frame())
}
x[r, vars, drop = drop]
}
请注意,如果缺少子集参数,则第一行
r <- if (missing(subset))
rep_len(TRUE, nrow(x))
产生一个与 data.frame 和最后一行长度相同的 TRUES 向量
x[r, vars, drop = drop]
将此向量输入到行参数中,这意味着如果您不包含子集参数,则subset 函数将返回 data.frame 的所有行。
从methods 调用的输出中可以看出,subset 没有原子向量的方法。这意味着,作为你的错误
subset.default(numbers, ) 中的错误
当您将subset 应用于向量时,R 调用定义为的subset.default 方法
subset.default
function (x, subset, ...)
{
if (!is.logical(subset))
stop("'subset' must be logical")
x[subset & !is.na(subset)]
}
当缺少子集参数时,subset.default 函数会抛出 stop 错误。