Hatena::ブログ(Diary)

ほくそ笑む このページをアンテナに追加 RSSフィード Twitter

2014-12-04

R にラムダ式を導入するパッケージ lambdaR を作った

※この記事は R Advent Calendar 2014 - Qiita の 4 日目の記事です。


いくつかのプログラミング言語には、無名関数を生成する方法として、ラムダ式が用意されています。

例えば、

# Python
increment = lambda x: x + 1
// Scala
def increment = (x: Int) => x + 1

などです。

ラムダ式は、無名関数をダイレクトに表現することができるため、プログラムの記述が容易になり、可読性も上がります。

ところが、R にはラムダ式はありません。

このように便利なラムダ式を R に導入できないでしょうか?


というわけで、作りました。

lambdaR は、R にラムダ式を導入するためのパッケージです。

次のようにしてインストールできます。

install.packages("devtools") # devtools をインストールしていない場合のみ
devtools::install_github("hoxo-m/lambdaR")

このパッケージで定義される lambda() は、ラムダ式を関数に変換する関数です。

increment <- lambda(x: x + 1)
add <- lambda(x,y: x + y)

ラムダ式は、上記のように、 x: x + 1 x,y: x + y のように、Python ライクに記述します。

この lambda() 関数を使うことにより、ラムダ式を入力として持つ高階関数(関数を入力として持つ関数)を作ることができるようになります。

lambdaR パッケージでは、適用例として、このようなラムダ式を入力として持つ高階関数が 6 つ定義されています。

  • Filter_()
  • Map_()
  • Reduce_()
  • Find_()
  • Position_()
  • Negate_()

これらの関数の詳細については、下記サイトを参考にして下さい。

これらの関数だけでなく、関数を入力とする関数ならば、ラムダ式を入力としたものとして再定義することができます。


例えば、Filter_() は、入力されたベクトルのうち、ラムダ式で指定された関数が TRUE を返す値のみを返します。

# 偶数のみを返す
Filter_(1:10, x: x %% 2 == 0)
 2  4  6  8 10

また、Map_() は、入力されたベクトルのそれぞれの値に対して、関数を適用したベクトルを生成します。

# 二乗した値を返す
Map_(1:5, x: x ** 2)
 1  4  9 16 25

このような関数と dplyr のパイプ演算子 %>% を組み合わせると、次のように書くことができます。

library(lambdaR)
library(dplyr)

1:10 %>% Filter_(x: x %% 2 == 0) %>% Map_(x: x ** 2)
 4  16  36  64 100

普通に書いた場合との記述量、可読性を比べてみてください。

# dplyr 不使用
Map(function(x) x ** 2, Filter(function(x) x %% 2 == 0, 1:10)

# dplyr 使用
1:10 %>% Filter(function(x) x %% 2 == 0, .) %>% Map(function(x) x ** 2, .)

ラムダ式を使うと、このような記述がすっきりすることがわかると思います。

プレースホルダ

lambdaR では、Scala で使えるプレースホルダを使うこともできます。

1:10 %>% Filter_(._ %% 2 == 0) %>% Map_(._ ** 2)

プレースホルダにより、より簡潔にラムダ式を記述することができます。

まとめ

lambdaR パッケージにより、R におけるラムダ式への道が開けました。

より詳しい使い方については、下記ページを参照して下さい。

以上です。

kaz_yoskaz_yos 2014/12/04 10:04 いいですね、これ。CRANにもぜひ! ちなみに、Wikipediaを見るかぎりはlambda abstraction = anonymous function = function literalと書いてあって、使いやすいかは別として、function(x){x*x}はラムダ式といってもいいような気がするのですが、どうでしょうか?
http://en.wikipedia.org/wiki/Anonymous_function

hoxo_mhoxo_m 2014/12/04 10:15 kaz_yos さん、実はラムダ式と無名関数の違いがよく分かってないのですが、ここで言うラムダ式とは、無名関数を簡潔に書く方法ということでお話してます。なので function(x){x*x} は無名関数ではあるがラムダ式ではないと。間違ってたらごめんなさい。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証