R에서 "="와 "<-"대입 연산자의 차이점은 무엇입니까?


712

할당 연산자 =<-R 의 차이점은 무엇입니까 ?

이 예제에서 보듯이 연산자가 약간 다르다는 것을 알고 있습니다.

x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"

그러나 이것이 유일한 차이점입니까?


45
여기 에서 언급했듯이 <-심볼 의 기원은 실제로 단일 <-키 가있는 오래된 APL 키보드에서 나옵니다 .
joran

답변:


97

할당 연산자 =<-R 의 차이점은 무엇입니까 ?

하여 예에서 보듯이, =그리고 <-(그들은 같은 식으로 혼합되는 경우 계산 순서를 결정하는) 약간 다른 연산자 우선 순위를 갖는다. 실제로 ?SyntaxR에서 다음과 같은 연산자 우선 순위 테이블을 제공합니다.

-> ->>’           rightwards assignment<- <<-’           assignment (right to left)=’                assignment (right to left)

그러나 이것이 유일한 차이점입니까?

대입 연산자 에 대해 질문 했으므로 그렇습니다. 이것이 유일한 차이점입니다. 그러나 그렇지 않으면 믿기 때문에 용서받을 것입니다. ?assignOps더 많은 차이점이 있다고 주장하는 R 문서조차도 :

연산자 <-는 어디에서나 사용할 수 있지만 연산자 =는 최상위 수준 (예 : 명령 프롬프트에 입력 된 전체 식) 또는 괄호 식 목록의 하위 식 중 하나에서만 허용됩니다.

의 그것에 너무 좋은 점 넣지 보자 는 R 문서는 (미묘) 잘못 [ 1 ] . 이것은 보여주기 쉽다. 우리 =는 (a) 최상위 수준이 아니고 (b) 괄호로 묶은 표현식 목록에서 하위 표현식이 아닌 연산자 의 반대 예를 찾아야한다 {…; …}. — 더 이상 고민하지 않고 :

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

=컨텍스트 (a)와 (b) 외부 에서를 사용하여 할당을 수행했습니다 . 그렇다면 왜 핵심 R 언어 기능에 대한 문서가 수십 년 동안 잘못 되었습니까?

R의 구문에서 기호 =는 일상적으로 접히는 두 가지 고유 한 의미를 갖기 때문입니다.

  1. 첫 번째 의미는 할당 연산자 입니다. 이것이 우리가 지금까지 이야기 한 전부입니다.
  2. 두 번째 의미는 연산자가 아니라 함수 호출에 인수 전달이라는 신호를 보내는 구문 토큰 입니다 . 연산자 와 달리 런타임에는 아무 작업도 수행하지 않고 표현식을 구문 분석하는 방식 만 변경합니다.=

보자

일반적인 형태의 모든 코드에서…

‹function_name›(‹argname› = ‹value›,)
‹function_name›(‹args›, ‹argname› = ‹value›,)

=는 명명 된 인수 전달을 정의하는 토큰입니다. 이는 할당 연산자 가 아닙니다 . 또한 일부 구문 적 맥락에서는 =완전히 금지 되어 있습니다.

if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …

이 중 하나라도 "‹bla›에서 예기치 않은 '='"오류가 발생합니다.

다른 상황에서는 =할당 연산자 호출을 나타냅니다. 특히, 서브 표현식 주위에 괄호를 두는 것만으로 위의 (a)가 유효하고 (b) 대입이 됩니다. 예를 들어 다음은 할당을 수행합니다.

median((x = 1 : 10))

또한 :

if (! (nf = length(from))) return()

이제 그러한 코드가 끔찍하다고 반대 할 수도 있습니다 (그리고 여러분이 옳을 수도 있습니다). 하지만 난에서이 코드를했다 base::file.copy(대체 기능 <-으로 =는 핵심 R 코드베이스의 대부분의 보급 패턴의 -).

R 문서에 기반한 John Chambers원래 설명 은 실제로 이것을 올바르게 설명합니다.

[ =할당]은 문법의 두 곳에서만 가능합니다 : 최상위 레벨 (완전한 프로그램 또는 사용자 유형 표현); 주변의 논리적 구조와 격리 할 때 중괄호 또는 추가 괄호로 묶습니다.


