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 14

回答:


97

代入演算子=<-R の違いは何ですか?

あなたの例が示すように、=及び<-(それらが同じ式で混合した場合の評価の順序を決定する)わずかに異なる演算子の優先順位を有します。実際、?SyntaxR では、次の演算子優先順位テーブルが最高から最低まで提供されます。

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

しかし、これが唯一の違いですか?

あなたは代入演算子について尋ねていたので、はい、それが唯一の違いです。しかし、そうでなければ信じることは許されます。?assignOpsより多くの違いがあるという主張のRドキュメントですら:

演算子<-は任意の場所で使用できますが、演算子=はトップレベル(たとえば、コマンドプロンプトで入力された完全な式)または式の括弧で囲まれたリスト内のサブ式の1つとしてのみ許可されます。

あまり細かくポイントを付けすぎないようにしましょう。Rのドキュメントは(微妙に)間違っています [ 1 ]。これは簡単に表示できます。必要なの=は、(a)最上位のレベルでも、(b)式の括弧で囲まれたリストのサブ式(つまり{…; …})でもない演算子の反例を見つけることだけです。- 難しい話は抜きにして:

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

明らかに=、コンテキスト(a)と(b)の外で、を使用して割り当てを実行しました。それで、コアR言語機能のドキュメントが何十年もの間間違っていたのはなぜですか?

これは、Rの構文では、記号=が2つの異なる意味を持ち、日常的に混乱するためです。

  1. 最初の意味は、代入演算子としてです。これまでのところ、これでお話しました。
  2. 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›) …

これらのいずれかを実行すると、「inbla›で予期しない '='」というエラーが発生します。

その他のコンテキストで=は、代入演算子呼び出しを指します。特に、部分式を括弧で囲むだけで、上記の(a)が有効になり、(b)割り当てが有効になります。たとえば、次は割り当てを実行します。

median((x = 1 : 10))

だけでなく:

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

さて、あなたはそのようなコードがひどいことに反対するかもしれません(そしてあなたは正しいかもしれません)しかし、私がこのコードを取ったbase::file.copy(置き換え機能<-=) -それはコアRのコードベースの多くに浸透パターンです。

ジョン・チェンバーズによるオリジナル解説 Rのドキュメントは、おそらくに基づいており、実際にこれを正しく説明します。

[ =割り当ては]文法の2つの場所でのみ許可されています。中括弧または追加の括弧のペアによって、周囲の論理構造から分離されている場合。


告白:私は以前に嘘をついた。演算子と演算子の間には、もう1つの違いがあります。それらは、別個の関数を呼び出します。デフォルトでは、これらの関数は同じことを行いますが、どちらかを個別にオーバーライドして動作を変更できます。対照的に、そして(左から右への代入)は構文的には異なりますが、常に同じ関数を呼び出します。一方をオーバーライドすると、もう一方もオーバーライドされます。これを知ることはめったに実用的ではありません、いくつかの楽しいシェニガンに使用できます=<-<-->


1
Rのドキュメントの優先順位とエラーについて、の優先順位?は実際にはとの中間に=あり<-、をオーバーライドするときに重要な結果をもたらし、? それ以外の場合は事実上ありません。
Moody_Mudskipper

@Moody_Mudskipper、それは奇妙です!あなたは正しいようですが、ソースコードmain/gram.y)によると、の優先順位?は正しく文書化されており、およびのどちらよりも低くなっ=てい<-ます。
Konrad Rudolph、

私はCを話せませんが=、解析ツリーが作成される前に特別な扱いを受けると思います。関数の引数に関連しているかもしれませfoo(x = a ? b)=が、式の残りの部分を解析する前に検索することは理にかなっています。
Moody_Mudskipper


2
@Moody_Mudskipper FWIWこれは、4.0.0でようやく修正されました。
コンラッドルドルフ

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はユーザーワークスペースで宣言されているため、関数呼び出しが完了した後で使用できます。


<-Sプラスの(非常に)古いバージョンとの互換性のために、(関数シグネチャ以外で)割り当てに使用するためのRコミュニティの一般的な好みがあります。スペースは、次のような状況を明確にするのに役立ちます。

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

ほとんどのR IDEには、入力を<-簡単にするためのキーボードショートカットがあります。 Ctrl+ =アーキテクト、Alt+ -RStudio(Option+- MacOSの下)、Shift+ -のEmacs + 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)

