为什么使用`<<-`被人所不齿,如何避免使用它?

9
我关注了这里的讨论,并且好奇为什么在R中使用<<-被认为不好。它会带来什么样的困惑?
我还想得到一些有关如何避免使用<<- 的提示。我经常使用以下方法。例如:
### Create dummy data frame of 10 x 10 integer matrix.
### Each cell contains a number that is between 1 to 6.
df <- do.call("rbind", lapply(1:10, function(i) sample(1:6, 10, replace = TRUE)))

我想要实现的是将每个数字降低1,也就是所有的2都变成1,所有的3都变成2等等。因此,所有的n都会变成n-1。我通过以下方式实现这一点:
df.rescaled <- df
sapply(2:6, function(i) df.rescaled[df.rescaled == i] <<- i-1))

在这种情况下,我该如何避免使用<<-?理想情况下,我希望能够将sapply结果输入到另一个变量中,类似于:
df.rescaled <- sapply(...)

请参见https://dev59.com/TmzXa4cB1Zd3GeqPX9PV#14166812 - Ari B. Friedman
2个回答

17

第一点

<<- 不是分配给全局变量的运算符。它试图将变量分配到最近的父环境中。因此,比如说,这会造成混淆:

f <- function() {
    a <- 2
    g <- function() {
        a <<- 3
    }
}

那么,

> a <- 1
> f()
> a # the global `a` is not affected
[1] 1

第二点

您可以通过使用 Reduce 实现:

Reduce(function(a, b) {a[a==b] <- a[a==b]-1; a}, 2:6, df)

或者 apply

apply(df, c(1, 2), function(i) if(i >= 2) {i-1} else {i})

但是

简单地说,这就足够了:

ifelse(df >= 2, df-1, df)

感谢您提供的代码替代方案。非常感激。您能详细说明一下Reduce函数吗?即使我已经阅读了?Reduce,但我对它的逻辑流程仍不太清楚。我理解您正在尝试在Reduce中创建一个带有2个变量的函数。对于所有在a中等于b-1的元素。接着是;a和其余的语法,我对此感到困惑。 - RJ-
Reduce也被称为Fold,是函数式编程中常用的方法。这里有一个简单的解释。维基百科 - kohske

5
你可以将<<-视为全局赋值(大致如此,因为正如kohske所指出的那样,它会分配给顶级环境,除非变量名存在于更近的环境中)。这种方式的缺点示例在此处: R和Stata中全局变量的危险示例

1
更合理的想法是将<<-视为一种分配方式,它检查封闭环境,因为x <<- value等同于assign('x', value, inherits=TRUE)。我使用它的目的与assign('x', value, pos=.GlobalEnv)完全不同。 - Steve Weston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接