고백 : 나는 일찍 거짓말을했다. 이 입니다 사이 하나 개의 추가 차이 =<-사업자 : 그들은 서로 다른 함수를 호출. 기본적으로 이러한 기능은 동일하지만 동작을 변경하기 위해 이들 중 하나를 개별적으로 재정의 할 수 있습니다. 반면,으로 <-하고 ->있지만 구문 별개의 (왼쪽에서 오른쪽으로 할당), 항상 전화 같은 기능을. 하나를 재정의하면 다른 것도 재정의됩니다. 이것을 아는 것은 거의 실용적이 아니지만 재미있는 재미를 위해 사용될 있습니다 .


1
우선 순위 및 R의 문서의 오류에 대해서는 우선 순위 ?가 실제로와 사이에 =있으며 <-재정의 할 때 중요한 결과를 낳습니다 ? .
Moody_Mudskipper

@Mody_Mudskipper 기괴한! 당신은 잘 될 것 같다,하지만에 따라 소스 코드 ( main/gram.y)의 우선 순위는 ?제대로 문서화, 모두보다 낮은있다 =<-.
Konrad Rudolph

나는 C를 말하지 않지만 =구문 분석 트리가 작성되기 전에 특별한 치료 를 받는 다고 생각합니다 . 함수 인수와 관련하여 어쩌면 나머지 표현식을 구문 분석하기 전에 foo(x = a ? b)살펴 보는 것이 좋습니다 =.
Moody_Mudskipper


2
@Moody_Mudskipper FWIW 이것은 4.0.0에서 수정되었습니다.
Konrad Rudolph

661

할당 연산자 의 차이점은 함수 호출에서 인수 값을 설정하기 위해 사용할 때 더 명확합니다. 예를 들면 다음과 같습니다.

median(x = 1:10)
x   
## Error: object 'x' not found

이 경우 x함수 범위 내에서 선언되므로 사용자 작업 공간에 존재하지 않습니다.

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

이 경우, x사용자 작업 공간에가 선언되어 함수 호출이 완료된 후에 사용할 수 있습니다.


R 커뮤니티 간에는 <-이전 버전의 S-Plus와의 호환성을 위해 할당 (함수 서명 제외)을 사용하는 것이 일반적으로 선호 됩니다. 공백은 다음과 같은 상황을 명확하게하는 데 도움이됩니다.

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

대부분의 R IDE에는 <-쉽게 입력 할 수있는 단축키가 있습니다. Ctrl+ =건축가에, Alt+ -RStudio에서 ( Option+ -맥 OS 미만) Shift+ -이맥스 +의 ESS (밑줄).


쓰기 =를 선호 <-하지만 공개적으로 출시 된 코드 (예 : CRAN)에 더 일반적인 할당 기호를 사용하려는 tidy_*경우 formatR패키지 의 기능 중 하나를 사용 하여로 대체 할 수 =있습니다 <-.

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

"왜 x <- y = 5오류가 발생 x <- y <- 5합니까?"라는 질문에 대한 답변 "파서에 포함 된 마법에 달려 있습니다". R의 구문에는 여러 가지 모호한 경우 가 포함되어 있으며, 여러 가지 방법으로 해결해야합니다. 파서 선택한다면이 있는지 여부에 따라 서로 다른 명령으로 표현의 비트를 해결하기 위해 =또는 <-사용 하였다.

무슨 일이 일어나고 있는지 이해하려면 할당이 할당 된 값을 자동으로 반환한다는 것을 알아야합니다. 예를 들어, 명시 적으로 인쇄하면 더 명확하게 알 수 있습니다 print(x <- 2 + 3).

둘째, 할당에 접두사 표기법을 사용하면 더 명확합니다. 그래서

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

파서는 다음 x <- y <- 5과 같이 해석 합니다.

`<-`(x, `<-`(y, 5))

우리는 그렇게 x <- y = 5될 것이라고 기대할 수 있습니다

`<-`(x, `=`(y, 5))

그러나 실제로는 다음과 같이 해석됩니다.

`=`(`<-`(x, y), 5)

도움말 페이지 에 표시된 것처럼 =우선 순위가보다 낮기 때문 입니다 .<-?Syntax


4
이것은 또한 장 8.2.26에서 언급 은 R 지옥 (안 나와 있지만, 추천 어쨌든) 패트릭 번즈
우베

3
그러나 median((x = 1:10))와 동일한 효과가 median(x <- 1:10)있습니다.
프란체스코 나폴리 타노

2
나는 그들에게 바로 가기를 고려하지 않는다. 어쨌든 당신은 같은 수의 키를 누른다
yosemite_k

