Word Cloud + kuromoji + Processing で日本語文章をビジュアライズ
完成品:
Word Cloud
文章中で出現頻度に重みを付け、その重みに応じた大きさで単語群を図示する手法。
Processing で行うには WordCram が手っ取り早く、デザインも良い。
いかにして日本語文章中の単語を抜き出すか
WordCram に何の手も加えていない日本語文章を読み込ませたところで、日本語単語への分かち書き方法を知らないため、不自然な Word Cloud が出来上がる。
そこで、日本語解析器である kuromoji を使い、対象文章を解析し、名詞を読みこませることにした。
下準備
WordCram
さて、まずは外部ライブラリである WordCram を 手元の Processing にインストールする。
- こちらから Processing 3.0 に対応した WordCram 1.0.0 の zip ファイルをダウンロードし、解凍する。
- Processing の sketchbook フォルダを開く。(
Processing
>Preferences
>Sketchbook location
)
- そのフォルダ内の
libraries
に、解凍した WordCram フォルダをコピーする。
基本的な使い方は次の通り:
import wordcram.*; // Set up the Processing sketch size(1000, 600); colorMode(HSB); background(230); // Make a wordcram from a random wikipedia page. new WordCram(this) .fromWebPage("https://en.wikipedia.org/wiki/Special:Random") .withColors(color(30), color(110), color(random(255), 240, 200)) .sizedByWeight(5, 120) .withFont("Copse") .drawAll();
kuromoji
kuromoji は Java 用のライブラリなので少し手を加える必要がある。
- こちらから zip ファイルをダウンロードし解凍する。
lib
フォルダ内にkuromoji-0.7.7.jar
ファイルがあるので、これをkuromoji.jar
にリネーム。- sketchbook フォルダの
libraries
にkuromoji/libraries
を作成し、先ほどのkuromoji.jar
ファイルを配置する。
基本的な使い方は次の通り:
import org.atilika.kuromoji.Token; import org.atilika.kuromoji.Tokenizer; import java.util.*; Tokenizer tokenizer = Tokenizer.builder().build(); List<Token> tokens = tokenizer.tokenize("吾輩は猫である。"); for (Token token : tokens) { println("PartOfSpeech:" + token.getPartOfSpeech()); println("surfaceForm:" + token.getSurfaceForm()); println("baseForm:" + token.getBaseForm()); }
出力:
PartOfSpeech:名詞,代名詞,一般,* surfaceForm:吾輩 baseForm:吾輩 PartOfSpeech:助詞,係助詞,*,* surfaceForm:は baseForm:は PartOfSpeech:名詞,一般,*,* surfaceForm:猫 baseForm:猫 PartOfSpeech:助動詞,*,*,* surfaceForm:で baseForm:だ PartOfSpeech:助動詞,*,*,* surfaceForm:ある baseForm:ある PartOfSpeech:記号,句点,*,* surfaceForm:。 baseForm:。
日本語文章を Word Cloud でビジュアライズ
これら2つのライブラリを活用して、ホッテントリのフィードを解析、Word Cloud を作成する。
String URL = "http://feeds.feedburner.com/hatena/b/hotentry"; XML[] items; String contents; PrintWriter output; String words; import wordcram.*; import org.atilika.kuromoji.Token; import org.atilika.kuromoji.Tokenizer; import java.util.*; void setup() { size(1000, 600); colorMode(HSB); background(230); XML xml = loadXML(URL); items = xml.getChildren("item"); for(int i = 0; i < items.length; i++){ contents += items[i].getChild("title").getContent(); contents += items[i].getChild("description").getContent(); } Tokenizer tokenizer = Tokenizer.builder().build(); List<Token> tokens = tokenizer.tokenize(contents); for (Token token : tokens) { String[] partOfSpeech = token.getPartOfSpeech().split(","); if (partOfSpeech[0].equals("名詞") && !token.getSurfaceForm().equals("こと")) { words += token.getSurfaceForm() + "\n"; } } output = createWriter("words.txt"); output.println(words); output.close(); drawWordCloud(); } void draw() { } void mousePressed() { drawWordCloud(); } void drawWordCloud() { println("creating a new word clound"); background(230); new WordCram(this) .fromTextFile("./words.txt") .withColors(color(30), color(110), color(random(255), 240, 200)) .sizedByWeight(5, 120) .withFont("Copse") .drawAll(); }
結果はこんな感じ:
WordCram にかける前にある程度意味のない頻出単語をフィルタしたほうが良い。今回は Processing での正規表現がわからなかったので、!token.getSurfaceForm().equals("こと")
のように kuromoji で弾くようにしている。