在R中,使用与基本R函数同名的变量到底有什么问题?

问题描述

| 通常,使用在基R中具有相同名称的函数的变量名称似乎被认为是较差的编程实践。 例如,写以下内容很诱人:
data <- data.frame(...)
df   <- data.frame(...)
现在,函数
data
加载数据集,而函数
df
计算f密度函数。 同样,写以下内容也很诱人:
a <- 1
b <- 2
c <- 3
这被认为是不好的形式,因为函数
c
将合并其参数。 但是:在R函数work5ѭ中,用来计算线性模型的函​​数中,
data
被用作自变量。换句话说,
data
成为
lm
函数内部的显式变量。 因此:如果R核心团队可以为变量和函数使用相同的名称,那么什么使我们成为凡人? 答案不是R会感到困惑。请尝试以下示例,在此示例中,我明确分配了名称为“ 4”的变量。 R完全不会与变量和函数之间的区别混淆:
c(\"A\",\"B\")
[1] \"A\" \"B\"

c <- c(\"Some text\",\"Second\",\"Third\")
c(1,3,5)
[1] 1 3 5

c[3]
[1] \"Third\"
问题:具有与基本R函数同名的变量到底有什么问题?     

解决方法

真的没有。 R在寻找功能时通常不会搜索对象(非功能对象):
> mean(1:10)
[1] 5.5
> mean <- 1
> mean(1:10)
[1] 5.5
> rm(mean)
> mean(1:10)
[1] 5.5
@Joris和@Sacha所示的示例是糟糕的编码使您脱颖而出的地方。编写“ 12”的一种更好的方法是:
foo <- function(x,fun) {
    fun <- match.fun(fun)
    fun(x)
}
使用时会给出:
> foo(1:10,mean)
[1] 5.5
> mean <- 1
> foo(1:10,mean)
[1] 5.5
在某些情况下,这会吸引您,@ Joris的示例中带有
na.omit
的示例就是一个例子,由于
lm()
中使用了标准,非标准评估,因此IIRC正在进行中。 几个答案还将
T
vs
TRUE
问题与功能掩盖问题混为一谈。因为
T
TRUE
不是函数,所以它在@Andrie \'s Question的范围之外。     ,问题不在于计算机,而在于用户。通常,代码很难调试。错字很容易制作,因此,如果这样做:
c <- c(\"Some text\",\"Second\",\"Third\")
c[3]
c(3)
您得到正确的结果。但是,如果您错过了代码中的某个地方,然后键入ѭ22of而不是
c[3]
,发现错误就不会那么容易了。 范围界定还可能导致非常混乱的错误报告。采取以下有缺陷的功能:
my.foo <- function(x){
    if(x) c <- 1
    c + 1
}

> my.foo(TRUE)
[1] 2
> my.foo(FALSE)
Error in c + 1 : non-numeric argument to binary operator
借助更复杂的功能,这可以引导您走上无路可走的调试路径。如果在上述功能中将
c
替换为
x
,则错误将显示为\“
object \'x\' not found
\”。这将更快地导致您的编码错误。 紧接着,它可能导致相当混乱的代码。像“ 28”这样的代码比“ 29”对大脑的要求更多。同样,这是一个简单的例子,但是可以有所作为。 显然,您也会遇到错误。当您期望某个功能时,您将无法获得它,这可能会引起另一组烦人的错误:
my.foo <- function(x,fun) fun(x)
my.foo(1,sum)
[1] 1
my.foo(1,c)
Error in my.foo(1,c) : could not find function \"fun\"
一个更现实的(和现实生活中的)示例如何导致麻烦:
x <- c(1:10,NA)
y <- c(NA,1:10)
lm(x~y,na.action=na.omit)
# ... correct output ...
na.omit <- TRUE
lm(x~y,na.action=na.omit)
Error in model.frame.default(formula = x ~ y,na.action = na.omit,drop.unused.levels = TRUE) : attempt to apply non-function
如果您的代码中出现
na.omit <- TRUE
50行,请尝试找出问题所在。 在@Andrie的评论后编辑的答案,包括混淆错误报告的示例     ,R对此非常健壮,但是您可以考虑打破它的方法。例如,考虑以下功能:
foo <- function(x,fun) fun(x)
只需将
fun
应用于
x
。这不是最漂亮的方法,但是您可能会在某人的脚本中遇到此问题。适用于
mean()
> foo(1:10,mean)
[1] 5.5
但是,如果我分配一个新值表示它坏了:
mean <- 1
foo(1:10,mean)

Error in foo(1:10,mean) : could not find function \"fun\"
这种情况很少发生,但有可能发生。如果同一件事意味着两件事,也会让人感到困惑:
mean(mean)
由于使用所需的任何其他名称都很简单,为什么不使用不同于基本R函数的名称呢?同样,对于某些R变量,这一点变得更加重要。考虑重新分配
\'+\'
功能!另一个很好的例子是重新分配
T
F
,这会破坏很多脚本。     ,我认为问题在于人们在全球环境中使用这些功能时,由于一些您不应该得到的意外错误而可能导致挫败感。想象一下,您只是运行了一个可重现的示例(也许是很长的示例),该示例重写了您在模拟中使用的功能之一,它花了很长时间才能到达您想要的位置,然后突然由于一个有趣的错误而崩溃。 在关闭的环境(如函数)中使用已经存在的函数名作为变量,在函数关闭后将被删除,不会造成伤害。假定程序员知道这种行为的所有后果。     ,答案很简单。好吧,有点。 底线是您应该避免混乱。从技术上讲,没有理由给变量取适当的名称,但这使您的代码更易于阅读。 想象一下,其中包含诸如
data()[1]
之类的代码的代码行(这行可能没有意义,但这仅是示例):尽管您现在很清楚这里使用的是函数数据,注意到那里有一个名为data的data.frame的读者可能会感到困惑。 而且,如果您不乐于助人,请记住,读者可能会在半年内成为您,试图弄清楚您正在使用“旧代码”做什么。 从一个已经学会使用长变量名和命名约定的人那里获取它:它会有所回报!     ,我同意@Gavin Simpson和@Nick Sabbe的观点,这并不是真正的问题,但这更多是代码的可读性问题。因此,生活中的许多事情都是约定俗成的问题。 我认为提供一般建议是一个很好的约定:不要像基础R函数那样命名变量! 该建议的工作方式与其他好的建议一样。例如,我们都知道我们不会喝太多酒,也不要吃太多不健康的食物,但是我们有时会不遵循这些建议,而在吃太多垃圾食品时会喝醉。 对于此建议也是如此。将数据参数命名为“ 1”显然很有意义。但是,命名数据向量
mean
的意义要小得多。尽管在某些情况下这似乎也很合适。但是,为了清楚起见,请尽量避免这些情况。     ,尽管某些语言可能允许这样做,但要记住
IF IF THEN THEN ELSE ELSE
。通常,这被认为是非常差的做法。不是我们不想给您机会展​​示您对语言的高级知识,而是有一天,我们将不得不处理该代码,而我们只是凡人。 因此,如果您感到异常温暖和模糊,可以避免破坏夜间构建,并为变量提供合理的名称,并使用一致的大小写形式,从而节省编程技巧。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...