5
나는 방금 x <- x = 5해석 방법에 대한 당신의 설명 이 약간 잘못되었다는 것을 깨달았습니다 . 실제로 R은 그것을 ​`<-<-`(x, y = 5, value = 5)(그 자체가 다소 비슷합니다)로 해석합니다 tmp <- x; x <- `<-<-`(tmp, y = 5, value = 5). 이케!
Konrad Rudolph

4
사용 방법 : ... 그리고 난 그냥 일반적인 오해 영속하기 때문에 매우 오해의 소지가 불행하게도,이 답변의 첫 부분이 잘못되었음을 깨닫고 =함수 호출에 할당을 수행하지 않습니다 및 할당 연산자가 아닙니다. 완전히 구별 된 구문 분석 된 R 표현식이며 동일한 문자를 사용합니다. 또한 표시하는 코드 x는 함수 범위에서 "선언"하지 않습니다 . 함수 선언 행한다는 선언했다. 함수 호출은 그렇지 않습니다 (이름이 지정된 ...인수 로 조금 더 복잡해집니다 ).
Konrad Rudolph

103

Google의 R 스타일 가이드는 과제에 "="를 금지하여 문제를 단순화합니다. 나쁜 선택은 아닙니다.

https://google.github.io/styleguide/Rguide.xml

R 매뉴얼은 5 개의 할당 연산자에 대해 자세하게 설명합니다.

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html


133
의도했던 x<-y때 의 우연한 할당의 단점은 x < -y내가 개인적으로 선호하는 것을 너무나 싫어합니다 =. 공백에 의존하여 코드를 작성하는 것은 좋지 않습니다. 스타일 조언으로 간격을 제안하는 것이 좋지만 공간이 있는지 여부에 관계없이 코드가 다르게 실행됩니까? 코드를 다시 포맷하거나 검색 및 바꾸기를 사용하면 공백이 사라지고 코드가 잘못 될 수 있습니다. 그것은 문제가되지 않습니다 =. IIUC, =" <- "; 즉, " <-" 뿐만 아니라 공백을 포함하여 3 자 입니다.
매트 Dowle

12
비 0으로 간주됩니다주의 TRUE경우 테스트하려는 경우 R. 그래서 의해 x보다 작은 -y, 당신이 쓸 수있는 if (x<-y)경고 또는 오류 및 작업 벌금 나타나지 않을 것이다. 그것은 단지 수 있습니다 FALSEy=0, 그래도.
매트 Dowle

4
금지 =하고 사용 <- 하면 추가 단계 grep "[^<]<-[^ ]" *.R가 필요하지 않다고 주장하기가 어렵습니다 . =그런 필요하지 않습니다 grep.
Matt Dowle

34
<-사용할 수 있다면 왜 눈과 손가락을 다치게 =합니까? 시간의 99.99 %에서 =좋습니다. 때로는 당신이 필요 <<-하지만 다른 역사입니다.
페르난도

10
<-에 대한 초점은 아마도 + =와-=가 부족한 절름발이 이유 중 하나 일 것입니다.
Chris

37

x = y = 5x = (y = 5)대입 연산자 "그룹"이 오른쪽에서 왼쪽으로 작동하기 때문에 는와 동일 합니다. 의미 :에 5를 할당 y하고 숫자 5는 그대로 둡니다. 그리고 5를에 할당하십시오 x.

이 (가) (x = y) = 5작동하지 않습니다! 의미 : 값 지정 y에 대한을 x의 가치를 떠나 y; 그 다음에 5를 정확히 ... 어떻게?

다른 종류의 대입 연산자를 혼합 할 때는 <-보다 꽉 묶습니다 =. 따라서 x = y <- 5로 해석됩니다 x = (y <- 5).

불행히도 x <- y = 5로 해석되어 (x <- y) = 5작동하지 않는 경우입니다!

참조 ?Syntax?assignOps우선 순위에 대한 (바인딩)과 규칙을 그룹화.


예, Konrad Rudolph 의 답변에 따르면 우선 순위 <- <<-가 위에 나와 있습니다. =즉, <-먼저 실행됩니다. 따라서 x <- y = 5로 실행해야합니다 (x <- y) = 5.
Nick Dong

1
@Nick Dong 그렇습니다. 유용하게도 연산자 우선 순위 테이블은 ? 구문 {base}에 명확하게 문서화되어 있습니다.
Steve Pitchers

33

John Chambers에 따르면, 작업자 =는 "최상위 수준"에서만 허용됩니다. 즉 if, 다음과 같은 제어 구조에서는 허용되지 않으므로 다음 프로그래밍 오류가 불법이됩니다.

