読者です 読者をやめる 読者になる 読者になる

データサイエ「ソ」ティストは語る

データサイエンティストではない、パチもんのデータサイエ「ソ」ティストのブログ

RからPowerPointを操作して自動レポート作成環境を作る(2)Rのグラフやデータフレームを挿入する

R ツール

前回の記事

datasciesotist.hatenablog.jp

(1)では、RからPowerPointを起動し、スライドの作成、テンプレートの適用までを紹介した。(2)では、スライドにRのグラフやデータフレームなどを挿入する方法を紹介する。

R2PPTパッケージが提供する関数

まずは、R2PPTパッケージが提供する関数を一覧する。といっても、(マニュアルには)13個しか関数はないし、名前が直感的なので、関数名を見ればだいたい用途はわかるだろう。

関数名 用途 用例
PPT.Init PowerPointオブジェクトの初期化 myPPT<-PPT.Init(visible=T,method="RDCOMClient")
PPT.Open 既存のPowerPointファイルを開く myPPT<-PPT.Open(file="",method="RDCOMClient")
PPT.AddTitleSlide 「タイトルスライド」レイアウトのページを作成する myPPT<-PPT.AddTitleSlide(myPPT,title="",subtitle="")
PPT.AddTitleOnlySlide 「タイトルのみ」レイアウトのページを作成する myPPT<-PPT.AddTitleOnlySlide(myPPT,title="")
PPT.AddTextSlide 「タイトルとテキスト」レイアウトのページを作成する myPPT<-PPT.AddTextSlide(myPPT,tilte="")
PPT.AddBlankSlide 「白紙」レイアウトのページを作成する myPPT<-PPT.AddBlankSlide(myPPT)
PPT.AddGraphicstoSlide アクティブなページにグラフィックスを追加する Rのアクティブなグラフィックスデバイスから貼り付ける
myPPT<-PPT.AddGraphictoSlide(myPPT,size="")
ファイルを指定して貼り付ける
myPPT<-PPT.AddGraphicstoSlide(myPPT,file="")
PPT.AddDataFrame データフレームをOLEオブジェクト(Excel表と同様)として貼り付ける myPPT<-PPT.AddDataFrame(myPPT,df="")
myPPT<-PPT.AddDataFrame(myPPT,df="",row.names=F)
PPT.ApplyTemplate スライドにテンプレート(*.potx)を適用する myPPT<-PPT.ApplyTemplate(myPPT,file="")
PPT.SaveAs 「名前を付けて保存」する myPPT<-PPT.SaveAs(myPPT,file="")
PPT.Close PowerPointファイルを閉じる myPPT<-PPT.Close(myPPT)
PPT.Present プレゼンテーションモードで表示する myPPT<-PPT.Present(myPPT)
PPT.getAbsolutePath 指定したファイルの絶対パスを得る PPT.getAbsolutePath(pathname="")

PowerPointオブジェクトを生成し、適当なページを作成する

本題の、「スライドにRのグラフやデータフレームを挿入する」ために、まずは適当なスライドを作る。基本的には前回記事の通り。

> myPPT<-PPT.Init(visible=T,method="RDCOMClient")
> myPPT<-PPT.AddTitleSlide(myPPT,title="PowerPointにRのグラフやデータフレームを挿入するテスト",title.fontsize=28)

Rで作成したグラフを貼り付ける

スライドのページにRで作成したグラフを貼り付けるには、上記のようにPPT.AddGraphicstoSlide関数を使う。この関数は、オブジェクト内の“現在アクティブなページ”(ようは、最後にmyPPTオブジェクトに代入された関数の実行結果)にグラフを挿入するので、「とりあえずページを作っておいて、後からグラフを挿入」というのはできないようだ。ページを作る→グラフを挿入→次のページを作る、という流れで処理する必要がある。

グラフ自体はなんでもよいので、「みんな大好きirisデータ」から作った箱ひげ図を使うことにする。

> data(iris) # データを読み込む
> head(iris) # データを確認しているだけ
> boxplot(iris[,1:4]) # irisデータの1列目から4列目を箱ひげ図でプロット

f:id:data_sciesotist:20160704231220p:plain

PPT.AddGraphicstoSlide関数には、現在開いているグラフィックスデバイスのデータを貼り付ける機能と、任意のファイルの内容を貼り付ける機能があるが、まずはグラフィックスデバイスのデータを貼り付ける。

> myPPT<-PPT.AddTitleOnlySlide(myPPT,title="グラフを挿入するためのページ")
> myPPT<-PPT.AddGraphicstoSlide(myPPT)

すると、以下のようにページにグラフが貼り付けられる……が、あまりイケてない。

f:id:data_sciesotist:20160704232037p:plain

グラフ全体が横に引き伸ばされた形で貼り付けられてしまう。これは、PPT.AddGraphicstoSlide関数のsizeオプションのデフォルトがsize=c(10,10,700,500)(左端からの距離、上端からの距離、幅、高さ)となっているためで、size=c(10,10,500,500)とすれば、デフォルトのグラフィックスデバイスの縦横比と同じ正方形で貼り付けられる。

> myPPT<-PPT.AddGraphicstoSlide(myPPT,size=c(10,10,500,500))

f:id:data_sciesotist:20160704234012p:plain

また、上記の記述ではグラフィックスは編集しようがない画像(デフォルトはJPEG形式)で貼り付けられているが、dev.out.typeオプションでemfを選択すると、PowerPointに貼り付け後に編集ができるようになる。これはけっこう便利。

> myPPT<-PPT.AddGraphicstoSlide(myPPT,size=c(10,10,500,500),dev.out.type="emf")

f:id:data_sciesotist:20160704233300p:plain

これはこれで、オブジェクトのサイズに比して画像のサイズが変だが、オブジェクトを右クリックし、「図の編集」を選ぶと、ラベルの文字列や色、線の太さなどをPowerPoint上で編集できる。下は、オブジェクトを適当に編集している様子。

f:id:data_sciesotist:20160704233749p:plain

もちろん、ggplot2パッケージで作成したグラフも貼り付けられる。

> require(ggplot2)
> qplot(Sepal.Length,Petal.Length, data=iris, color=Species)
> myPPT<-PPT.AddGraphicstoSlide(myPPT)

f:id:data_sciesotist:20160704234346p:plain

ということで、Rで作成したグラフは、PPT.AddGraphicstoSlide関数で(まぁまぁ)簡単に貼り付けることができる。

Rのデータフレームを貼り付ける

次に、データフレーム(いわゆる表)をPowerPointに貼り付ける。これも、PPT.AddDataFrame関数で容易に実現できる(何でこの関数はPPT.AddDataFrametoSlideじゃないのだろうか)。また、irisデータを使う。

> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

このデータを貼り付けるため、以下のコードを実行する。

