トレンドワード抽出をちょっとまともに

寒い

今年は節約のために暖房を使っておらず、換気のために窓を開けていることも多いので寒いです。身も心も懐も……。今年は就職できるといいんですけれど、なかなか厳しいです。

名詞から「RT」の削除

これまでに何度も出ているように、ツイート名詞の収集すると「RT」なんてのが名詞として判定されるし、頻出名詞として出るのでイヤです。削除するのは簡単ですが、簡単だからこそ、いつでもできるし……と除去をしていませんでした。
ツイートにおける頻出名詞ということを考えると、RT以降に続く文は誰かが書いた文が再度表れているわけで、ダブってカウントしているとも言えます。
そこで、ツイート中のRT以降の文はすべて除去することにします。非公式RTの代わりにQTを使って引用する人もいるので、QTも同様に処理します。引用した文の後に自分のコメントを書く人もいますが、そこらへんは無視します。
って、MeCab形態素解析する前にツイートに対してsedを通すだけです。

sed 's/[QR]T.*$//g'

これで名詞として「RT」や「QT」が出てくることはなくなりました。

記号は名詞として扱いたくない

先日名詞などから記号などをフィルタリングしたつもりでしたが、文字種判定がイイカゲンでしたし、後日のトレンドワード抽出処理ではフィルタリング処理を経由しないので、またもや記号などが現れていました。

そこで、以前のツイートから名詞を抽出する処理に追加して、それら記号などを除去することにします。MeCabは文字種が判定できるので、その判定結果を使います。MeCabでの文字種は辞書に依存します。辞書のあるディレクトリを見てみると、それらしきファイル( /usr/share/mecab/dic/ipadic/char.def )がありました。中には次のような記述があります。

DEFAULT        0 1 0  # DEFAULT is a mandatory category!
SPACE        0 1 0   
KANJI        0 0 2 
SYMBOL         1 1 0 
NUMERIC        1 1 0 
ALPHA        1 1 0 
HIRAGANA       0 1 2 
KATAKANA       1 1 2 
KANJINUMERIC   1 1 0 
GREEK        1 1 0 
CYRILLIC       1 1 0 

この順番が文字種IDになっているような気もします。確認のために、コマンドラインMeCabを動かして文字種IDを表示してみます。

$ mecab '--node-format=%m\t%f[0]\t%t\n'
こんにちは。私は「アホ」です。
こんにちは	感動詞	6
。	記号	3
私	名詞	2
は	助詞	6
「	記号	3
アホ	名詞	7
」	記号	3
です	助動詞	6
。	記号	3
EOS

「こんにちは」「は」「です」は6となっています。char.defの定義では0から数えて6番目がHIRAGANAなので合っています。括弧や句点は3でSYMBOLに対応するし、「アホ」は7でKATAKANAに対応しています。ってことで、とりあえずchar.defのこの定義順序が文字種IDだろうってことで作業を進めます。

MeCabの文字種IDを用いて記号などをフィルタリング

ツイートからの名詞抽出処理に、この文字種IDを用いたフィルタリングを加えます。記号を省くというだけではなく、1文字の語はそれが漢字でなければ省くという処理も加えます。これは名詞として判定された1文字のひらがなやカタカナを除去するためです。

#!/usr/bin/ruby
#Coding:utf-8

require 'MeCab'

#char type
CHAR_DEFAULT = 0
CHAR_SPACE = 1
CHAR_KANJI = 2
CHAR_SYMBOL = 3
CHAR_NUMERIC = 4
CHAR_ALPHA = 5
CHAR_HIRAGANA = 6
CHAR_KATAKANA = 7
CHAR_KANJINUMERIC = 8
CHAR_GREEK = 9
CHAR_CYRILLIC = 10

def isNoun(morph_type)
  morph_type == "名詞"
end

def isSymbol(char_type)
  char_type == CHAR_SYMBOL
end

def isKanji(char_type)
  char_type == CHAR_KANJI 
end

def isAcceptableNoun(morph_inf)
  return isNoun(morph_inf[1]) \
    && !isSymbol(morph_inf[2].to_i) \
    && (morph_inf[0].length != 1 || isKanji(morph_inf[2].to_i))
end

mc = MeCab::Tagger.new('--node-format=%m\t%f[0]\t%t\n --eos-format=\tEOS\n')

while gets
  morphs = mc.parse($_).force_encoding("utf-8").split("\n")
  morphs.each do |morph|
    morph_inf = morph.split("\t")
    puts morph_inf[0] if isAcceptableNoun(morph_inf)
  end
end

元旦のトレンドワード再抽出結果

前回、元旦のトレンドワードを抽出しましたが、今回変更した処理を経たデータを使って再度やり直してみました。
なお、前回は名詞の過去の平均出現頻度を得るために抽出対象日の11日前から2日前の10日間のデータを利用していましたが、8日前から2日前の7日間に変更しました。なんとなくですが1週間分あれば充分だろうと思います。

$ ./trend1.rb 20120101
争事	   546.0
出頭	   188.0
鳥島	   142.0
大凶	   139.1
ペッタン	   129.0
大儲け	   126.0
大損	   109.0
賭け事	   106.0
学業	    92.7
謹賀	    87.8
初夢	    76.7
大吉	    73.0
トリビア	    72.3
オウム真理教	    71.0
格付け	    70.2
ゃんあけおめ	    66.0
小吉	    63.5
Gackt	    63.3
ベイベー	    60.6
里谷	    59.0
アケオメ	    55.0
大河内	    55.0
あけ	    54.3
吹豪	    53.0
屠蘇	    53.0
ハス	    52.0
年初	    50.1
ぺったん	    49.6
メヌ	    49.0
ベイベ	    45.0
末吉	    44.7
343343	    43.0
辛酸	    43.0
運勢	    42.0
苦汁	    42.0
アンダルシア	    41.4
本年	    41.0
イタミン	    40.0
ピカル	    39.5
ガックン	    39.0
YEAR	    38.2
名塚	    38.0
富澤	    37.0
QE	    37.0
マジカルバナナ	    36.0
朝生	    36.0
TIGERandBUNNY	    35.0
幸先	    35.0
川崎大師	    35.0
願望	    34.6
あっけ	    34.3
ーベイ	    34.0
ペケポン	    33.0
清原	    32.5
梅宮	    32.0
貞治	    32.0
初詣	    31.9
年男	    29.3
アケオメ	    29.0
Year	    28.7
フットンダ	    28.6
初日の出	    28.3
お神酒	    28.0
コトヨロ	    28.0
護国	    28.0
ガクト	    27.8
雑煮	    27.7
凶	    27.1
上戸	    27.1
宇賀	    27.0
フレキス	    27.0
ジャニーズカウントダウン	    26.7
CDTV	    26.6
八幡宮	    26.1
書初め	    26.0
待人	    26.0
年頭	    26.0
堤下	    26.0
アビリティレベル	    26.0
HappyNewYear	    26.0

前回は記号やEUCでは表現できない文字が入っていましたが、マシな感じになりました。前回はいくつかあった数値がほとんど消えましたが、これはRT以降の文を削除したことが影響しています。唯一残っている「343343」は「343343+343343+343343=1030029」というツイートが複数あったことによります。これはテレビの「トリビアの泉」で「刺し身刺し身+刺し身刺し身+刺し身刺し身=お父さんはお肉」というネタをやったためです。

あとは複合語をまともに扱えるようになればだいぶマシになるのですが、複合語の扱いは敷居が高そうです。