> if(x = 0) 1 else x
Error: syntax error

그는 "제어식에서 새로운 할당 형식 [=]을 허용하지 않으면 다른 S 할당보다 동일한 연산자에서 발생하는 프로그래밍 오류 (예 : 위의 예)를 피할 수 있습니다."라고 말합니다.

"중괄호 나 여분의 괄호로 둘러싼 논리적 구조와 분리 된"경우이 작업을 수행 할 수 있습니다 if ((x = 0)) 1 else x.

http://developer.r-project.org/equalAssign.html을 참조 하십시오


11
그것은 일반적인 버그 x==0이며 거의 항상 의미가 있습니다.
Aaron은 Stack Overflow를 남겼습니다.

14
아, 네, "프로그래밍 오류"라고 말한 것을 간과했습니다. 실제로 이것이 오류를 일으키는 것은 좋은 소식입니다. 그리고 x=0할당보다 선호하는 좋은 이유 x<-0!
Steve Pitchers

7
그렇습니다. 내가 선호하는 것에 대해 다른 교훈을 얻었지만 오류가 발생하는 것이 좋습니다. 내가 사용하도록 선택할 수 =있기 때문에 가능한 한 적게 =하고 ==모양과 유사하므로.
Aaron은 스택 오버플로를 종료

2
이 예가 제시된 방식은 나에게 매우 이상합니다. if(x = 0) 1 else x오류를 찾아서 버그를 찾아서 수정하는 데 도움이됩니다. if(x <- 1) 1 else x오류가 발생하지 않으며 매우 혼란 스럽습니다.
Gregor Thomas

3
나는 말은 정말 유용한 오류 검사가 오류가 발생하고 "당신은 항상 돌아갑니다 쓸모없는 코드가 말할 것 else... 파이프 꿈 수,?, 값을 당신이 그런 식으로 작성하는 것을 의미했다"하지만
TylerH

26

운영자 <-=그들이 평가되는 환경에 할당합니다. 연산자 <-는 어디에서나 사용할 수 있지만 연산자 =는 최상위 수준 (예 : 명령 프롬프트에 입력 된 전체 식) 또는 괄호 식 목록의 하위 식 중 하나 에서만 허용됩니다 .


8
"최상위 수준"은 표현 수준이 아니라 진술 수준을 의미한다고 생각합니다. 따라서 x <- 42그 자체로 진술이 있습니다. 에 if (x <- 42) {}그것을 표현, 그리고 유효하지 않은 것입니다. 분명히, 이것은 당신이 지구 환경에 있는지 여부와 관계가 없습니다.
Steve Pitchers

1
"운영자 = 최상위 수준에서만 허용됩니다"는 널리 오해되어 있으며 완전히 잘못되었습니다.
Konrad Rudolph

이것은 사실이 아닙니다. 예를 들어, 과제가 완전한 표현이 아니더라도 작동합니다.1 + (x = 2)
Pavel Minaev

1
KonradRudolph와 PavelMinaev의 의견을 명확히하기 위해, 그것이 완전히 잘못되었다고 말하기에는 너무 강하다고 생각하지만 예외는 예외입니다. "논리적 구조에서 둘러싸는 중괄호 또는 여분의 괄호로 분리됩니다."
Aaron은 Stack Overflow를

또는 function() x = 1, repeat x = 1, if (TRUE) x = 1...
Moody_Mudskipper

6

또한이 두 연산자의 차이점을 이해하는 데 도움이 될 수 있습니다.

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)

첫 번째 요소의 경우 R은 값과 적절한 이름을 할당했지만 두 번째 요소의 이름은 약간 이상하게 보입니다.

str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

R 버전 3.3.2 (2016-10-31); macOS Sierra 10.12.1


6
왜 이런 일이 일어나고 있는지, 여기에서 무슨 일이 일어나고 있는지에 대한 자세한 설명을 줄 수 있습니까? (힌트 : data.frame제공된 변수의 이름을 데이터 프레임의 요소 이름으로 사용하려고합니다 . )
Ben Bolker

방금 생각했는데 이것이 버그 일 수 있습니까? 그렇다면 어떻게 어디서보고해야합니까?
Denis Rasulev

7
버그가 아닙니다. 위의 의견에서 답변을 암시하려고했습니다. 요소의 이름을 설정할 때 R은에 해당 make.names("b <- rnorm(10)")합니다.
벤 볼커
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.