> myPPT<-PPT.AddTitleOnlySlide(myPPT,title="データフレームを挿入するためのページ")
> myPPT<-PPT.AddDataFrame(myPPT,head(iris))

これもやはり、縦横比がイケてない感じになる。

f:id:data_sciesotist:20160704235456p:plain

グラフィックスの場合と同様に、sizeオプションが微妙な数値になっているためで、size=c(10,100,500,300)といったようにすると、多少見栄えが良くなる。

f:id:data_sciesotist:20160704235818p:plain

とはいえ、最適なサイズをトライアンドエラーで探すのは面倒だ。データフレームに関しては、いちどクリップボードにコピーしてExcelに貼り付け、体裁を整えてからさらにPowerPointに貼り付けるほうが楽かもしれない。

# クリップボードにタブ区切りでコピー
> write.table(head(iris),"clipboard",sep="\t",row.names=F,quote=F)

「自動レポート作成環境を作る」という観点では、毎回のレポートで出力する行・列の数が決まっているのなら、いちどがんばって最適なサイズを探せば、後はその値を使い続ければよいだろう。

いちおう、PPT.AddDataFrame関数で貼り付けたデータフレームはOLEオブジェクトになっており、表をダブルクリックするとExcelが起動し、内容を編集できる。

f:id:data_sciesotist:20160705000202p:plain

ということで、Rのデータフレームは、PPT.AddDataFrame関数で(まぁまぁ)簡単に貼り付けることができる。

まとめ

  • PPT.AddGraphicstoSlide関数でグラフィックスをPowerPointに貼り付けられる
  • PPT.AddDataFrame関数でデータフレームをPowerPointに貼り付けられる

実際のところ、R2PPTパッケージの主な関数はこの2回で紹介したものくらいなので、おそらく(3)はないものと思われる。あるとしたら、何か1件ケーススタディっぽいものを取り上げるかもしれない。

取り上げるが・・・・・・今回 まだその時と場所の指定まではしていない そのことをどうか諸君らも思い出していただきたい つまり・・・・我々がその気になれば記事の作成は10年20年後という ことも可能だろう・・・・・・・・・・ということ・・・・!

おしまい。

RからPowerPointを操作して自動レポート作成環境を作る(1)R2PPTの導入

R ツール

(1)としたものの、続かないかもしれない。ただ、自分の業務上のニーズとして、可能な限り同じ作業の繰り返しを避けて、定型的なレポートは自動生成したい、というのがあるので、やりかたを調べてみた。

……knitr使えとか、RMarkdownがいいぞ、とかあるのだけど、残念ながらこのセカイPowerPointExcelで満たされている。なので、PowerPointに出力する。

RからPowerPointを操作するのに必要なもの

もちろんPowerPointは必要だが、他にいくつかのRパッケージを導入する。

R2PPTのインストール

R2PPTは普通にCRANからインストールする。

> install.packages("R2PPT")

RDCOMClientのインストール

