通常我想知道神秘错误来自哪里,但现在我的问题是神秘的错误来自何处。
让
using Plots; gr()
histogram(randn(1000), yaxis = (:log10, (1,Inf)))
如果我输入
numbers <- c(1, 2, 3)
frame <- as.data.frame(numbers)
(所以我想拿一些子集但忘记指定子集函数的subset-argument)然后R提醒我(应该这样):
subset.default(数字,)出错:
论证&#34;子集&#34;缺少,没有默认
但是当我输入
时subset(numbers, )
(与subset(frame,)
而不是向量相同),它不会给出错误,而只是返回(完整)数据帧。
这里发生了什么?为什么我不能得到我当之无误的错误信息?
答案 0 :(得分:8)
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
检查第一个参数中对象的类,然后使用方法分派将适当的方法应用于对象。
泛型函数的方法编码为
&LT;通用功能名称&gt;。&lt;班级名称&gt;
可以使用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))
生成一个TRUES向量,其长度与data.frame相同,最后一行
x[r, vars, drop = drop]
将此向量提供给row参数,这意味着如果您没有包含子集参数,则subset
函数将返回data.frame的所有行。
正如我们从methods
调用的输出中看到的那样,subset
没有原子向量的方法。这意味着,作为您的错误
subset.default(数字,)中的错误
当您将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
时抛出错误。