문자열로 주어진 표현식 평가


283

R이 eval()함수를 사용하여 문자열과 같은 계산을 수행 할 수 있는지 궁금 합니다.

이것은 일반적인 경우입니다.

eval("5+5")

그러나 10 대신에 나는 얻는다 :

[1] "5+5"

어떤 해결책?


6
구문 분석으로 해결하는 방법을 보여주는 모든 대답에도 불구하고 ... 문자에 언어 유형을 저장 해야하는 이유는 무엇 string입니까? Martin Mächler의 답변은 훨씬 더 많은지지를 받아야합니다.
Petr Matousu

7
@PetrMatousu 감사합니다. 그렇습니다. 나는 eval(parse(text = *)) 가짜 솔루션을지지 하는 사람들에 의해 잘못된 정보가 SO에 어떻게 퍼져 있는지를보고 놀랐습니다 .
Martin Mächler

2
QQ = c('11','12','13','21','22','23'), 즉 QQ = c (..., 'ij', ..) 형식의 스크립을 실행하고 싶습니다 . 이 예제와 비슷한 예제의 경우 스크립트를로 작성할 수 paste( "QQ = c('", paste(rep(1:2,each=3),1:3, sep="", collapse="','"), "')",sep="")있으며 옵션 eval(parse(text=...))은 스크립트 에 따라 작업 환경에서 벡터 QQ를 만듭니다. "text = ..."가 아닌 경우이를 수행하는 올바른 R 코더 방법은 무엇입니까?
VictorZurkowski

답변:


418

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 도 참조하십시오 .


27
Shane이 아래에 설명했듯이 "파싱은 기본적으로 파일을 기대하기 때문에 입력이 텍스트임을 지정해야합니다"
PatrickT