RDCOMClientは、以前はCRANにあったようだが、現在は開発者のサイトで公開されている。Windows用のバイナリ版( http://www.omegahat.net/RDCOMClient/RDCOMClient_0.93-0.zip )をダウンロードして、RGuiのメニューからインストールすればよい。↓参考

datasciesotist.hatenablog.jp

あるいは、レポジトリを用意してくれているので、RToolsがインストールされていて、コンパイル可能な環境なら、以下のコマンドを実行すればよい。

> install.packages("RDCOMClient",repos="http://www.omegahat.net/R")

サイトには、http://www.omegahat.org と書いてあるが、実際のURLはhttp://www.omegahat.net なので、注意する。

R2PPTパッケージを読み込み、PowerPointを操作する

RDCOMClientパッケージは、PowerPoint以外にもDCOMでアクセス可能なさまざまなアプリケーションを操作可能だが、今回はPowerPointを操作することが目的なので、それに特化したR2PPTパッケージを使う。まずは普通にパッケージを読み込む。

> require(R2PPT)

R2PPTオブジェクトの初期化

まずはPowerPointを起動し、オブジェクトを作成する。以下のコードを実行する。

> myPPT<-PPT.Init(visible=T,method="RDCOMClient")

R2PPTパッケージはデフォルトでは rcom パッケージを使って通信しようとするが、rcom パッケージはすでに存在しないため、method オプションで RDCOMClient を指定する。これで、PowerPointが起動するはず。

f:id:data_sciesotist:20160701004458p:plain

あまり普段見ないが、スライドを作る前のPowerPointが起動する。

タイトルスライドを作成する

ここから、実際にRからスライドを操作していく。はじめに、1枚目のタイトルスライドを作成する。以下のコードを実行する。

> myPPT<-PPT.AddTitleSlide(myPPT,title="Rからパワポを操作するテスト",title.fontsize=28)

文面はなんでもよいが、日本語もちゃんと使える。他に、subtitle オプションもあり、同様に subtitle.fontsize などが指定できる。これで、1枚スライドが作成され、指定した文字列が入力される。

f:id:data_sciesotist:20160701004900p:plain

作成中のPowerPointスライドは別にRからしか触れないわけではないので、手でさらにカスタマイズすることもできる。

テンプレートの適用

企業や大学のテンプレートファイル(*.potx)がある場合、すでにあるスライドに適用できる。普段、手作業するときは、テンプレートファイルを開き、適当にいじってプレゼンファイル(*.pptx)として保存、という流れが多いと思うが、Rから操作する場合は逆で、少なくとも1ページは何かスライドを作って、そこにテンプレートを適用することになる。テンプレートファイルを用意したら、以下のコマンドを実行する。

> myPPT<-PPT.ApplyTemplate(myPPT,file="mytemplate.potx") # ファイル名は絶対・相対パスで指定

今回の例では、たまたまRのワーキングディレクトリにテンプレートファイルがあるのでファイル名だけを指定しているが、別の場所にファイルがある場合は、適宜絶対パスまたは相対パスで指定する。

すると、既存のスライドのデザインが変更される。

f:id:data_sciesotist:20160701005418p:plain

続く

ただこれだけだと全然嬉しくないが、今後Rで作ったグラフをスライドに貼り付けるなど、実用的な例を紹介していく予定。

RとFacebook Graph APIであのサイトのファン層を可視化する

R API

執筆中のBGM


アイドルネッサンス「ベステンダンク」(MV)

サマリー

こういう図が作れます。 f:id:data_sciesotist:20160620224345p:plain

  • Facebook Graph APIを使うと、他人(他社)のFacebookページのファン数を国別に取得できる
  • Rから直接APIにアクセスしてJSONを取得し、パースしてデータフレームに格納する
  • 国名コードと首都の緯度・経度を記述したデータを照合して、プロットのための座標を取得する
  • 世界地図の首都の座標に、ファン数を示す丸をプロットする

Facebook Graph APIについて

いまさらこまごま話すものでもないが、Facebookにおけるオブジェクト(ページ、人、投稿、写真など、“すべて”)間の関係・情報を取得できるAPIが、Graph API

Graph APIを使うことで、例えば自分のFacebookアカウントをフォローしている人の情報などを取得できる。定期的なAPIへのアクセスには、きちんとプログラムを組んでアプリ登録して、アクセストークンをプログラムに埋め込まないといけないが、アドホックな分析、例えば今回のように特定のFacebookページのファン情報を取得し、それを可視化するというようなAPIの利用法であれば、Facebookが提供しているGraph APIエクスプローラーを使って、アクセストークンを取得すればよいだろう。

f:id:data_sciesotist:20160620230134p:plain

今回の用途では、Graph APIエクスプローラーの画面ではアクセストークンを控えておくだけでよい。

任意のFacebookページのIDを調べる

企業や有名人のFacebookページの情報を取得するためには、アクセストークンと合わせて、そのFacebookページのIDを知る必要がある。IDは、URLに含まれる文字列ではなく、数字だけからなる。といっても、調べ方は簡単で、http://findmyfbid.com/にアクセスし、IDを知りたいFacebookページのURLを貼り付ければよい。ここでは、(大して関心はないが、媚びて)AKB48メンバー(akb48.member)のページを例として使用する。

f:id:data_sciesotist:20160620231143p:plain f:id:data_sciesotist:20160620231237p:plain

IDまで48なのは偶然なのか。これも、得られたIDを控えておくだけでよい。

RからGraph APIにアクセスする

アクセストークンが有効期間内(だいたい1~2時間らしい)であれば、ブラウザからでも任意のプログラムからでもGraph APIにアクセスできるので、Rでアクセスし、任意のFacebookページのデータを取得する。

データの取得には、jsonliteパッケージを使う。また、その他地図を描画するためのパッケージなども使うので、ここで必要に応じて不足しているパッケージをインストールする。

install.packages("jsonlite")
install.packages("ggmap")
install.packages("maps")

準備ができたら、Graph APIにアクセスする。なお、今回は他人(他社)のページに関する情報のうち、特別な許可なく勝手に取得できる、page_fans_countryにアクセスする。

ということで、まずは以下のようなコードを実行する。

require(jsonlite)

fb<-fromJSON("https://graph.facebook.com/v2.6/564843926980748/insights/page_fans_country?period=lifetime&access_token=自分で取得したアクセストークン&pretty=0")
fb.fans<-t(fb$data$values[[1]][3,-ncol(fb$data$values[[1]])]) # ※1
fb.fans<-data.frame(rownames(fb.fans),fb.fans[,1]) # ※2
rownames(fb.fans)<-NULL
colnames(fb.fans)<-c("code","fans")

上記のコードを実行すると、以下のようなデータが得られる。

   code  fans
1    DE  1326
2    BD   461
3    NP   471
4    BE    NA
5    RU   353
6    HK 21570
7    TW 47630
8    JP 63045
9    NZ   493
10   FR  3800
...

上記コードの※1、※2あたりで、データの3行目(最新の日付分だけ)取り出したり、転置したり、列名をデータフレームの1列目にしたり、いろいろやっている。これでいちおう、国名コード別に、ファン登録をしているユーザーが何人いるかがわかった。

国名コードと首都の緯度・経度を対応させる

Graph APIから得られる国の情報は、(たぶん)ISO 3166-1の2文字で構成される国名コードである。このままでは、地図上にその位置をプロットすることはできない。そこで、国名コードとその国の都市の緯度・経度を対応付ける必要がある。とりあえず首都でいいだろう、ということで、「国名コード 緯度 経度」でググると、アマノ技研様が世界の首都の位置座標データを公開してくださっている。アンケートに答えるとダウンロードできる。「全項目空白・未入力でもダウンロードは可能」と書かれているが、せっかくなので協力してあげましょう。

f:id:data_sciesotist:20160620233611p:plain

ページを進めると、位置座標のCSVファイルをアーカイブしたzipファイルがダウンロードできる。アーカイブを展開して得られるh2704world.csvをRのワーキングディレクトリに配置する。このファイルと、先ほど作ったfb.fansデータフレームを結合する。

やり方は簡単で、CSVファイルを読み込んでmerge関数でマージするだけでよい(そのためにfb.fansの列名をcodeにしている)。

countries<-read.csv("h2704world.csv")
fb.fans<-merge(fb.fans,countries[,c("code","lat","lon")])

これで、国名コード、ファン数、緯度、経度の4列からなるデータフレームができる。

  code fans       lat       lon
1   AE  351  24.46667  54.36667
2   AR  899 -34.60372 -58.38159
3   AU 2771 -35.30824 149.12422
...

このデータを使い、地図上にファン数をマッピングする。地図の描画にはmapsパッケージを使う。ggmapなどもうちょっとイケてるパッケージを使いたかったが、世界地図を取得する方法がよくわからなかったので。さっそく、以下のコードを実行する。

require(maps)
map("world",fill=T,col="white",bg="lightblue",ylim=c(-60,110),mar=c(0,0,4,0))
points(fb.fans$lon,fb.fans$lat,cex=scale(fb.fans$fans)+3,col=2,pch=19)
text(0,100,"AKB48 Facebookページのファン分布",cex=1)
dev.off()

f:id:data_sciesotist:20160620224345p:plain

なぜか、日本語のページなのに、日本よりもインドネシアにファンがやたらと多い。JKT48の影響なのか。日本ではFacebookよりもGoogle+や個人のページ(あるのか知らないが)などに注目が集まっているからか。

なお、この例ではファン数をpoints関数の丸の大きさ(cex)で表現しているが、国ごとに差が大きすぎるため、scale関数で標準化し、とりあえず全部が正の値になるように3を足している。場合によっては、log関数なども使い、とにかく「ちょうどよい」くらいに調整する。

そのほかの例

以下、同様にいくつかの会社について調べてみた例。

ユニクロ

f:id:data_sciesotist:20160620222355p:plain

日本が圧倒的に多いが、アジア、ヨーロッパなどにもまんべんなくファンがいる様子。

某リサーチ会社

f:id:data_sciesotist:20160620235657p:plain

なぜかアフリカにファンがいる様子。

IBM

f:id:data_sciesotist:20160621000534p:plain

なぜかインドにファンがたくさんいる様子。

まとめ

こんな感じで、「国別ファン数」は、アクセス許可がいらず、任意の(企業、有名人)ページの情報が取得できる。その他の、都市別、性別などは取得できなかった。全部試したわけではないので、他にもアクセスできるエンドポイントがあるかもしれないが、いろいろ試していただければ。

日本語WikipediaとRのwordVectorsパッケージで“言葉遊び”

R テキストマイニング

執筆時のBGM:アイドルネッサンス「夏の決心」


アイドルネッサンス「夏の決心」(MV)

まえがき

世の中の「でーたさいえんてぃすと」はとうの昔に通り過ぎてしまったところだろうけど、「言葉の意味」をベクトル空間にマッピングして、様々に操作(計算)できるword2vecで遊んでみた記録。

前提

今回は、慣れているR(最近はMicrosoft R Open)のwordVectorsパッケージを使う。また、テキストデータは、昨年夏前ころにダウンロードした、Wikipedia日本語版のダンプXMLを使う。

作業環境

たまたま、自分のPCがそうだ、というだけなのだけど。ただ、メモリは十分に必要。ソフトウェア類は、基本的に最新のものをダウンロードすればよい。





  • Git ※アクセスするとインストーラのダウンロードが始まる
    たぶん、いろいろなOSSツールを入れるとGitも入ってくるだろうから、オフィシャルの配布物じゃなくてもよいと思う
  • Windows版nkf ※パスの通ったフォルダに配置する

使用するデータ

上記のように、Wikipedia日本語版のダンプXMLを使う。基本的には、 https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 をダウンロードすればよいと思うが、以前WP2TXTを実行した環境の都合で、分割されたデータ https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles[1-4].xml.bz2 を使った。いずれにしても、ファイルサイズが巨大なので、時間とディスク容量に注意する。

ダウンロードしたデータは、bz2圧縮されたままで処理できるが、環境がしょぼい(メモリ4GB程度)と、メモリ不足で処理が進まなかったので、場合によっては事前に展開だけしておく。

 for i in *.xml.bz2
     do
         bzip2 -d $i
     done

なお、今回は、昨年の夏ごろ(2015年6月ころ)にダウンロードしたデータが手元にあったので、それを使っている。そのため、収録記事数などは現在の最新のものとは異なる。

作業手順

流れは、以下のようになる。

  1. Wikipedia XMLをプレインテキストに変換する(WP2TXT)
  2. テキストの分かち書きMeCab + mecab-ipadic-neologd)
  3. RおよびRtoolsのインストール
  4. word2vecのコンパイルWindows版word2vec)
  5. wordVectorsパッケージのインストール(R)

