1. ホーム
  2. r

[解決済み] レベル<-` ( これは何の魔法だ?)

2022-05-14 22:51:36

質問

別の質問に対する回答で、@Marek さんは以下のような解決策を投稿しています。 https://stackoverflow.com/a/10432263/636656

dat <- structure(list(product = c(11L, 11L, 9L, 9L, 6L, 1L, 11L, 5L, 
                                  7L, 11L, 5L, 11L, 4L, 3L, 10L, 7L, 10L, 5L, 9L, 8L)), .Names = "product", row.names = c(NA, -20L), class = "data.frame")

`levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

これは出力として生成されます。

 [1] Generic Generic Bayer   Bayer   Advil   Tylenol Generic Advil   Bayer   Generic Advil   Generic Advil   Tylenol
[15] Generic Bayer   Generic Advil   Bayer   Bayer  

これは単なるベクトルの印刷物です。ですから、それを保存するためには、さらに紛らわしいことをします。

res <- `levels<-`(
  factor(dat$product),
  list(Tylenol=1:3, Advil=4:6, Bayer=7:9, Generic=10:12)
  )

明らかにこれはレベル関数の呼び出しの一種ですが、ここで何が行われているのかさっぱりわかりません。この種の魔術を何と呼ぶのか、そしてこの領域で私の魔術能力を高めるにはどうすればよいのか。

どのように解決するのですか?

ここでの回答は良いのですが、重要なポイントを見逃しています。それを説明しましょう。

Rは関数型言語であり、オブジェクトを変異させることを好みません。しかし、置換関数を使った代入文は許されています。

levels(x) <- y

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

仕掛けは、この書き換えは <- によって行われないことです。 levels<- . levels<- は入力を受けて出力をする普通の関数で、何も変異させません。

その一つの帰結として、上記のルールに従えば <- は再帰的でなければならないということです。

levels(factor(x)) <- y

factor(x) <- `levels<-`(factor(x), y)

x <- `factor<-`(x, `levels<-`(factor(x), y))

この純粋な関数型変換(代入が行われる最後の部分まで)が、命令型言語における代入と同等であることは、ある種の美しさです。私の記憶が正しければ、関数型言語におけるこの構成はレンズと呼ばれています。

のような置換関数を定義してしまえば、あとは levels<- 単に代入ができるだけでなく、ある因子を取り込んで、異なるレベルの別の因子を出力する便利な関数があるのです。これについては、本当に何もありません。

つまり、あなたが説明しているコードは、この別の解釈を利用しているに過ぎないのです。 levels<- . という名前は認めますが levels<- という名前は代入を連想させるので少し紛らわしいですが、これは起こっていることではありません。このコードは単にパイプラインの一種を設定しているだけです。

  • で開始します。 dat$product

  • 係数に変換する

  • レベルを変更する

  • に格納します。 res

個人的には、このコードの行は美しいと思います ;)