使用命名向量时
vec <- c(a = 1, b = 2)
Run Code Online (Sandbox Code Playgroud)
我经常发现自己vec$a在应该写的时候通过写错误vec["a"]或vec[["a"]]使用相应的名称(不带名称)访问相应的值。
我认为vec$a出现错误是违反直觉的,因为$通常会提取命名的事物。这种感觉甚至似乎得到了支持,例如在?Extract示例用法为的中x$name,这是否不完美地适合命名向量?
那让我开始思考是否可能使$运算符超负荷以处理命名向量。但是,我对R中的运算符重载不是很有经验,并且我了解(例如,从这里的答案)在重载基本运算符时应谨慎。
我的互连问题:有,为什么我不应该超载的原因$描述说我不理解?也就是说,在某种程度上,这不是R中的默认值吗?如果没有,我将如何明智地这样做?
我了解实际上,即使只是出于可移植性的原因,这可能不是一个好主意,但我仍然很好奇。
有时方法重载是一件好事;data.table:::$<-.data.table对于原始函数,对于某些类(例如,和)是可行的tibble:::$.tbl_df,对于基类则不是微不足道的。总的来说,我认为尝试这样做是一个坏主意。
一种惯用的方法是提供支持它的 S3 方法,例如$.numeric. 这将允许您严格控制此方法对特定类型对象的使用(在本例中,向量numeric ,不会在lists 上触发)。不幸的是,因为$是一个原始函数,所以它不允许在基本 R 对象类(例如$.numeric.
如果您愿意重新分类要应用此功能的向量,则可以这样做:
`$.quux` <- function(x, name) x[name]
vec <- c(a = 1)
class(vec) <- c("quux", class(vec))
vec$a
# a
# 1
vec$b
# <NA>
# NA
Run Code Online (Sandbox Code Playgroud)
不幸的是,这需要您重新创建class任何您想要执行此操作的对象。
另一种选择是重写$自身:
`$` <- function(x, name) x[deparse(substitute(name))]
c(a=1)$a
# a
# 1
Run Code Online (Sandbox Code Playgroud)
但这有很多问题:它影响 的每个正常使用$,包括非向量参数(尝试mtcars$mpg看看它现在返回单列data.frame而不是向量的正常行为)和赋值(mtcars$mpg <- ...失败)。当然可以尝试捕获每一种特殊情况,但您总是会错过一些极端情况、某些对象类型,或者导致一些其他假设的行为出现错误,从而破坏其他事情。
虽然我同意这种行为可能看起来有点不一致,但老实说,有时改变这种行为会产生太多的二阶效应,超出了创可贴的作用。(与这种变化的一个密切的类比是 python2 与 python3:这种“过渡”始于 2008 年 12 月,随着 python-3 的第一个版本的发布,尽管 python-2 据称已于 2020 年1 月终止生命,但它并没有迅速也不顺利。)
| 归档时间: |
|
| 查看次数: |
57 次 |
| 最近记录: |