Wikipedia XMLをプレインテキストに変換する(WP2TXT)

WP2TXTを使う。事前にRubyなどはインストールしておく。

 git clone https://github.com/yohasebe/wp2txt.git

とするなり、zipファイルをダウンロードするなりして、WP2TXTを入手する。なお、スクリプトの実行には、いくつかのライブラリのインストールが必要なので、以下のようにする。

  gem install nokogiri
  gem install htmlentities
  gem install trollop

ダウンロードしたWP2TXTのbinフォルダに移動し、コマンドプロンプトを開く(パスがわかればどこでもいいけど)。そして、以下のように実行して、ヘルプが表示されることを確認する。

  ruby wp2txt --help

  WP2TXT extracts plain text data from Wikipedia
  dump file (encoded in XML/compressed with Bzip2) 
  stripping all the MediaWiki markups and other metadata.
  
  Usage: wp2txt [options]
  where [options] are:
    -i, --input-file              Wikipedia dump file with .bz2
                                  (compressed) or .txt (uncompressed)
                                       format
    -o, --output-dir=<s>          Output directory (default:
                                  C:/Users/XXX/XXX/wp2txt/bin)
...

表示されなかったら、不足したライブラリをインストールするなど、どうにかする。

準備ができたら、WikipediaXMLデータをパースし、プレインテキストに変換する。この際、後で分かち書きする際に邪魔になりそうな要素を、様々なオプションを使って除去する必要がある。また、処理には非常に長い時間がかかるので、注意する。

実行例

  ruby wp2txt -i jawiki-latest-pages-articles1.xml.bz2 -o C:\Users\XXX\Desktop
  --no-list --no-heading --no-title --no-multiline -f 70
  (実際には1行で続けて書く)

※最後の-fオプションは出力ファイルのサイズ指定。何度か試してみて、70MBにしている。環境によっては、もう少し大きくてもよいだろう。

これで、指定したフォルダにテキストファイルが順次出力される。すごく時間がかかる。あまり具体的に覚えていないが、昨年この作業を行った時は、丸2日くらいかかったようだ。ちなみに、英語版Wikipediaのサイズだと、丸1週間かかった。

出力の結合と文字コード変換

次に、できあがったテキストファイルを結合する(せっかく分割して出力したのだが)。コマンドプロンプトでテキストファイルがあるフォルダに移動し、以下のようにする。

 type jawiki-latest-*.txt > jawiki.txt

また、テキストの文字コードUTF-8になっているので、このあとWindows環境で扱うために、Shift_JIS(CP932)に変換する。

  for %%f in (jawiki-latest-*.txt) do nkf -sLw --overwrite %%f

テキストの分かち書きMeCab + mecab-ipadic-neologd)

Wikipediaテキストデータの準備ができたら、次に、テキストを形態素単位で分かち書きにする。word2vecは日本語の「区切り」を知らないので、事前に区切っておく必要がある。分かち書き自体は、MeCab-O wakatiオプションで簡単にできる。

ただし、MeCabに標準で付属する辞書(IPADIC)は古いので、最近出てきた新しい言葉などを意図しないところで区切ってしまうことがあるため、より新しい辞書であるmecab-ipadic-neologdを導入する。なお、mecab-ipadic-neologdは、基本的にはUNIX / Linux環境でコンパイルして作成するため、何らかの作業環境が必要だ。UNIX / Linux環境でWindows向けの辞書を作成する方法は、mecab-ipadic-neologdをNMeCab用にshift-jisでコンパイルしたなどを参照する。単に、辞書作成スクリプトmake-mecab-ipadic-neologd.shの中で-t UTF8となっている部分を、-t shift-jisにするだけ。実際には、Shift_JISで表現できない文字(記号、絵文字など)が大量にスキップされるが、しょうがない。

なお、現時点の最新の辞書(20160317-01)をWindows用にコンパイルしたものをGoogleドライブに置いた。

作成した辞書を、MeCabの辞書フォルダ(例えば C:\Program Files (x86)\MeCab\dic)に配置し、設定ファイル(C:\Program Files (x86)\MeCab\etc\mecabrc)を以下のように書き換える。

  ;dicdir =  $(rcpath)\..\dic\ipadic
  dicdir =  $(rcpath)\..\dic\mecab-ipadic-neologd
  ※IPADICを使う設定をコメントアウトし、mecab-ipadic-neologdを使うようにする