第2に、割り当てに接頭表記を使用する方が明確です。そう

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
これは、パトリックバーンズによるRインフェルノの 8.2.26章でも言及されています(とにかく私ではなく推奨です)
Uwe

3
ただし、median((x = 1:10))と同じ効果がありmedian(x <- 1:10)ます。
フランチェスコナポリターノ2016

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文字。
Matt Dowle

12
TRUER は0以外を考慮していることに注意してください。したがって、xがより小さいかどうかをテストする場合は-yif (x<-y)警告やエラーが発生せず、正常に動作しているように見える可能性があります。それだけだろうFALSEときy=0に、しかし。
Matt Dowle

4
禁止=して使用する場合<- 、の追加の手順がgrep "[^<]<-[^ ]" *.R不要であると主張するのは困難です。=そのような必要はありませんgrep
Matt Dowle

34
<-使用できるのになぜ目と指を傷つけるの=ですか?99.99%の時間=で結構です。時々あなた<<-はそれを必要とします、それは異なる歴史です。
フェルナンド

10
<-に焦点を合わせるのは、おそらく+ =と-=が欠けている原因としては不十分です。
クリス、

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
@ニック・ドンはい、そうです。便利なことに、演算子の優先順位表は?Syntax {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あり、ほとんどの場合、代わりに意味されます。
アーロンは、スタックオーバーフロー

14
ああ、はい、あなたが「プログラミングエラー」と言ったことを私は見落としました。これによりエラーが発生するのは、実際に朗報です。そして、x=0割り当てよりも優先するのに十分な理由がありx<-0ます!
スティーブピッチャー、2014

7
はい、これがエラーを引き起こすのは良いことですが、私は何を好むかについて別のレッスンを描きます。私はとても似ている=ので=、できるだけ使用しないことを選択します==
アーロンがスタックオーバーフローを去っ

2
この例の表示方法は私には奇妙です。if(x = 0) 1 else xエラーをスローし、バグを見つけて修正するのに役立ちます。if(x <- 1) 1 else xエラーをスローせず、非常に混乱しています。
グレゴールトーマス

3
つまり、本当に役立つエラーチェッカーがエラーをスローし、「else値を常に返す無用のコードがあります。そのように記述するつもりでしたか?」と言いますが、それは夢のようなものかもしれません...
タイラーH

26

演算子<-=、それらが評価される環境に割り当てます。演算子<-は任意の場所で使用できますが、演算子=はトップレベル(たとえば、コマンドプロンプトで入力された完全な式)または式の括弧で囲まれたリスト内のサブ式の1つとしてのみ許可されます。


8
「トップレベル」とは、表現レベルではなく、ステートメントレベルを意味すると思います。したがってx <- 42、それ自体がステートメントです。でif (x <- 42) {}、それは表現であり、有効ではありませんでしょう。明確に言うと、これはあなたが地球環境にいるかどうかとは関係ありません。
スティーブピッチャー、2014

1
これは、「演算子=はトップレベルでのみ許可されている」と広く認識されている誤解であり、完全に間違っています。
Konrad Rudolph

これは真実ではありません-例えば、この作品、割り当ては完全な式ではないにもかかわらず:1 + (x = 2)
パベルMinaev

1
KonradRudolphとPavelMinaevによるコメントを明確にするために、それが完全に間違っていると言うのはあまりにも強すぎると思いますが、例外があります。それは、「中かっこまたは余分な括弧のペアによって周囲の論理構造から分離されている」場合です。
アーロンは、

またはでfunction() x = 1repeat x = 1if (TRUE) x = 1....
Moody_Mudskipper

6

これは、これら2つの演算子の違いを理解する上でも役立ちます。

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

最初の要素の場合、Rには値と固有名が割り当てられていますが、2番目の要素の名前は少し奇妙に見えます。

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シエラ10.12.1


6
なぜこれが起こるのか/ここで何が起こっているのか、より詳細な説明を提供できますか?(ヒント:data.frame提供された変数の名前をデータフレームの要素の名前として使用しようとします)
Ben Bolker

考えただけで、これはバグかもしれませんか?もしそうなら、どのようにそしてどこで私はそれを報告しますか?
Denis Rasulev 2017

7
バグではありません。上記のコメントの答えをヒントにしてみました。要素の名前を設定するとき、Rはと同等のものを使用しmake.names("b <- rnorm(10)")ます。
ベンボルカー2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.