1
eval (parse) 사용의 부작용을 지정해야합니다. 예를 들어, 사전 정의 된 변수 이름 이 "David"와 같고 eval (parse (text = "name") == "Alexander"를 사용하여 다시 할당하면 eval & parse는 평가할 수있는 R 표현
Crt

1
@NelsonGon : 평가되지 않은 표현을 사용하여 구성 quote(), bquote()또는에서 제공하는보다 정교한 도구 rlang패키지.
Artem Sokolov

@ArtemSokolov 고마워, 나는 어떻게 든 대안을 찾고있는이 질문으로 돌아갑니다. 나는 살펴 보았지만 rlang가장 근접한 것은 parse_expr전화 parse_exprs를 사용 parse하고 래핑 하는 것과 동일한 호출 이며 eval여기에서 수행 한 것과 같은 것으로 보입니다. 어떤 이점을 사용할지 잘 모르겠습니다 rlang.
NelsonGon

1
@NelsonGon :를 사용 rlang하면 문자열이 아닌 표현식으로 직접 작업 할 수 있습니다. 구문 분석 단계가 필요하지 않습니다. 두 가지 장점이 있습니다. 1. 표현식 조작은 항상 유효한 표현식을 생성합니다. 문자열 조작은 유효한 문자열 만 생성합니다. 구문 분석 할 때까지 유효한 표현식인지 알 수 없습니다. 2. substitute()문자열 세계에는 함수 클래스 와 동등한 기능 이 없으므로 함수 호출을 조작하는 기능이 심각하게 제한됩니다. 이 glm 래퍼를 고려하십시오 . 동등한 문자열은 무엇입니까?
Artem Sokolov

100

parse()함수를 사용하여 문자를 표현식으로 변환 할 수 있습니다 . 구문 분석시 기본적으로 파일이 필요하므로 입력이 텍스트임을 지정해야합니다.

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

7
> fortunes :: fortune ( "answer is parse") 답변이 parse ()이면 일반적으로 질문을 다시 생각해야합니다. -Thomas Lumley R-help (2005 년 2 월)>
Martin Mächler

13
@ MartinMächler 핵심 R 패키지가 parse항상 사용하기 때문에 아이러니 합니다. github.com/wch/r-source/…
geneorama

49

죄송하지만 너무 많은 사람들이 왜 문자열이 평가할 수 있다고 생각하는지 이해하지 못합니다. 정말로 사고 방식을 바꿔야합니다. 한쪽의 문자열과 다른 쪽의 표현식, 호출, 평가 사이의 모든 연결을 잊어 버리십시오.

(아마도) 유일한 연결은 가능 parse(text = ....)하며 모든 훌륭한 R 프로그래머는 이것이 표현식 (또는 호출)을 구성하는 효율적이거나 안전한 수단이 아니라는 것을 알아야합니다. 오히려 더에 대해 알아 substitute(), quote()그리고 아마도 사용의 힘을 do.call(substitute, ......).

fortunes::fortune("answer is parse")
# If the answer is parse() you should usually rethink the question.
#    -- Thomas Lumley
#       R-help (February 2005)

2017 년 12 월 : 예, 여기 예가 있습니다 (댓글에는 멋진 형식이 없습니다).

q5 <- quote(5+5)
str(q5)
# language 5 + 5

e5 <- expression(5+5)
str(e5)
# expression(5 + 5)

당신이 더 많이 배울 경험을 얻을 경우 그 q5A는 "call"반면 e5입니다 "expression"심지어와 e5[[1]]동일합니다 q5:

identical(q5, e5[[1]])
# [1] TRUE

4
예를 들어 주시겠습니까? r 객체에서 5 + 5까지 "보류"하는 방법을 보여준 다음 문자와 eval (parse (text =)) 대신 따옴표와 대체를 사용하여 나중에 평가하는 방법을 보여줄 수 있습니다.
Richard DiSalvo

3
조금 길을 잃을 수도 있습니다. 어느 시점에서 10을 얻습니까? 아니면 요점이 아닌가?
Nick S

@RichardDiSalvo : 예, q5 <- quote(5+5)이상 입니다 식 (실제로 "전화") 5+5과는 R 객체가 아닌 문자열입니다. 언제든지 평가할 수 있습니다. 다시 말하지만, quote (), replacement (), ... 대신 구문 분석은 parse (text =.)를 통하는 것보다 직접적이고 효율적으로 호출 또는 표현식을 작성합니다. 사용은 eval()사용, 괜찮 parse(text=*)경향 및 건설 통화에 비해 때로는 매우 비효율적를 조작 오류입니다 .. @Nick S : 그것은 eval(q5) 또는 eval(e5) 우리의 실행 예에
마틴 Mächler

@NickS : 10을 얻으려면 호출 / 표현, 즉 호출을 평가하십시오 eval(.). 내 요점은 사람들 이 나중에 사용될 부름을 구성하기 위해 parse(text=.)오히려 사용하지 말아야한다는 것이었다 . quote(.)eval()
Martin Mächler

2
eval(quote())몇 가지 경우에는 작동하지만 eval(parse())잘 작동 하는 경우에는 실패 합니다.
NelsonGon

18

또는 evalspander패키지에서 결과 및 모든 경고, 오류 및 기타 메시지와 원시 결과를 캡처 할 수 있습니다 .

> 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"

2
좋은 기능; evaluate::evaluate실제로 결과 객체를 반환하여 홀을 채 웁니다 . mclapply를 통한 호출에 사용하기에 적합한 함수입니다. 그 기능이 남아 있기를 바랍니다!
russellpierce

@rpierce 감사합니다. 이 기능은 원래 2011 년에 rapport패키지의 일부로 작성되었으며 그 이후로 몇 가지 다른 프로젝트 외에도 rapporter.net 서비스 에서 많이 사용 된 이후 적극적으로 유지되었습니다 . 동안 :) 나는 당신이 친절하게 의견을 보내 주셔서 감사합니다, 당신이 그것을 유용하게 생각합니다.
daroczig


2

마찬가지로 rlang:

eval(parse_expr("5+5"))

3
여기에 rlang답을 찾고 있지만 기본 대안보다 이것의 장점이 있다면 어떨까요? 실제로, 사용 된 코드를 면밀히 조사한 결과 실제로 eval(parse(....))피하고 싶은 코드를 사용하고 있음을 알 수 있습니다.
NelsonGon

4
그 부정적인 것뿐만 아니라 그 이름도 오도합니다. 표현식을 평가하지 않습니다. parse_to_expr ot라는 이름으로 사용자가 문자 인수를 의도한다는 것을 사용자에게 알릴 수 있습니다.
IRTFM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.