試しに、コマンドプロンプトで以下のように入力し、新しい言葉が適切に区切られることを確認する。……無駄に長い例だけど、ようは新しい言葉(馬名、人名)がちゃんと認識できていればよい。

  echo リオンディーズ、マカヒキ、エアスピネル、サトノダイヤモンドなど、史上最高メンバーの皐月賞!きゃりーぱみゅぱみゅも興味津々!(嘘) | mecab
  リオンディーズ  名詞,固有名詞,一般,*,*,*,リオンディーズ,リオンディーズ,リオンディーズ
  、      記号,読点,*,*,*,*,、,、,、
  マカヒキ        名詞,固有名詞,一般,*,*,*,マカヒキ,マカヒキ,マカヒキ
  、      記号,読点,*,*,*,*,、,、,、
  エアスピネル    名詞,固有名詞,一般,*,*,*,エアスピネル,エアスピネル,エアスピネル
  、      記号,読点,*,*,*,*,、,、,、
  サトノダイヤモンド      名詞,固有名詞,一般,*,*,*,サトノダイヤモンド,サトノダイヤモンド,サトノダイヤモンド
  など    助詞,副助詞,*,*,*,*,など,ナド,ナド
  、      記号,読点,*,*,*,*,、,、,、
  史上    名詞,一般,*,*,*,*,史上,シジョウ,シジョー
  最高    名詞,一般,*,*,*,*,最高,サイコウ,サイコー
  メンバー        名詞,一般,*,*,*,*,メンバー,メンバー,メンバー
  の      助詞,連体化,*,*,*,*,の,ノ,ノ
  皐月賞  名詞,固有名詞,一般,*,*,*,皐月賞,サツキショウ,サツキショー
  が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
  来る    動詞,自立,*,*,カ変・来ル,基本形,来る,クル,クル
  !      記号,一般,*,*,*,*,!,!,!
  きゃりーぱみゅぱみゅ    名詞,固有名詞,一般,*,*,*,きゃりーぱみゅぱみゅ,キャリーパミュパミュ,キャリーパミュパミュ
  も      助詞,係助詞,*,*,*,*,も,モ,モ
  興味津々        名詞,一般,*,*,*,*,興味津々,キョウミシンシン,キョーミシンシン
  !      記号,一般,*,*,*,*,!,!,!
 (      記号,括弧開,*,*,*,*,(,(,(
  嘘      名詞,一般,*,*,*,*,嘘,ウソ,ウソ
  )      記号,括弧閉,*,*,*,*,),),)
  EOS

環境が整ったら、本題に戻って、Wikipediaのテキストを分かち書きする。テキストファイルがあるフォルダで、以下のようにする。-O wakatiオプションで分かち書きをする。-b 81920は、標準のバッファサイズでは溢れてしまったため、とりあえず10倍にしている設定。

  for %%f in (*.txt) do mecab -b 81920 -O wakati %%f > wakati_%%f
  type wakati_jawiki-latest-pages-articles*.txt >> wakati_jawiki.txt

これで、Wikipedia日本語版のテキストを分かち書きしたデータが手に入った。

RおよびRtoolsの導入

ここは、書くまでもないところだけど、最新のRまたはMicrosoft R Openと、Rtoolsをダウンロード、インストールする。

word2vecのコンパイルWindows版word2vec)

ようやく、word2vecを導入する。オリジナルのword2vecはUNIX / Linux用のコードで、そのままではWindowsコンパイルできない(らしい)ので、Windows版word2vecを使う。こちらも、コンパイル環境が必要だが、Rtoolsが入っていれば、それで事足りる。詳しい手順などは、Windowsにword2vecをインストールする方法を参照。

単純には、以下のような手順になる。

  git clone https://github.com/zhangyafeikimi/word2vec-win32.git
  cd word2vec-win32
  make
  ...
  demo-word.sh

これで、一通りコンパイルが完了し、サンプルの実行まで進む。フォルダ内に、word2vec.exedistance.exeなどができるので、それら実行ファイルを、パスの通ったフォルダに配置する。

wordVectorsパッケージのインストール(R)

大方の準備が整ったので、Rからword2vecを呼び出すための、wordVectorsパッケージをインストールする。Rを起動し、まずはdevtoolsパッケージをインストールする。

  > install.packages("devtools")

次に、wordVectorsパッケージをGitHubからインストールする。

  > require(devtools)
  > install_github("bmschmidt/wordVectors")

合わせて、word2vecモデルを操作するときに便利なmagrittrパッケージも導入する。

  > install.packages("magrittr")

これで、Rからword2vecを呼び出す環境が整った。

20160502追記

「この前までできていたのに」wordVectorsパッケージの更新かなにかで、筆者のCore i7-4770環境では、インストールができなくなっていた。RToolsが提供するgcc 4.6.3では、ソース中の最適化フラグ-march=nativeがHaswellアーキテクチャに対応していないらしい。そのため、解決するには、いったんgit cloneソースコードをダウンロードし、Makevars.winファイルの当該部分を書き換える必要がある。

ソースを修正したうえで、コマンドラインから以下のようにしてコンパイルする(Windowsの場合)。

 Rcmd INSTALL --build wordVectors(フォルダ)

これでパッケージのzipファイルができるので、インストールする。

word2vecモデルの作成

上記の環境構築が終わったら、Wikipediaのテキストデータと、RのwordVectorsパッケージを使い、word2vecの意味空間モデル(何のこっちゃ……)を作成する。Rを起動し、テキストデータがあるフォルダに移動したうえで、以下のように実行する。

  > require(wordVectors)
  > train_word2vec("wakati_jawiki.txt",output="jawiki.vectors",threads=3,vectors=200,window=12)

一般化すると以下のように書ける。

  train_word2vec("テキストファイル名",output="出力ファイル名",threads=実行スレッド数,vectors=次元数,window=語長)

threadsは、実際にはCPUのコア数-1くらいを指定するとよいのではないだろうか。vectorswindowは、正直、適切な値はよくわからないけど、いろいろ調べる限り、vectorsはだいたい200で、windowは、5や12などいろいろな例があった。Wikipediaに関しては、5では短すぎて意味のある結果が得られにくいようなので、12とした。

これも、すごく時間がかかる。冒頭のPC環境で、3-4時間くらいかかった。処理が終了すると、上記の例では、およそ88万語について、200次元のベクトルで特徴を表したモデルが出力される。

なお、train_word2vec関数で出力されるモデルのフォーマットは以下のようになっている。

  889165 200
  JR東海道線 0.357443 -0.265362 0.144581...
  ...

一般化すると、以下のようになる。

  1行目      行数(語数)  次元数
  2行目以降  形態素 第1次元 第2次元 第3次元...

出力は、シンプルなテキストファイルなので、UNIX / Linuxのテキスト操作コマンドで、一部を抽出することなどが簡単にできる。例えば、全889165語のうち、100000語をランダムに取り出して、小さなファイルを作るには、以下のようにする。

  $ echo "100000 200" > small_jawiki.vectors
  $ tail -889165 jawiki.vectors | sort -R | head -100000 >> small_jawiki.vectors

※こんなことをして抽出したデータが、言語学的に正しいのかは知らない。

ちなみに、ここまでの操作の結果、できあがったデータ(全件、300000件抽出)を、Googleドライブに置いている。

