【问题标题】:Inline expansion of variables in RR中变量的内联扩展
【发布时间】:2013-05-10 15:38:33
【问题描述】:

我很困惑何时将值视为变量,何时将 R 中的值视为字符串。在 Ruby 和 Python 中,我习惯于始终必须引用字符串,而始终处理未引用的字符串作为变量。 IE。

a["hello"] => a["hello"]
b = "hi"
a[b] => a["hi"]

但在 R 中,情况并非如此,例如

a$b < c(1,2,3)

这里的b是列的值/名称,而不是变量b。

c <- "b"
a$c => column not found (it's looking for column c, not b, which is the value of the variable c)

(我知道在这种特定情况下我可以使用 a[c],但还有很多其他情况。例如 ggplot(a, aes(x=c)) - 我想绘制作为 c 值的列,而不是名称 c )...

在其他 StackOverflow 问题中,我看到了引用、替代等内容。

我的问题是:是否有一种“扩展”变量并确保使用变量的值而不是变量名的通用方法?或者这不是 R 中的工作方式?

【问题讨论】:

  • 我认为下面提到的get 在技术上是最“通用”的解决方案。但是对于不同的情况,正确的答案可能会有所不同。例如请参阅下面的我的 cmets,了解在 ggplot 中不使用 aes_string 的可怕性。
  • @joran 我同意,但我认为使用$ 运算符没有任何正确 方式(或其他方式)。
  • 您可能会觉得这很有帮助:github.com/hadley/devtools/wiki/Computing-on-the-language(仍在进行中)

标签: r


【解决方案1】:

在您的示例中,a$ba[["b"]] 的语法糖。这是$ 符号与列表一起使用时的一个特殊功能。第二种形式符合您的预期 - a[[b]] 将返回 a 的元素,其名称 == 变量 b 的值,而不是名称 is 的元素> “b”。

数据框是相似的。对于数据框a$ 运算符指的是列名。所以a$ba[ , "b"] 相同。在这种情况下,要引用b 指示的a 列,请使用a[, b]

【讨论】:

    【解决方案2】:

    您发布的关于 $ 运算符的内容不起作用的原因非常微妙,并且通常与 R 中的大多数其他情况完全不同,在这些情况下您可以使用像 get 这样设计的函数为了这个目的。但是,调用a$b 相当于调用

    `$`(a , b)
    

    这提醒我们,在 R 中,一切都是一个对象。 $ 是一个函数,它需要两个参数。如果我们检查源代码,我们可以看到调用 a$c 并期望 R 将 c 评估为 "b"永远工作,因为在源代码中它指出:

    /* The $ subset operator.  
       We need to be sure to only evaluate the first argument.  
       The second will be a symbol that needs to be matched, not evaluated.  
    */
    

    它使用以下方法实现这一点:

    if(isSymbol(nlist) )
    SET_STRING_ELT(input, 0, PRINTNAME(nlist));
    else if(isString(nlist) )
    SET_STRING_ELT(input, 0, STRING_ELT(nlist, 0));
    else {
    errorcall(call,_("invalid subscript type '%s'"),
          type2char(TYPEOF(nlist)));
    }
    

    nlist 是您传递的参数do_subset_3(C 函数的名称$ 映射到),在本例中为c。它发现c 是一个符号,所以它用字符串替换它但不计算它。如果是字符串,则作为字符串传递。

    【讨论】:

      【解决方案3】:

      这里有一些链接可以帮助您了解 R 中评估的“为什么”和“何时”。它们可能很有启发性,甚至可能会有所帮助,如果没有别的,它们会让您知道您并不孤单:

      http://developer.r-project.org/nonstandard-eval.pdf

      http://journal.r-project.org/2009-1/RJournal_2009-1_Chambers.pdf

      http://www.burns-stat.com/documents/presentations/inferno-ish-r/

      在最后一个中,最重要的部分是要点 2,然后通读整套幻灯片。我可能会从第 3 个开始,然后是第 2 个。

      这些不是如何使特定案例工作的精神(正如其他答案所做的那样),而更多的是导致这种事态的精神以及为什么在某些情况下有标准是有意义的访问变量的非标准方式。希望了解原因和时间将有助于整体做什么。

      【讨论】:

      • +1 感谢您提供有趣的要点。伯恩斯的谈话一如既往地有趣。我必须指出我的答案中心是为什么 OP 发布的内容无法起作用,而不是如何使它起作用。
      【解决方案4】:

      如果您想获取名为“b”的变量,请在每种情况下使用 get 函数。这会将 b 的值替换为 get(b) 的任何位置。

      【讨论】:

      • 虽然并不适用于所有事情。 a &lt;- "mpg"; mtcars$get(a)
      • 我绝不会建议在 OP 提到的某些特定情况下使用get,例如ggplot,正确的解决方案是使用aes_string
      • @joran 我不经常使用 ggplot2。我希望我知道aes_string - 不久前我使用... evalparse 来做我想做的事...让回避开始...
      【解决方案5】:

      如果你想玩转表达式,你需要使用quote()、substitute()、bquote()和你提到的朋友。

      例如:

      x <- quote(list(a = 1))
      names(x) # [1] ""  "a"
      names(x) <- c("", a)
      x # list(foo = 1)
      

      还有:

      c <- "foo"
      bquote(ggplot(a, aes(x=.(c)))) # ggplot(a, aes(x = "foo"))
      substitute(ggplot(a, aes(x=c)), list(c = "foo"))
      

      【讨论】:

      • 你的 ggplot 例子很聪明,但很糟糕,永远不应该这样做。
      猜你喜欢
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 2014-06-19
      • 2016-04-24
      • 1970-01-01
      相关资源
      最近更新 更多