为什么替换函数将noquote文本更改为字符串[r]

时间:2018-08-26 12:13:32

标签: r

我想回答一个关于绘图的问题,但是我没有得到想要的替代输出。 我想要的输出:paste("Hi", paste(italic(yes),"why not?"))
以及我得到的:paste("Hi", "paste(italic(yes),\"why not?\")")

text<-'paste(italic(yes),"why not?")'
text
[1] "paste(italic(yes),\"why not?\")"
noqoute_text<-noquote(text)
noqoute_text
[1] paste(italic(yes),"why not?")
sub<-substitute(paste("Hi",noqoute_text),
           env=list(noqoute_text=noqoute_text))
sub
paste("Hi", "paste(italic(yes),\"why not?\")")

2 个答案:

答案 0 :(得分:10)

您使用了错误的功能,请使用parse而不是noquote

text<-'paste(italic(yes),"why not?")'
noquote_text <- parse(text=text)[[1]]

sub<- substitute(paste("Hi",noquote_text),env=list(noquote_text= noquote_text))
# paste("Hi", paste(italic(yes), "why not?"))

noquote只是将类应用于字符类型的对象,并使用特定的打印方法不显示引号。

str(noquote("a"))
Class 'noquote'  chr "a"
unclass(noquote("a"))
[1] "a"

  

请详细说明您的答案吗?

在R中,您应该注意对象中的内容和打印的内容之间的区别。

noquote的作用是:

  • "noquote"添加到对象的class属性
  • 就这样

代码是:

function (obj) 
{
    if (!inherits(obj, "noquote")) 
        class(obj) <- c(attr(obj, "class"), "noquote")
    obj
}

然后在打印时,方法print.noquote

  • 从对象中删除类"noquote"(如果存在)
  • 使用参数print调用quote = FALSE
  • 就这样

您实际上也可以在字符串上调用print.noquote

print.noquote("a")
[1] a

它的打印方式与quote(a)substitute(a)相似,但这是完全不同的野兽。

在您尝试的代码中,您一直在替换字符串而不是调用。

答案 1 :(得分:4)

对于解决这个问题,我认为Moody_Mudskipperss的答案很好,但是正如您要求的详细说明...

您需要注意类似的事物实际存储在R中的不同方式,这意味着它们的行为有所不同。
尤其是在plotmath处理标签的方式上,因为它们试图模仿通常处理字符串的方式,但随后应用其自己的规则。我认为您正在混合的三件事:

  • character()是最熟悉的:只是一个字符串。转义引号等时,打印可能会造成混乱。函数noquote基本上告诉R标记它的参数,这样引号就不会转义。
  • 调用是“未评估的函数调用”:这是有关R应该做什么的指令,但尚未执行。尚未出现此呼叫中的任何错误,您可以对其进行检查。
    请注意,通话未附带其自身的环境信息,这意味着如果对通话进行评估(例如评估),通话结果可能会不同。从函数内部。
  • 表达式就像调用一样,但是更普遍地应用,即并不总是需要执行的函数。表达式可以是变量名,也可以是简单值,例如“为什么不?”。此外,表达式可以包含多个单位,就像使用{
  • 一样

不同的函数可以在这些类之间转换,但是有时函数(例如paste!)也可能会意外转换:

    正如Moody_Mudskipper指出的,
  • noquote并没有太大用处:它仅更改打印。但是对象基本上仍然是字符
  • Substitute不仅替代变量,而且将其第一个参数转换为(通常是)调用。在这里,print会叮咬您,因为在打印呼叫时,没有为其成员提供特殊类别的规定。尝试一下:问题中的sub[[3]]给出了
    [1]粘贴(斜体(是),“为什么不呢?”)
    没有任何反斜杠!仅当打印完整呼叫时,noquote-part才会丢失。
  • parse用于将字符转换为表达式。尚未评估任何内容,但引入了一些结构,以便您可以操纵表达式。
  • paste通常表现得很烦人(尽管已记录),因为它只能将字符串粘贴在一起。因此,如果您将字符以外的任何内容作为它的饲料,它将调用as.character。因此,如果给它打电话,您只会再得到一条文本行。因此,在您的问题中,即使您要使用解析,只要一开始将它们粘贴在一起,就可以再次得到引号。

最后,由于使用plotmath的内部逻辑,因此您的问题更加棘手。
这意味着,当您尝试评估文本时,可能会收到错误“找不到斜体”(如果存在 函数italic,则可能会引起更混乱的错误)在其他地方定义)。当在plotmath中提供它时,它之所以有效,是因为该调用仅由plotmath评估,这将为它提供一个很好的环境,斜体可以按预期工作。

这一切都意味着您需要将其全部视为表达式或调用。只要无法进行求值(只要是由 you 处理表达式,而不是plotmath),则都需要保留表达式或调用。给予替代呼叫是可行的,但是您也可以通过以下方式更紧密地模拟R中发生的情况:

call('paste', 'Hi', parse(text=text)[[1]])