さぁ、ようやくだ!書くだけでも2時間くらいかかっているが、これからできあがったモデルを操作していく。

word2vecモデルで遊ぶ

まず、Rを起動し、wordVectorsパッケージを読み込む。

  > require(wordVectors)

次に、作成したword2vecモデルファイル(ここでは、jawiki.vectors)を読み込む。データ量とディスク性能しだいで、かなり(4-5分程度)時間がかかる。また、データがメモリに展開されるため、メモリ消費に注意する。今回作成した、およそ89万語のデータの場合、ファイルサイズが1.65GBで、メモリに展開されると、5GBほど消費する。

  > model<-read.vectors("jawiki.vectors")

読み込んだモデルの各要素にアクセスするには、以下のようにする。

  > model # モデル全体(実際には先頭の一部だけ表示される)
  A VectorSpaceModel object of  889165  words and  200  vectors
              V1        V2        V3        V4       V5        V6
  </s>  0.001712  0.001952  0.002184 -0.000975 0.001271 -0.0004820.061107 -0.167354  0.029397 -0.006784 0.277198  0.0483190.068990 -0.281579  0.061935 -0.067788 0.242458  0.105923-0.063259 -0.292497  0.138581 -0.086513 0.291480  0.135969

  > model[1:3] # 先頭から3行を表示する
  A VectorSpaceModel object of  3  words and  200  vectors
             V1        V2       V3        V4       V5        V6
  </s> 0.001712  0.001952 0.002184 -0.000975 0.001271 -0.0004820.061107 -0.167354 0.029397 -0.006784 0.277198  0.0483190.068990 -0.281579 0.061935 -0.067788 0.242458  0.105923


  > model[["エアメサイア"]] # 指定した語の行のみ表示する
  A VectorSpaceModel object of  1  words and  200  vectors
         V1        V2        V3        V4        V5        V6 
   0.153385  0.181259 -0.093122 -0.037569 -0.604000 -0.145498

  > model[[c("エアメサイア","シーザリオ")]] # 何が返ってきているのだろう? 2つの言葉の共通次元?
  A VectorSpaceModel object of  1  words and  200  vectors
          V1         V2         V3         V4         V5         V6 
   0.0780615  0.0151365 -0.0739540  0.0080325 -0.2092705  0.0824025

その他、普通の文字列と数値からなるデータフレームなので、grep関数なども使えるが、なにせデータ量が大きいので、やたらと時間がかかる。

関数の使用(1)nearest_to関数

wordVectorsパッケージには、「言葉の意味」を操作する様々な関数があるが、まずは、指定した語と(意味的に)類似した語を出力する、nearest_to関数を使ってみる。ちなみに、n=オプションで出力する要素数を指定できる。デフォルトは10。

  > nearest_to(model,model[["エアメサイア"]])
        エアメサイア ショウナンパントル       トールポピー   オレハマッテルゼ
       -2.220446e-16       2.534338e-01       3.597027e-01       3.620715e-01
  ホエールキャプチャ     グランプリボス   フサイチパンドラ   セイウンワンダー
        3.748858e-01       3.768097e-01       3.894503e-01       3.960476e-01
        伊豆急8000系     マツリダゴッホ
        4.098723e-01       4.139108e-01

謎の伊豆急8000系(2005年デビューだからか。エアメサイアは2005年の秋華賞馬。)はともかく、他はちゃんと?サンデーサイレンス産駒やマイル・中距離のGI馬が出てきている。って、読んでいる人は誰も判断がつかないだろうが。同期の三冠馬ディープインパクトについて類似した語を抽出すると、以下のようになる。

  > nearest_to(model,model[["ディープインパクト"]])
  ディープインパクト   シンボリルドルフ           宝塚記念     オグリキャップ
       -4.440892e-16       2.647716e-01       2.800557e-01       2.966380e-01 
              菊花賞   ミスターシービー           有馬記念     ジャパンカップ
        2.982116e-01       3.022025e-01       3.033070e-01       3.085915e-01
  テイエムオペラオー メジロマックイーン
        3.088792e-01       3.126304e-01

これも、読んでいる人には判断がつかないだろうが、競馬ファンからすると、「あぁ」という結果になった。シンボリルドルフミスターシービーは同じ三冠馬だし、メジロマックイーンは同じ池江泰郎厩舎の所属だった。オグリキャップテイエムオペラオーは、「熱狂」や「強さ」の面でよく対比される存在だ。映画のほうは何も出てこない。

また、tsneパッケージを使うことで、言葉の意味空間をプロットできる。

  > install.packages("tsne")
  > require(tsne)

  > horses<-nearest_to(model,model[[c("エアメサイア","シーザリオ","ラインクラフト")]])
  > plot(filter_to_rownames(model,names(horses)))

f:id:data_sciesotist:20160320213903p:plain

なんか、わかるようなわからないような結果になった。スズカフェニックスヘヴンリーロマンスなど、同じ時期にGI戦線を賑わせた馬や、2005年前後に生まれた(サクセスブロッケン!!!!!!)り、亡くなった(アドマイヤベガ)馬が出てきている。「○○は日本の競走馬。○○年、どこそこで生まれる。○○年に死亡」といった、Wikipediaの文体の特徴が反映されたのだろうか。

ともあれ、こんなふうに、ごくシンプルに、「ある言葉と似ているらしい言葉」を抽出できる。他に、reject関数で意味の除去、project関数で意味の付与ができる。

関数の使用(2)magrittrパッケージと組み合わせる

次に、word2vecモデルを操作し、ある言葉に意味を足したり引いたりしてみる。その際、magrittrパッケージを使うと、チェイン関数(%>%)でUNIX / Linuxのパイプのように処理をつなげていくことができる。

前項でパッケージのインストールはしているはずなので、require関数やlibrary関数で読み込む。

  > require(magrittr)

まずは、以下のような例を実行してみる。

  > tkd<-model[["JR東海道線"]] %>% reject(model[["JR東日本"]])
  > model %>% nearest_to(tkd)
      JR東海道線   JR東海道本線       茶沢通り         戸塚駅         鴨居駅 
       0.1276491      0.3291890      0.3423227      0.3487515      0.3505389 
          仙川駅 小田急小田原線   尻手黒川道路         長原駅         神宮前 
       0.3522090      0.3556912      0.3594673      0.3597864      0.3614786

わかるような、わからないような。小田急、茶沢通り、仙川駅、長原駅、神宮前など、なぜか世田谷・調布周辺が多く返ってくる。地図で見ると、だいたい都心から同じ方向なのだが。

……ということで、WikipediaとRのwordVectorsパッケージを使って、word2vecで遊ぶための手順をまとめてみた。

miniCRANパッケージを使ってパッケージをオフラインインストールする

R

いつも自分でしゃべっていて、「検索したらヒントが出てきますよ」と言っているのだけど、参照先がうまく紹介できないので、研修のネタ帳として。

