2009-11-16 5 views
202

Мне интересно узнать, может ли R использовать свою функцию eval() для выполнения расчетов, предоставляемых, например. строка.Вычислить выражение, данное как строка

Это общий случай:

eval("5+5") 

Однако вместо 10 я получаю:

[1] "5+5" 

Любое решение?

+5

Несмотря на все ответы, показывающие, как решить это с помощью синтаксического анализа ... Почему вам нужно хранить типы языков в символьной строке? Ответ Мартина Махлера должен заслуживать гораздо большего внимания. –

+3

Спасибо @PetrMatousu. Да, я в шоке от того, как сейчас происходит распространение неверной информации на SO .. людьми, которые выказывают 'eval (parse (text = *))' поддельные решения. –

ответ

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

Как отмечает Шейн ниже, «вам нужно указать, что входной текст является текстовым, поскольку синтаксический анализ ожидает, что файл по умолчанию « – PatrickT

+0

» должны быть указаны побочные эффекты использования eval (parse). Например, если у вас есть предопределенная переменная ** name **, равная «David», и вы переназначаете с помощью eval (parse (text = «name») == «Alexander», вы получите сообщение об ошибке, потому что eval & parse не возвращать выражение R., которое может быть оценено. – Crt

73

Вы можете использовать функцию parse(), чтобы преобразовать символы в выражение. Необходимо указать, что ввод текста, потому что синтаксический анализ ожидает файла по умолчанию:

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

> fortunes :: fortune ("answer is parse") Если ответ разобран(), вы должны, как правило, переосмыслить вопрос. - Thomas Lumley R-help (февраль 2005) > –

+5

@ MartinMächler Это иронично, потому что в базовых R-пакетах используется 'parse' все время! https://github.com/wch/r-source/search?utf8=%E2%9C%93&q=extension%3AR+parse&type= – geneorama

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

Хорошая функция, заполняет отверстие, оставшееся от 'оценки :: оценки', фактически возвращая объект результата, что оставляет вашу функцию подходящей для использования для вызова через mclapply. Надеюсь, что функция остается ! – russellpierce

+0

Благодарим вас, @rpierce. Эта функция была первоначально написана в 2011 году как часть нашего пакета «rapport», и с тех пор активно поддерживается с ее помощью в нашем [rapporter.net] (http://rapporter.net)), кроме нескольких других проектов, так что я уверен, что он будет поддерживаться на некоторое время :) Я рад, что вы сочтете это полезным, спасибо за ваши добрые отзывы. – daroczig

20

Извините, но я не понимаю, почему слишком много людей, даже подумайте, что строка может быть оценена. На самом деле вы должны изменить свое мышление. Забудьте обо всех связях между строками на одной стороне и выражениях, вызовах, оценке на другой стороне.

Подключение (возможно) только через parse(text = ....), и все хорошие программисты R должны знать, что это редко является эффективным или безопасным средством для создания выражений (или вызовов). Скорее узнать больше о substitute(), quote(), и, возможно, власть использования do.call(substitute, ......)

R> фортуну :: состояние («ответ разобрать»)

Если ответ синтаксического анализа() вы должны, как правило, переосмыслить вопрос. - Томас Ламли R-помощь (февраль 2005)

R>

декабря2017: Хорошо, вот пример (в комментариях, нет хорошего форматирования):

R> q5 < - цитата (5 + 5)
R> ул (q5)
языка 5 +-

R> e5 < - выражение (5 + 5)
R> ул (e5)
выражение (5 + 5)

и если вы получите больше опыта вы узнаете, чтоявляется "call" где, как e5 является "expression", и даже, что е5 [[1]] идентична q5:

R> идентичным (q5, e5 [[1]])
[1] ИСТИНА

+0

не могли бы вы дать пример? возможно, вы могли бы показать нам, как «удерживать» до 5 + 5 в r-объекте, а затем оценивать его позже, используя цитату и замену, а не символ и eval (parse (text =)? –

+0

Возможно, я немного потерялся. В какой момент вы получаете 10? Или это не так? –

+0

@RichardDiSalvo: yes, 'q5 <- quote (5 + 5)' above * is * выражение (фактически «вызов») '5 + 5' и это объект R, но не строка. Вы можете оценить его в любое время. Снова: использование, quote(), substitute(), ... ** вместо ** parse создает вызовы или выражения напрямую и эффективнее, чем через parse (text = *) 'является ошибкой и иногда довольно неэффективен по сравнению со строительными вызовами и манипулирует ими. @Nick S: Это' eval (eval() q5) 'или' eval (e5) 'в нашем примере –

1

В настоящее время вы также можете использовать функцию lazy_eval от lazyeval.

> lazyeval::lazy_eval("5+5") 
[1] 10 
Смежные вопросы