2009-11-16 135 views
202

我很想知道R是否可以使用它的eval()函數來執行由一個字符串。以字符串形式給出的表達式的評估

這是一個常見的情況:

eval("5+5") 

然而,而不是10,我得到:

[1] "5+5" 

任何解決方案?

+5

儘管所有的答案顯示如何解析解...爲什麼你需要在字符串中存儲語言類型? MartinMächler的回答應該得到更多讚揚。 – 2016-11-29 10:48:25

+3

謝謝@PetrMatousu。是的,我很震驚地發現錯誤信息是如何在現在傳播的......人們高舉「eval(解析(text = *))」虛假解決方案。 – 2017-04-01 16:22:20

回答

311

eval()函數計算表達式,但"5+5"是一個字符串,而不是一個表達式。使用parse()text=<string>字符串變成一個表達式:

> eval(parse(text="5+5")) 
[1] 10 
> class("5+5") 
[1] "character" 
> class(parse(text="5+5")) 
[1] "expression" 

調用eval()調用許多行爲,有些則不是很明顯:

> class(eval(parse(text="5+5"))) 
[1] "numeric" 
> class(eval(parse(text="gray"))) 
[1] "function" 
> class(eval(parse(text="blue"))) 
Error in eval(expr, envir, enclos) : object 'blue' not found 

tryCatch見。

+16

正如Shane在下面指出的那樣,「您需要指定輸入是文本,因爲解析預期默認文件「 – PatrickT 2014-01-15 08:39:14

+0

應該指定使用eval(解析)的副作用。例如,如果你有一個預定義的變量** name **等於「David」,並且你使用eval(parse(text =「name」)==「Alexander」重新分配,你會得到一個錯誤,因爲eval&parse不要返回可以被評估的R表達式 – Crt 2016-08-01 22:51:14

73

您可以使用parse()函數將字符轉換爲表達式。您需要指定輸入是文本,因爲解析期望一個文件,在默認情況下:

eval(parse(text="5+5")) 
+4

> fortunes :: fortune(「answer is parse」) 如果答案是parse(),您通常應該重新考慮這個問題。 - Thomas Lumley R-help(2005年2月) > – 2016-10-20 20:40:33

+5

@MartinMächler這很具有諷刺意味,因爲核心R包始終都使用'parse'! https://github.com/wch/r-source/search?utf8=%E2%9C%93&q=extension%3AR+parse&type= – geneorama 2017-03-30 22:10:29

15

或者,你可以使用evals從我pander包捕獲輸出,以及所有警告,錯誤和其他消息與原結果一起:

> pander::evals("5+5") 
[[1]] 
$src 
[1] "5 + 5" 

$result 
[1] 10 

$output 
[1] "[1] 10" 

$type 
[1] "numeric" 

$msg 
$msg$messages 
NULL 

$msg$warnings 
NULL 

$msg$errors 
NULL 


$stdout 
NULL 

attr(,"class") 
[1] "evals" 
+0

不錯的函數;通過實際返回結果對象填充'evaluate :: evaluate'左邊的一個空洞;這使得函數適用於通過mclapply進行調用。 ! – russellpierce 2015-12-02 09:56:03

+0

謝謝@rpierce。這個函數最初是作爲我們''rapport'包的一部分在2011年編寫的,並且自那時起一直積極維護,因爲它在我們的[rapporter.net](http://rapporter.net )服務除了一些其他項目 - 所以我相信它會保持一段時間:)我很高興你覺得它有用,謝謝你的反饋。 – daroczig 2015-12-03 07:22:49

20

很抱歉,但我不明白爲什麼連人太多認爲一個字符串是可以評估的東西。真的,你必須改變你的想法。 忘記一側的字符串與表達式,調用,另一側的評估之間的所有連接。

(可能)唯一的連接是通過parse(text = ....)和所有優秀的R程序員應該知道,這是很少有效或安全的方法來構造表達式(或調用)。而是更多地瞭解substitute()quote(),並使用do.call(substitute, ......)

R>財富::財富的可能的功率(「答案解析」)

如果答案是解析()你通常應該重新思考題。 - 托馬斯·拉姆利 R-幫助(2005年2月)

R>

十二月2017年:好吧,這裏是一個例子(註釋中,有沒有好的格式):

R> Q5 < - 報價(5 + 5)
R> STR(Q5)
語言5 + 5

R> E5 < - 表達式(5 + 5)
R> STR(E5)
表達式(5 + 5)

,如果你獲得更多的經驗,你會了解到q5"call"爲其中e5"expression",甚至說E5 [[1]]是相同的Q5:

R>相同(Q5,E5 [[1]])
[1] TRUE

+0

你能舉個例子嗎?也許你可以告訴我們如何在一個r對象中「堅持」到5 + 5,然後用引號和替換來評估它,而不是一個字符和eval(解析(text =)? – 2017-12-19 03:30:33

+0

我可能有點迷路。在什麼時候你得到10?或者那不是重點? – 2018-02-20 13:12:18

+0

@RichardDiSalvo:是的,上面的'q5 < - quote(5 + 5)'是表達式(實際上是「call」)'5 + 5'它是一個R對象,但不是一個字符串,你可以隨時評估它。再一次:使用,引用(),替代(),... **而不是**解析創建調用或表達式直接和更有效地比通過parse(text =。)。使用'eval()'很好,使用'parse(text = *)'是很容易出錯的,與施工調用和操作相比,有時非常低效。@Nick S:它是'eval q5)'或'eval(e5)'在我們的運行示例中 – 2018-02-25 21:05:10

1

如今您還可以使用lazy_eval函數從lazyeval包。

> lazyeval::lazy_eval("5+5") 
[1] 10 
相關問題