オフラインのパソコンでRを使う

データ分析を専門にしている方からすると信じられないかもしれないが、一般的なIT企業や官公庁ではいろいろセキュリティが厳しいので、限られたパソコンしかインターネットに接続できないことが多い(らしい。お客さんと話をすると)。

特に、「分析したくなる」データを扱うようなパソコンは、尚更ネットには繋げないかもしれない。

そのようなオフラインのパソコンでRを使いたいとき、問題になるのはパッケージの導入である。Rは、まぁ最初にCDか何かでインストーラを持ち込めばよいが、その後必要に応じてパッケージを導入したいときに、 install.packages が使えないのは不便だ。特に、依存関係を手動で解決しなければならない、というのが困難だ。

解決すべき課題

  1. パッケージを install.packages を使わずにインストールする
  2. その際に必要な依存関係を解決する
  3. (パッケージのバージョン管理、更新を行う)

このうち1. については、WindowsのRであればメニューバーの[パッケージ]-[ローカルにあるzipファイルからのパッケージのインストール]を選択し、ダウンロードしたパッケージのzipファイルを指定すればよい。Ctrl-aで複数のzipファイルをまとめて選択することもできる。

f:id:data_sciesotist:20150324004258p:plain

もうひとつの2. が課題で、CRANのページを目で見て、関係するパッケージを手でダウンロードしていくのは非常に困難だ。3. については、とりあえず所望の分析ができれば古くてもよかろう、ということで今回は考えない。

解決策

パッケージの依存関係を解決して手動でインストールするために、{miniCRAN}パッケージを用いる。また、どうしてもCRANの情報を参照する必要があるため、最低1台はネットにつながるパソコンが必要だ。

{miniCRAN}パッケージのインストール

ネットにつながるパソコンで、{miniCRAN}パッケージをインストールする。

 install.packages("miniCRAN")

オフラインで使用したいパッケージをリストアップする

なんでもよいが、ここでは項目反応理論のための{ltm}パッケージを選んだとする。

ltmパッケージの依存関係をpkgDep関数で調べる

{miniCRAN}パッケージを読み込み、 pkgDep 関数で{ltm}パッケージと依存関係にあるパッケージを調べる。結果を、適当な変数pkgsに格納する。

 require(miniCRAN)
 pkgs<-pkgDep("ltm")

pkgs変数の中身を見ると、{ltm}パッケージ自身を含めて10個のパッケージ名が格納されている。

 pkgs
 [1] "ltm" "MASS" "msm" "polycor" "survival"
 [6] "mvtnorm" "expm" "sfsmisc" "Matrix" "lattice"

これらのパッケージをダウンロードし、オフライン環境にインストールすれば、{ltm}パッケージが使えるようになる。

パッケージのダウンロード

パッケージのダウンロードには download.packages 関数を使う。先に、ダウンロードしたzipファイルを配置するフォルダを適当に作っておく。ここではR_pkgsフォルダとする。

 download.packages(pkgs,destdir="R_pkgs")

ダウンロードしたパッケージをオフライン環境に持っていく

CDに焼くとか、USBメモリにコピーするなどして、オフラインのパソコンにデータを持ち込む。あとは先程述べたように、メニューからzipファイルを指定してインストールすればよい。

まとめ

あまり意識していなかったが、一般の企業では思った以上にネットにつなげないコンピュータが多いことをRの研修を通じて知った。「パッケージを使いたかったら install.packages で簡単ですよ」と言ってきたが、そうもいかない環境があるらしい。そのような環境でパッケージの導入を行うためには、(ネットにつながるコンピュータで){miniCRAN}パッケージを用いて依存関係を調査し、download.packages 関数でファイルをダウンロードし、それを持ち込むという方法がある。

Spark 1.3.0リリースノートを訳した

Apache Spark

Gistにも上げました。

ただし、2時間くらいの“雰囲気”で訳したもの。そのため、そもそもSpark開発コミュニティにおける文脈を知らないし、動作検証もしていないので、あまり信用しないでください。

(あと、はてな記法とかMarkDownも忘れたのでレイアウトが変かもしれない)

特に機械学習の手法名など、よく知らない部分も多いので、間違いがあればご指摘ください。

Apache Spark 1.3.0 リリースノート

日本語訳: @data_sciesotist

Spark 1.3.0

Spark 1.3.0は1.x系の4つ目のリリースです。本リリースでは、Spark SQLのアルファ版プロジェクトから、DataFrame APIが正式に取り込まれました。

また、Spark CoreやMLlib、Spark Streamingについても改良が加えられました。

Spark 1.3は60以上の組織、174名のコントリビューターからの、1000以上のパッチによる成果です。

