
近年、データサイエンティストが用いる言語として、RよりもPythonの人気が出てきている。たとえばプログラミング言語ランキングで有名なTIOBE Index(2018年4月)によると、Pythonが4位、Rが12位だ。最近、あまりにも「Python優位」の風潮があるため、一石を投じる目的で本記事を執筆する。
なぜPythonの方が人気なのか?
Pythonの人気が出ることには、必然的な理由がある。Rが統計(近年ではデータサイエンス)に特化した言語であり、Pythonはデータサイエンス以外の分野でも使われる汎用言語であるためだ。また、R言語の文法には癖があり、もともと他の言語を使用していた人にとってはPythonの方が使いやすいだろう。
しかしこのR言語の癖こそ、私がノンプログラマーにRをすすめる最大の理由である。特に、普段EXCELで作業をしており、コンピュータ言語には一切触れたことがないような人には特におすすめだ。
R言語の癖
個人的な意見だが、私はPythonの文法に関して"醜い"と感じるときがある。それはデータの要素にアクセスする瞬間だ。たとえば、1,2,3,4,5という5つの数字を格納するデータXがあるとする。データの1番目の要素にアクセスしようとしたとき、私たちはもちろん1という数字が返ってくることを期待する(1,2,3,4,5の1番目は1である)。それを実現するコードを書いてみようと思う。
R:X[1]と打つと1を返す
同様の発想でPythonも書いてみる。
Python:X[1]と打つと2を返す
さて、Pythonではおかしなことが起きた。1が返ってくると思いきや、数字の2が返ってきたのだ。プログラマーにとっては当たり前のことであるが、Pythonではデータの要素が0番から始まるのである。したがって、Pythonで1を得たいなら
Python:X[0]と打つと1を返す
私たちは生まれてから、1番、2番と数字を数えている。0番、1番とは数えない。ノンプログラマーにとっては、R言語の方が直感的に感じるはずだ。
ここまではまだいい。仮に、ノンプログラマーであるあなたが、Pythonは0番から始まると理解したとしよう。次に、あなたは最初の4つの要素を取得しようと思った。R言語の場合、
R:X[1:4]と打つと1,2,3,4となる
ここであなたは、「Pythonは0番から始まる。だからX[0:3]と打てばいい。1,2,3,4と4つの数字が返ってくる」と思うはずだ。実際に打ってみよう
Python:X[0:3]と打つと1,2,3
そう。Pythonでは4が返ってこないのだ。この時点で、頭に多くのクエスチョンマークがつくはずだ。Pythonでは次のようにしなければならない。
Python:X[0:4]と打つと1,2,3,4
直感的に考えると、意味がわからない。
ところが、まだある。それはX[-1]と打つときだ。RとPythonではX[-1]の意味が異なる。それはともかく、何が出力されるか見てみよう。
R:X[-1]と打つと、2,3,4,5を返す
R言語だと、X[-1]は1番目の要素を除外したものとなる。一方Pythonでは
Python:X[-1]と打つと、5を返す
Pythonでは、X[-1]が最後の要素を返した。あなたの賢い頭にはまた大量の疑問符が生じるはずだ。「1番目の要素は0から始まるはずだ」と。最後の要素が欲しいなら、X[-0]とするべきではないかと。最初の要素にアクセスするときは0を使ったのに、最後の要素にアクセスするには1を使わねばならないのだ。
以上から、もともと発想が数学寄りの私にはPythonの文法が醜く思えるのだ。Pythonの文法を眺めると、非対称、アンバランスと感じてしまう。プログラマーにとっては不自然なR言語の文法こそ美しいと思わないだろうか?
RとPythonのインストールから使い始めるまで
Rの場合、普通にインストールするだけでいい(コード補完などの機能があるRStudioという開発環境を入れる方がベターで、しかも簡単にインストールできる)。しかしPythonの場合、インストールが結構ややこしい。普通にやると往々にして失敗する。私はAnacondaを使った。Pythonの環境構築からデータサイエンスに必要なライブラリのインストールまでできる。Rは、時間がないビジネスパーソンが迷いなく導入できる点もありがたい。
Rは関数的、Pythonはオブジェクト的
ノンプログラマーには、「関数的」、「オブジェクト的」という言葉の意味がわからないかもしれない。まずは例を見ていただこう。最初のいくつかの要素にアクセスしたいとき、headというものを使う。これはRとPythonの両方に存在する。Xというデータフレーム(データ型の一種)に対して、このheadを適用してみよう。
R言語:head(X)と打つと先頭から5番目までの要素を返す
Python:X.head()と打つと先頭から5番目までの要素を返す
数学の授業で、f(x)という関数を習ったはずだ。R言語の場合、headもそれと同じようなものと考えてよい。fの代わりにhead(x)とするだけだ。一方、X.head()のheadはメソッドと呼ばれるものだ。関数とメソッドは厳密には同種ともいえるが、メソッドはプログラミングで用いられる概念なだけに、ノンプログラマーにとっては馴染みのない用語だ。一方関数的なR言語の場合、学校で習った関数の延長で理解することができる。
R言語のデメリット
もちろんR言語にも欠点がある。以下のような短所がよく指摘される。
①遅い
②大容量データを扱いづらい
③システム開発ができるような汎用性に欠ける
②、③に関しては、私もそう思う(ffやbigmemoryなどのパッケージがあるものの、Rでメモリにのらない大容量データを扱うのは手間がかかる)。ただ、「遅い」という批判は当たらない。その遅さをカバーできる方法が確立されているからだ。詳細に関しては踏み込まないが、以下のような解決策がある。
①forループを使わない
②forループしたいならRcppを使う(RからC++を呼び出し、遅い部分をC++で記述)
②ベクトル演算
③dplyrパッケージでデータ加工・整理する
まとめ
ここまで、R言語に偏った主張を展開してきた。Pythonユーザーの方にはもちろん反論があると思う。そしてその指摘は、正しいはずだ。
最後にまとめておく。「『EXCELからステップアップしたい』とか『データサイエンスに触れてみたい』と考えてはいるものの、別にプログラマーになりたいわけじゃない」と思う人にはRをすすめる。R言語の方が「普通の直感」で扱えるだろう。一方、「機械学習だけでなく、汎用的なプログラミングまで習得したい」という人にはPythonをすすめたい。