Spark 1.3は、ダウンロードページ (https://spark.apache.org/downloads.html) から入手できます。

Spark Core

Spark 1.3では、Spark Coreに対していくつかの改良を行いました。

Core APIでは、複雑なReduce処理を高速化するために"multi level aggregation trees" (https://issues.apache.org/jira/browse/SPARK-5430) をサポートしました。

エラーレポートの改良 (https://issues.apache.org/jira/browse/SPARK-5063) により、的確に処理の過程、結果を把握できるようになりました。

SparkのJettyアプリケーションサーバへの依存性により、ユーザープログラムと衝突していた問題が解消されました (https://issues.apache.org/jira/browse/SPARK-3996)。

Sparkは、いくつかの通信機能において、SSL encryptionをサポートしました (https://issues.apache.org/jira/browse/SPARK-3883)。

また、リアルタイムにガベージコレクションのメトリクスを行う機能 (https://issues.apache.org/jira/browse/SPARK-3428)、タスク内のI/Oを計測する機能 (https://issues.apache.org/jira/browse/SPARK-4874) を新たにUIに追加しました。

DataFrame API

Spark 1.3では、新たにDataFrame API (https://spark.apache.org/docs/1.3.0/sql-programming-guide.html#dataframes) が導入されました。

DataFrame APIは、構造化されたデータセットに対する強力で簡便な操作を実現します。DataFrame APIは、スキーマ情報と紐付いた名前付きフィールドを保有しており、基本的なRDD APIの発展形と言えます。

DataFrame APIはHiveテーブルやJSONデータ、JDBCで接続したデータベース、その他Sparkの新しいデータソースAPIを経由したさまざまなデータから、データフレームを作成できます。

データフレームは、今後Sparkとその他システムとの間での標準的なデータ交換フォーマットになる予定です。データフレームは、PythonScalaJavaでサポートされています。

Spark SQL

本リリースにおいて、Spark SQLはアルファプロジェクトを卒業 (https://issues.apache.org/jira/browse/SPARK-5166) しました。

また、HiveQLの"方言"への後方互換性を保証し、安定したプログラミングAPIを提供することになりました。

Spark SQLは、各データソースAPIに対するテーブルの書き込み機能をサポートしました (https://issues.apache.org/jira/browse/SPARK-5658)。

新しいJDBCデータソースAPI (https://issues.apache.org/jira/browse/SPARK-5472) はMySQLPostgreSQL、その他のRDBMSとの間のインポート、エクスポートに対応しました。

HiveQLとの互換性を向上するため、多岐にわたる小さな機能追加が行われています。

また、Parquetと互換性のあるスキーマ構造を取り入れた (https://issues.apache.org/jira/browse/SPARK-3851) ことにより、機能が向上しています。

Spark ML / MLlib

本リリースにおいて、Spark MLlibにいくつかの新しいアルゴリズムが実装されました。

(1) トピックモデルのための"Latent Dirichlet Allocation (LDA)" (https://issues.apache.org/jira/browse/SPARK-1405)

(2) 多値分類のための多項ロジスティック回帰 (https://issues.apache.org/jira/browse/SPARK-2309)

(3) クラスタリングのためのガウス混合分布モデル (https://issues.apache.org/jira/browse/SPARK-5012) と (4) べき乗法クラスタリング (https://issues.apache.org/jira/browse/SPARK-4259)

(5) 頻出パターンマイニングのための頻出パターン成長 (FP-growth) モデル (https://issues.apache.org/jira/browse/SPARK-4001)

(6) 分散環境における線形代数処理のための "block matrix abstraction" (https://issues.apache.org/jira/browse/SPARK-4409)

また、交換可能なフォーマットによるモデルのインポート、エクスポートのサポートを開始しました (https://issues.apache.org/jira/browse/SPARK-4587)。今後、Java / Python / Scalaにおいてさらに交換可能なモデルを追加していきます。

k-means法とALSの実装を改良し、パフォーマンスが向上しました (https://issues.apache.org/jira/browse/SPARK-3424,%20https://issues.apache.org/jira/browse/SPARK-3541)。

PySparkにおいて、Spark 1.2で追加されたML pipeline API (https://issues.apache.org/jira/browse/SPARK-4586) と、勾配ブースティング木 (gradient boosted trees) (https://issues.apache.org/jira/browse/SPARK-5094) およびガウス混合分布モデル (https://issues.apache.org/jira/browse/SPARK-5012) をサポートしました。

ML pipeline APIは、新しいDataFrame構造をサポートします。

Spark Streaming

Spark 1.3では、"direct Kafka API"を提供します (https://issues.apache.org/jira/browse/SPARK-4964 ; http://spark.apache.org/docs/1.3.0/streaming-kafka-integration.html)。これにより、ログ先行書き込みを必要とせず、重複を排除したデータ入出力が可能になりました。

PythonのためのKafka APIも、将来的な拡張を念頭に実装されました (https://issues.apache.org/jira/browse/SPARK-5047)。

ロジスティック回帰のオンライン (リアルタイム) 処理 (https://issues.apache.org/jira/browse/SPARK-4979) を実装し、バイナリデータ (2値データ) を処理することが可能になりました (https://issues.apache.org/jira/browse/SPARK-4969)。

ステートフルな処理を実現するため、"initial state RDD"がサポートされました (https://issues.apache.org/jira/browse/SPARK-3660)。

ドキュメントを更新し、ストリーミング処理におけるSQLやDataFrameの扱いに関する情報を追加しました。また、Sparkにおける「フォールトトレランス」の意味を明確化しました。

GraphX

グラフにおける"canonical edge"のサポート (https://issues.apache.org/jira/browse/SPARK-4917) をはじめとした、いくつかの改良、拡張を行いました。

Spark 1.3へのアップグレード

Spark 1.3は過去の1.x系とバイナリ互換性があります。そのため、自作アプリケーションのコードなどを書き換える必要はありません。ただし、unstable扱いであったAPIは除きます。

例えば、Spark SQL APIが安定化したことにより、SchemaRDDクラスはDataFrameクラスに拡張、改名されました。詳細は、Spark SQLの移行ガイド (http://spark.apache.org/docs/1.3.0/sql-programming-guide.html#migration-guide) を参照してください。

Spark SQLは、列識別子を必要とします。予約語 ("string"や"table"など) を識別子に用いることもできますが、その場合はバッククォート (` `) によりエスケープします。

既知の問題点

(1) SPARK-6194: PySparkのcollect()関数におけるメモリリーク (https://issues.apache.org/jira/browse/SPARK-6194)
(2) SPARK-6222: Spark Streamingにおけるリカバリ処理に関する問題 (https://issues.apache.org/jira/browse/SPARK-6222)
(3) SAPRK-6315: Spark SQLにおいて、Spark 1.1で生成されたParquet形式のデータが読み込めない問題 (https://issues.apache.org/jira/browse/SPARK-6315)
(4) SPARK-6247: Spark SQLにおいて、いくつかのjoin構文の処理がエラーになる問題 (https://issues.apache.org/jira/browse/SPARK-6247)

クレジットは省略

SparkRのインストール(spark-ec2版)

Apache Spark R

参考:https://github.com/amplab-extras/SparkR-pkg/wiki/SparkR-on-EC2

前提

spark-ec2スクリプトクラスタが構成されていること。例えば、以下のような感じ。

./spark-ec2 -k SparkLab -i ~/sparklab/aws_key/SparkLab.pem -s 4 -t m3.xlarge launch SparkLab

マスタサーバにログインしてから、以降の作業をしていく。

./spark-ec2 -k SparkLab -i ~/sparklab/aws_key/SparkLab.pem login SparkLab

rJavaのダウンロード、スレーブへの配置

  1. wget http://cran.ism.ac.jp/src/contrib/rJava_0.9-6.tar.gz
  2. spark-ec2/bin/copy-dir rJava_0.9-6.tar.gz

RのJava設定

  1. R CMD javareconf
  2. spark/sbin/slaves.sh R CMD javareconf

rJavaのインストール

  1. tar xvzf rJava_0.9-6.tar.gz && R CMD INSTALL rJava
  2. spark/sbin/slaves.sh R CMD INSTALL rJava_0.9-6.tar.gz

SparkRのインストール

  1. git clone https://github.com/amplab-extras/SparkR-pkg.git
  2. cd SparkR-pkg
  3. ./install-dev.sh
  4. /root/spark-ec2/copy-dir /root/SparkR-pkg

ドキュメント(roxygen2)生成用のCurlインストール

  1. yum install curl-devel

SparkRの起動

  1. MASTER=spark://master_hostname:7077 ./sparkR

ドキュメントの生成

  1. install.packages("devtools")
  2. install.packages("roxygen2")
  3. library(devtools)
  4. devtools::document(pkg="./pkg", roclets=c("rd"))

……“素の”RとSparkRの比較ができるようなコードをいろいろ考えてみたが、ぱっとしないので、とりあえず導入手順だけ。