文字分析

かな3グラムの物差しを作ってみる

前回の「かな3グラム分析」というエントリで、投稿数の多かったIDの「かな3グラム」リストを作ってみました。

今回は、このリスト同士の近さ/遠さを測る物差しを試してみました。物差しと言うのは、ID「A」とID「B」があった時に、それらのリストがどの程度の類似しているか(=どの程度の近さにあるか)を測る道具という意味です。

この道具として「類似度」を以下のように定義しました。

  • Aのリストには、各3グラムに対する出現率が計算されているとする。例えば、リストされた全3グラムの総出現回数が3000で、「しかし」の出現回数が10ならば、「しかし」の出現率は10÷3000=0.33%。
  • ある3グラムが、AとBの両方のリストに存在する場合、その3グラムの出現率の小さい方の値を取る。
  • Aのリストにある全ての3グラムに対して、上記の値を集計したものを、AとBの類似度とする。(Bのリストに対して同じ操作をやったとしても同じ類似度になる筈 ★追記:これは間違っているかもしれません。もう一度考えてみます。)

言い換えると、Aの3グラム全体をBの3グラムで塗りつぶしたら、Aの全体の何%が塗られるか、というのが類似度です。この類似度はAとBの組合せに対して定義されるので、例えばIDが10個あったとすると、類似度は「10×9÷2=45」個ある事になります。

投稿回数が多かった以下の10個のIDに対して、類似度を計算してみました(リスト中に×をつけたのはプログラム上の問題でうまく行かないので除外しました)。

  • "ID","投稿回数"
  • "LcGCvJzD0",181
  • "tDFR9K4O0",179
  • "V+JBJ/g20",172 ×
  • "W0TlTNwBO",142
  • "bHdrgqPh0",141
  • "PUKvC9zG0",125
  • "zW3b9lWV0",113
  • "bhHp1lbI0",103
  • "4W0I7nSj0",99
  • "0N2z540MO",98
  • "???0",98 ×
  • "UvSWUjb+0",95 ×
  • "sIdB1Bjh0",94

類似度の大きい順に並べたリストを以下に置きました。カラムのid1-URLとid2-URLには「必死チェッカーもどき」へのURLを入れておいたので、発言内容が知りたい時はこのカラムをクリックしてください。

http://spreadsheets.google.com/pub?key=rKhn-vQysHs8lDevWs8RNvw&single=true&gid=0&output=html

最大の類似度は、PUKvC9zG0とzW3b9lWV0の43%です。また、この二者とLcGCvJzD0もお互いに高い類似度を示しており、PUKvC9zG0・zW3b9lWV0・LcGCvJzD0が同じような文体の傾向を示しているように見えます。内容を見ると、論調も似通っているように思えます。しかし、類似度が少し小さくなると、正反対の意見内容だったりするので、どこまで有効なのか判断がつきません。

という訳で、もう少しIDの範囲を広げて検証してみようかと思っています。

以上

| | コメント (0) | トラックバック (0)

かな3グラム分析

スレ乱立」というエントリであげた「最後のパレード」盗作疑惑関連の74スレッドについて、ID毎の文体の特徴を自動的に取り出せないかと思って試してます。

今までの経験から、漢字の熟語はその人の特徴というより、その時の話題の特徴を表しやすいと考えています。そのため、今回は、仮名(ひらがな、カタカナ)と文尾に来る特殊な文字(!や?など)を対象に頻度を調べてみようと思います。

まず、調査対象を絞るために、投稿数が100回を越えるIDのリストを作ります(以下)。

  • "id","count"
  • "LcGCvJzD0",181
  • "tDFR9K4O0",179
  • "V+JBJ/g20",172(※後述)
  • "W0TlTNwBO",142
  • "bHdrgqPh0",141
  • "PUKvC9zG0",125
  • "zW3b9lWV0",113
  • "bhHp1lbI0",103

この各IDについて、以下の文字が3個連続して現れるパターン(3グラム)を抽出し、その総計を調べます。

  • ひらがな(ぁあ~をんゔ)
  • カタカナ(ァア~ヷヸヹヺ)
  • 長音(ー)
  • 文尾にきそうな記号(。、.,.,!?!?)
  • 改行(ここではアレフ文字「ℵ」で表現)

上記の(※)をつけた"V+JBJ/g20"については、プログラム上の問題(何故かエラーが出る)が解決できず、調べていません。(こういう「ええ加減さ」が趣味的なプログラムの良いところです)

結果は以下の通り。Google Spreadsheetに一覧を載せました。

"LcGCvJzD0",181
http://spreadsheets.google.com/pub?key=rqKg1kmO82ny59BathDZAbg

"tDFR9K4O0",179
http://spreadsheets.google.com/pub?key=rbqWzJf8fp59vRuJOXFawFw

"V+JBJ/g20",172
なし

"W0TlTNwBO",142
http://spreadsheets.google.com/pub?key=rq5XVGwH6o69K_zpat1-erw

"bHdrgqPh0",141
http://spreadsheets.google.com/pub?key=rN9EDIjpBxk3k7oZeCY9Z5g

"PUKvC9zG0",125
http://spreadsheets.google.com/pub?key=rVCpvDnOBltCDP-8wEVNlUQ

"zW3b9lWV0",113
http://spreadsheets.google.com/pub?key=rcOwsOtPIQ6eTYaOauOznoA

"bhHp1lbI0",103
http://spreadsheets.google.com/pub?key=rWYOLhBHy916ZLLzkSfc0NQ

全ID対象(全部で102,189件になるので上位1000件程度のみ)
http://spreadsheets.google.com/pub?key=rcsB6otNlby5d7kWFpHSZlQ

リストの第一項目(body)は3グラムの文字列を、第二項目(count)は出現回数を示します。第三項目の項目名ratioの後ろにある数字(3337等)は出現回数の総和を示し、第三項目の値は総和に対する割合を示します(処理の都合で10の9乗倍しているのでやたらと大きな数値になってますが、パーセントと同じ意味です)。

一番面白かったのは、"W0TlTNwBO"さんの一位が「すかぁ」だった事です。すっかり流行語になった「すかぁ」については、3羽の雀さんの以下の記事で知りました。

http://d.hatena.ne.jp/three_sparrows/20090504/p1
2009-05-04 リコールかぁ

あと、文字を反転させてみると、最後の「読売社内も、徹底検証しないわけにはいかない事態に立ち至っているんじゃないでしょうか!?」のあとに「すかぁ。」という文字が見えます。最初は「・・・立ち至っているんじゃないですかぁ。」と書いてたんでしょうね。

この他の3グラムの特徴を見比べているのですが、もっと道具を作らないと人間の目では類似点や相違点を見つけるのが難しいですね。例えば、目で見て以下のような特徴を見つけました。今日はこれで自己満足して寝ることにします。

◆IDによって使用/不使用が分かれる用語
(1) "ねらー"
de-id-count-sorted-ratio-all1000.csv: "ねらー",401,233386
de-id-count-sorted-ratio-tDFR9K4O0.csv: "ねらー",7,2610966
de-id-count-sorted-ratio-LcGCvJzD0.csv: "ねらー",3,899011
de-id-count-sorted-ratio-W0TlTNwBO.csv: "ねらー",4,1260636

(2) "じゃね"
de-id-count-sorted-ratio-all1000.csv: "じゃね",1708,994073
de-id-count-sorted-ratio-LcGCvJzD0.csv: "じゃね",5,1498351
de-id-count-sorted-ratio-tDFR9K4O0.csv: "じゃね",4,1491980
de-id-count-sorted-ratio-bHdrgqPh0.csv: "じゃね",7,2648505
de-id-count-sorted-ratio-bhHp1lbI0.csv: "じゃね",9,2631578

◆特有の文尾
(3) "ヨ"で終わるもの(おそらく★印のものが文尾)
de-id-count-sorted-ratio-LcGCvJzD0.csv: "ますヨ",1,299670★
de-id-count-sorted-ratio-W0TlTNwBO.csv: "インヨ",1,315159
de-id-count-sorted-ratio-bHdrgqPh0.csv: "ℵサヨ",1,378357
de-id-count-sorted-ratio-PUKvC9zG0.csv: "せんヨ",3,1118985★
de-id-count-sorted-ratio-PUKvC9zG0.csv: "ですヨ",2,745990★
de-id-count-sorted-ratio-PUKvC9zG0.csv: "ますヨ",2,745990★
de-id-count-sorted-ratio-zW3b9lWV0.csv: "ますヨ",3,1337494★
de-id-count-sorted-ratio-zW3b9lWV0.csv: "ですヨ",2,891662★
de-id-count-sorted-ratio-bhHp1lbI0.csv: "てサヨ",1,292397
de-id-count-sorted-ratio-bhHp1lbI0.csv: "トウヨ",1,292397

◆特有の文頭
(4) 改行して"で、"で始まるもの
de-id-count-sorted-ratio-all1000.csv: "ℵで、",358,208359
de-id-count-sorted-ratio-LcGCvJzD0.csv: "ℵで、",3,899011
de-id-count-sorted-ratio-tDFR9K4O0.csv: "ℵで、",2,745990
de-id-count-sorted-ratio-bHdrgqPh0.csv: "ℵで、",4,1513431
de-id-count-sorted-ratio-bhHp1lbI0.csv: "ℵで、",5,1461988

語尾が「ネ」や「ヨ」の文章については、最近のν速+の投稿でも目立ってきており、松沢呉一さんの以下の記事で指摘されています。但し、上記は内容に関係なく集計していますので、語尾に「ヨ」があったからといって直ぐに中村克氏擁護と判断する事はできませんのでご注意を。

http://www.pot.co.jp/matsukuro/%E3%81%8A%E9%83%A8%E5%B1%8B1894%E7%80%AC%E6%88%B8%E5%BC%98%E5%B9%B8%E3%81%AF%E9%80%83%E4%BA%A1%E3%81%8B.html
2009-05-15
お部屋1849/瀬戸弘幸は逃亡か【追記あり】

2ちゃんねるでも、「東村山市民の2割が創価学会員」なんて書き込みを必死にやっている人がいます。これが矢野や朝木であるかどうかわからないですが、矢野穂積が「匿名ネット族」になって、2ちゃんねるに書き込んでいることは間違いなさそうです。「ネ」「ヨ」という語尾以外に、矢野穂積の癖が出ているコメントがありますので。だから、少しは市議の仕事をやれって。

以上

| | コメント (0) | トラックバック (0)

2chのν速+における「コピペ宣伝」の検証

相変わらず東村山界隈の話題はたいへんな勢いで推移していくので全くついていけてません。はるか数周前の話題で恐縮ですが、調べてみたので報告します。

4月9日の03:10:06に、「【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」」というスレが2chのニュース速報+(以下、ν速+と略す)に立ちました。このスレは★15(15番目のスレを意味する)まで継続されました。最後の書き込みは、★15の580番目の「2009/04/21(火) 01:48:17」だと思われます。スレ一覧は文末に示しました。

確かめたかったのは、こういった一連のスレの中で「コピペ宣伝」が行われているか否か、また行われているとすると、どういう内容でどういう頻度なのかという点です。ここでコピペ宣伝とは、おそらくは特定のメッセージの宣伝の意図を持って、同じ内容のレスを繰り返し投稿する行為を指します。2chを見ていると良く目にするような気はするのですが、定量的に示せるデータがなかったので調べてみました。

まず、「コピペ宣伝レス」を以下のように定義しました。認定条件2を加えたのは、短時間の内に何回も同じレスを書き込むケースは宣伝というより読者の反応を考えない自己満足行為だと考えたからです。また、「どっちもどっちだな」や「踊れ☆コリア」など、メッセージ性が乏しい短文レスを排除するため、認定条件3を加えました。

(認定条件1) 同一内容のレスであり、最初~★15の全スレで3回以上投稿されている
(認定条件2) 同一内容レスの初回と最終回の投稿時間が12時間以上離れている
(認定条件3) レスの長さが40文字以上である

このような条件に該当する「コピペ宣伝レス」の一覧は以下のようになります(一覧では個人名は**で置き換えました。また半角カンマは処理の都合で全角カンマに変換してあります)。全部で22種類のレスがあります。

投稿回数    先頭40文字
22    必見!!韓国人・***に暴行を受けた新風の弁士・****(38歳、街宣右翼)は、
8    帰化しろよそんなに在日特権が惜しいのか?そんなに祖国が嫌なのか?じゃあ、帰化して
8    http://de.nicovideo.jp/watch/sm6668694&n
7    ■北朝鮮と戦争したい■拉致被害者を取り戻すために。ミサイル発射を阻止するために。
7    【朝鮮半島の統治国の歴史】万年属国から独立まで(笑)紀元前108年〜220年:漢
6    自民党支持者よ、これだけは覚えておけ。民主の評価が下がっただけで、自民の評価が上
6    〔名称〕維新政党・新風 〔母体〕統一協会、勝共連合 〔代表〕
6    日本は在日癌という病気にかかっております少し前までは熱や痛みを感じなかったのです
4    <日本人を100%とした場合の外国人犯罪比率>刑法犯凶悪犯粗暴犯窃盗犯知能犯覚醒
4    汚い手段で日本に寄生してる朝鮮人については、このスレを見てください。実は自称在日
4    【寄生虫駆除】(きせいちゅうくじょ)名詞寄生虫駆除は、諸君が「寄生虫を駆除しよう
3    憲法9条がある限り、日本は専守防衛で、尚且つ、自国領でしか戦闘できない。敵国に物
3    世界基督教統一神霊協会御用達の在日朝鮮記者おそろくんが立てた電通公認シオサイトス
3    お前らがいくらどんなに朝鮮人って罵っても、一般の善良な日本人は強制的に日本に連れ
3    朝鮮人なんか昔からこうだよhttp://blog-imgs-11.fc2.com
3    図書館へ行ったら、下記のバックナンバーを読もう。●正論2003年6月号掲載評論家
3    日本が阪神・淡路大震災で受けた援助(抜粋)米国:地震専門家、毛布57千枚、飲料水
3    561:おさかなくわえた名無しさん:2008/02/17(日)22:36:40I
3    民主党は韓国に賠償したくてしたくて仕方ないらしいw日本を自ら悪に仕立て上げてまで
3    街宣右翼は似非右翼の朝鮮人だった。ここでも日本人のフリ偽者違法コピー■右翼団体「
3    汚い手段で日本に寄生してる朝鮮人については、このスレを見てください。実は自称在日
3    7⌒ー-//|,′ヽ`ヽ///-‐ト、{卜、‘,.| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|/

投稿回数トップ(22回)のレスは新風弁士を揶揄していると思いますが、半数以上は朝鮮に対する憎悪や侮蔑を煽るものです。また、トップのレスを除けば、各々のレスの投稿回数は8回以下です。もっと回数が多いと予想していたのでこれは意外な結果でした。

ところが元のレスを抜き出して見てみると面白い事が分かります。一つのIDで複数種類のレスを書き込んでいるケースが結構あるのです。

一つのIDで複数種類のレスを書いている事を裏返すと、「このコピペ宣伝レスを書いた人はこんなコピペ宣伝レスも書いています」という関係性が分かります(Amazonの商品推薦と似てます)。「こんなコピペ宣伝レスを書いた人は、こんなコピペ宣伝レスも書いています」を繰り返し、この関係をどんどん辿っていけば、コピペ宣伝レスをグループ化できます。このグループは「一人もしくは同じ意図を持った人達が使ったコピペ宣伝レスの集まり」とみなして良いでしょう。

この観点で先ほどのコピペ宣伝レス一覧をグループ化してみると、複数レスでグループになったのは以下の3つでした。各レスの先頭の括弧付き数字は書き込み回数を示します。

◆グループ1
(3)憲法9条がある限り、日本は専守防衛で、尚且つ、自国領でしか戦闘できない。敵国に物
(8)帰化しろよそんなに在日特権が惜しいのか?そんなに祖国が嫌なのか?じゃあ、帰化して
(7)■北朝鮮と戦争したい■拉致被害者を取り戻すために。ミサイル発射を阻止するために。
(3)街宣右翼は似非右翼の朝鮮人だった。ここでも日本人のフリ偽者違法コピー■右翼団体「
(3)日本が阪神・淡路大震災で受けた援助(抜粋)米国:地震専門家、毛布57千枚、飲料水

◆グループ2
(6)日本は在日癌という病気にかかっております少し前までは熱や痛みを感じなかったのです
(3)7⌒ー-//|,′ヽ`ヽ///-‐ト、{卜、‘,.| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|/

◆グループ3
(6)〔名称〕維新政党・新風 〔母体〕統一協会、勝共連合 〔代表〕
(8)http://de.nicovideo.jp/watch/sm6668694&n
(22)必見!!韓国人・***に暴行を受けた新風の弁士・****(38歳、街宣右翼)は、

これを見ると、同じグループに属するレスは例えば朝鮮を貶めるといった一つの意図に基づいていると考えて良いと思います。また、例えばグループ1では各々のレスの投稿回数は少なくても、合計すれば24回と相当な回数になります。複数種類のレスを使い分ける事によって、読み手の拒否感を少なくする効果もあると思われます。宣伝する立場に立てば当たり前の工夫かもしれませんが、今回発見して感心しました(^^;

今回の結論は以下です。
・一定の意図に基づき同じレスを複数回書き込む「コピペ宣伝」は存在する。
・書き込まれるレスは1種類とは限らない。複数種類のレスを組合せたコピペ宣伝が存在する。

以上

■リスト1:ν速+で立った該当スレ一覧(逆順)
【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★15
http://tsushima.2ch.net/test/read.cgi/newsplus/1239820133/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★14
http://tsushima.2ch.net/test/read.cgi/newsplus/1239690574/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★13
http://tsushima.2ch.net/test/read.cgi/newsplus/1239626034/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★12
http://tsushima.2ch.net/test/read.cgi/newsplus/1239556561/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★11
http://tsushima.2ch.net/test/read.cgi/newsplus/1239521878/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★10
http://tsushima.2ch.net/test/read.cgi/newsplus/1239457892/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★9
http://tsushima.2ch.net/test/read.cgi/newsplus/1239426250/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★8
http://tsushima.2ch.net/test/read.cgi/newsplus/1239389903/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★7
http://tsushima.2ch.net/test/read.cgi/newsplus/1239366288/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★6
http://tsushima.2ch.net/test/read.cgi/newsplus/1239353323/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★5
http://tsushima.2ch.net/test/read.cgi/newsplus/1239288558/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★4
http://tsushima.2ch.net/test/read.cgi/newsplus/1239263102/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★3
http://tsushima.2ch.net/test/read.cgi/newsplus/1239252170/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」★2
http://tsushima.2ch.net/test/read.cgi/newsplus/1239224309/

【韓国・朝鮮】北朝鮮ミサイル反対を演説する日本人を韓国人青年が襲う「動画に収められた一部始終」
http://tsushima.2ch.net/test/read.cgi/newsplus/1239214206/

| | コメント (0) | トラックバック (0)

そのような率

年が明けたと思ったら、仕事の方では延伸だの発注停止だの暗い話題続き。政治の世界でもイスラエルのガザ虐殺はエスカレートする一方で何とも重苦しい1月です。

さて、気を取り直して文字分析の続きです。
Interstage Data Effector体験版というツールを使っているのですが、データの連結機能が文字列の出現頻度を測るのに使えると分かりました。

これは意外な発見でした。データベースで言うとJOIN操作に当たる機能ですが、文字の部分列の一致でJOINができるのが面白い所です。

以下のようなコメントデータベース(タブ区切りテキストファイル)があるとします。

■de1-test.txt
filename    blogdate    comauthor    comdate    comtime    post    body
26873583.html    2005年07月01日    鉄男    2005-07-02    01:31    Posted by 鉄男 at 2005年07月02日 01:31     あのような物体をそのような態度で取り扱ったのがこのような事態を招いた原因だ。
27140626.html    2005年07月04日    正雄    2005-07-06    08:44    Posted by 正雄 at 2005年07月06日 08:44     うんこのような黒い物体をそのように取り扱ってはならない。このような取り扱いが正しいのです。
27140626.html    2005年07月04日    正雄    2005-07-06    10:45    Posted by 正雄 at 2005年07月06日 10:45     そうですか
26873583.html    2005年09月01日    鉄男    2005-09-02    01:31    Posted by 鉄男 at 2005年09月02日 01:31     あのような物体をあのような態度で取り扱ったのがあのような事態を招いた原因だ。

これを以下のコマンドで処理します。
shunreplace -s de1-testrep.cfg -j de1-repcond.txt > test1-rep.txt

出力されたファイルは以下のようになります。

■test1-rep.txt
"comdate","comtime","comauthor","countkey"
"2005-07-02","01:31","鉄男","あのような"
"2005-07-02","01:31","鉄男","そのような"
"2005-07-02","01:31","鉄男","このような"
"2005-07-02","01:31","鉄男","。"
"2005-07-06","08:44","正雄","このような"
"2005-07-06","08:44","正雄","そのように"
"2005-07-06","08:44","正雄","。"
"2005-07-06","10:45","正雄",
"2005-09-02","01:31","鉄男","あのような"
"2005-09-02","01:31","鉄男","。"

「あのような」「このような」「そのような」「あのように」「このように」「そのように」「。」という7種類の文字列が出現すると、そのレコード(行)のコメント日付、時刻、著者とその文字列を出力するよう設定したのです。

鉄男さんの最初のコメントは、「あのような」「そのような」「このような」「。」の4つを含んでいるので、4行の出力に展開されました。
正雄さんの最初のコメントには「このような」が2回含まれていますが、この場合でも出力は1行になります。コメントの中の出現回数を測る事はできなくて、出現したか否かだけを測る事ができます。また、文節などは意識していませんので、「うんこのように」という文脈であっても「このように」という文字列として判定されます。
正雄さんの2番目のコメントのように該当文字列が無い場合には、空の項目が出力されます。

上記のようにするための設定ファイルは以下のようになります。

■de1-testrep.cfg
FieldSeparator "\t"
JnlFile J "F:\stringcount\de1-test.txt"
MstFile {
  M "F:\stringcount\de1-repmaster.txt"
}

■de1-repmaster.txt
keyword    countkey
。    。
あのような    あのような
あのように    あのように
このような    このような
このように    このように
そのような    そのような
そのように    そのように

■de1-repcond.txt
CharacterCode UTF-8
InFileType CSV
ListDef {
  document(J) {
    $filename filename,
    $blogdate blogdate,
    $comauthor comauthor,
    $comdate comdate,
    $comtime comtime,
    $post post,
    $body body
  },
  document(M) { $key keyword, $countkey countkey }
}
OutputDef {
  $comdate, $comtime, $comauthor, $countkey
}
Jcondition {
  join(J,M, $body = $key, "LEFT")
}

これができてしまえば、shunanalyzeコマンドを使った以下の集計で簡単に頻度一覧を出せます。

shunanalyze -s de2-analyze.cfg -a de2-anacond.txt < test1-rep.txt > test2-ana.txt

結果は以下の通り。

■test2-ana.txt
"comauthor","time","maru","total","あのような","あのように","このような","このように","そのような","そのように"
"正雄","2005-07-01",1,2,0,0,1,0,0,1
"鉄男","2005-07-01",2,4,2,0,1,0,1,0

カラムの意味は以下の通りです。
1カラム目comauthor:コメント著者
2カラム目time:コメント日付
3カラム目maru:「。」の出現したコメント数
4カラム目total:「あのような」~「そのように」の6種の文字列が出現した延べコメント数
5カラム目あのような:「あのような」が出現した延べコメント数
・・・

「。」の出現するコメント数は、おそらく全コメント数に近くなると思っています。全コメント数に対する比率を考えたかったので数えてみました。本当はコメント数を別途集計する方が正確なのですが、面倒なので「。」の出現するコメント数で代替したのです。

また、totalは一つのコメントを2回以上カウントしている可能性のある数なので、全コメント数との比率を読む時には注意が必要です。

設定ファイルは以下のようにしました。

■de2-anacond.txt
CharacterCode  UTF-8

InFileType     CSV
OutFileType    CSV
MemorySize     1000

LCondition {
  $n_。_ :=
    IF  $countkey == "。" THEN 1
    ELSE 0
    ENDIF,
  $n_あのような_ :=
    IF  $countkey == "あのような" THEN 1
    ELSE 0
    ENDIF,
  $n_あのように_ :=
    IF  $countkey == "あのように" THEN 1
    ELSE 0
    ENDIF,
  $n_このような_ :=
    IF  $countkey == "このような" THEN 1
    ELSE 0
    ENDIF,
  $n_このように_ :=
    IF  $countkey == "このように" THEN 1
    ELSE 0
    ENDIF,
  $n_そのような_ :=
    IF  $countkey == "そのような" THEN 1
    ELSE 0
    ENDIF,
  $n_そのように_ :=
    IF  $countkey == "そのように" THEN 1
    ELSE 0
    ENDIF
}

GCondition  substr($comauthor,0,25) comauthor, trunc_date($comdate,"HALF") time
RCondition    sum($n_。_) maru ,  sum($n_あのような_) + sum($n_このような_) + sum($n_そのような_) + sum($n_あのように_) + sum($n_このように_) + sum($n_そのように_) total,  sum($n_あのような_) あのような,  sum($n_あのように_) あのように,  sum($n_このような_) このような,  sum($n_このように_) このように,  sum($n_そのような_) そのような,  sum($n_そのように_) そのように

■de2-analyze.cfg
# FieldSeparator "\t"
WorkFolder "F:\stringcount\"

なぜこのようにしたかと言うと、シベリア板に以下のような発言があって、気になっていたからです。

20 名前:いやあ名無しってほんとにいいもんですね[sage] 投稿日:2008/12/09(火) 20:03:38 発信元:219.165.53.195
前から気になってたんですが、今回のエントリで数えて、みたら
このような 9回
そのような 2回
この、その、これ、それ等多数が使用されていました。
それだけですが…

22 名前:いやあ名無しってほんとにいいもんですね[sage] 投稿日:2008/12/10(水) 21:27:02 発信元:219.165.53.195
ANA関係のエントリではざっと数えて(文脈のおかしいのはおいといて)
このような(に) 1
この 12
これ 7
その 2
それ 4
> この件ですが、これは飲んでいたことは事実ですが、その後の調査でこのサプリメントはその検査機には反応しないことが分かったそうです。
サプリメントは「ミッカンMICRA」と言うものだそうですが、それは酢酸が混入しているので、それが検査機に反応したと思ったそうですが、
そうではなかったという回答が得られました。
この件も私がブログで書いたので、慌てて会社側が調べ直して、「サプリメントではなかった。」と報告をし直したと私は考えています。
あくまでも初期段階の話で、後日判明したそうですが、私が書かなければこのケースはサプリメントが犯人にされていたかも知れません。
さて、日本航空が花火を積んで運んだ件ですが、この便に乗車した方がいればと呼びかけましたが、現在までの所メールはありませんでした。

こういうものなんでしょうか?

23 名前:いやあ名無しってほんとにいいもんですね[sage] 投稿日:2008/12/10(水) 21:37:40 発信元:219.165.53.195
領海侵犯
このような 4
この 6
その 6

言われてみると、瀬戸氏の発言には「このような」という言い回しが多用されている印象があります。てな訳で、2008年末までの全コメントについて先ほどの方法でカウントしてみました。

■stringcount.bat
rem stringcount.bat
rem de-repmaster.txt で定義したキーワードの出現回数をカウントする
del countout1-rep.txt countout2-ana.txt countout3-sel.txt countout4-sort.txt
shunreplace -s de1-rep.cfg -j de1-repcond.txt > countout1-rep.txt
shunanalyze -s de2-analyze.cfg -a de2-anacond.txt < countout1-rep.txt > countout2-ana.txt
shunselect -s de3-sel.cfg -q de3-selcond.txt < countout2-ana.txt > countout3-sel.txt
shunsort -a de4-sortcond.txt < countout3-sel.txt > countout4-sort.txt

■de1-rep.cfg
FieldSeparator "\t"
JnlFile J "D:\scomgram\commentdb-noq.txt"
MstFile {
  M "F:\stringcount\de1-repmaster.txt"
}

■de3-selcond.txt (以下の条件で抽出)
1 $total >= 5 AND $maru >= 20

結果をExcelに取り込んで、「。」出現コメント数に対するtotal数の率の順に並べてみました。
20%以上のコメント者は以下のようになります。timeの欄は、yyyy-01-01となっているのが1月~6月の上半期、yyyy-07-01となっているのが7月~12月の下半期を表します。これを見ると、どの時期をとっても、瀬戸氏の発言は率が高い事が分かります。こんなに鮮やかに現れるとは驚きです。

comauthor    time    maru    total    率
ヒトシ1015    2008-01-01    28    9    32.1%
せと弘幸    2007-07-01    81    26    32.1%
大韓王    2008-07-01    82    25    30.5%
瀬戸弘幸    2006-07-01    418    126    30.1%
sayoku?    2006-07-01    217    64    29.5%
瀬戸弘幸    2006-01-01    693    189    27.3%
基準点    2006-07-01    33    9    27.3%
土民    2008-07-01    46    12    26.1%
瀬戸弘幸    2007-01-01    267    67    25.1%
愛国主義者    2007-01-01    20    5    25.0%
datetopic    2006-07-01    20    5    25.0%
月影兵庫    2008-07-01    85    21    24.7%
!    2008-07-01    78    19    24.4%
多聞丸    2008-01-01    25    6    24.0%
瀬戸弘幸    2005-07-01    30    7    23.3%
荑戸弘幸    2006-01-01    95    22    23.2%
視点    2006-07-01    52    12    23.1%
せと弘幸    2008-07-01    261    59    22.6%
主婦    2008-01-01    46    10    21.7%
WWWへの同情者その2    2008-07-01    37    8    21.6%
せと弘幸    2008-01-01    128    27    21.1%
トランプ    2006-07-01    86    18    20.9%
まりこ    2006-07-01    34    7    20.6%

では、どの言葉の出現頻度が高いかを以下の一覧で見てみます。瀬戸氏については、「そのような」「このような」が多いようです。

comauthor    time    maru    total    率    あのような    あのように    このような    このように    そのような    そのように
ヒトシ1015    2008-01-01    28    9    32.1%    0    0    8    0    1    0
せと弘幸    2007-07-01    81    26    32.1%    0    0    7    0    13    6
大韓王    2008-07-01    82    25    30.5%    0    0    11    1    11    2
瀬戸弘幸    2006-07-01    418    126    30.1%    2    0    26    6    77    15
sayoku?    2006-07-01    217    64    29.5%    3    1    11    2    31    16
瀬戸弘幸    2006-01-01    693    189    27.3%    4    1    59    12    96    17
基準点    2006-07-01    33    9    27.3%    0    0    6    0    2    1
土民    2008-07-01    46    12    26.1%    2    0    5    2    3    0
瀬戸弘幸    2007-01-01    267    67    25.1%    1    0    13    2    44    7
愛国主義者    2007-01-01    20    5    25.0%    0    0    3    0    2    0
datetopic    2006-07-01    20    5    25.0%    1    0    3    0    1    0
月影兵庫    2008-07-01    85    21    24.7%    2    0    10    0    7    2
!    2008-07-01    78    19    24.4%    0    0    9    0    6    4
多聞丸    2008-01-01    25    6    24.0%    1    0    2    1    2    0
瀬戸弘幸    2005-07-01    30    7    23.3%    0    0    1    0    4    2
荑戸弘幸    2006-01-01    95    22    23.2%    0    0    8    1    13    0
視点    2006-07-01    52    12    23.1%    2    0    7    0    3    0
せと弘幸    2008-07-01    261    59    22.6%    1    0    10    0    34    14
主婦    2008-01-01    46    10    21.7%    0    0    4    3    2    1
WWWへの同情者その2    2008-07-01    37    8    21.6%    1    0    3    0    2    2
せと弘幸    2008-01-01    128    27    21.1%    0    0    8    2    14    3
トランプ    2006-07-01    86    18    20.9%    1    0    9    0    7    1
まりこ    2006-07-01    34    7    20.6%    0    0    4    0    3    0

そこで、「そのような」の出現率に着目して並べたのが以下の一覧です。この表では更に鮮やかに瀬戸氏の「そのような」多用傾向が現れていると思います。

comauthor    time    maru    total    率    あのような    あのように    このような    このように    そのような    そのように    そのような率
瀬戸弘幸    2006-07-01    418    126    30.1%    2    0    26    6    77    15    18.4%
瀬戸弘幸    2007-01-01    267    67    25.1%    1    0    13    2    44    7    16.5%
せと弘幸    2007-07-01    81    26    32.1%    0    0    7    0    13    6    16.0%
sayoku?    2006-07-01    217    64    29.5%    3    1    11    2    31    16    14.3%
瀬戸弘幸    2006-01-01    693    189    27.3%    4    1    59    12    96    17    13.9%
荑戸弘幸    2006-01-01    95    22    23.2%    0    0    8    1    13    0    13.7%
大韓王    2008-07-01    82    25    30.5%    0    0    11    1    11    2    13.4%
瀬戸弘幸    2005-07-01    30    7    23.3%    0    0    1    0    4    2    13.3%
せと弘幸    2008-07-01    261    59    22.6%    1    0    10    0    34    14    13.0%
『日本よ何処へ』管理者    2007-07-01    86    11    12.8%    0    0    0    0    11    0    12.8%
せと弘幸    2008-01-01    128    27    21.1%    0    0    8    2    14    3    10.9%
opps    2006-07-01    46    9    19.6%    0    0    3    0    5    1    10.9%
極右評論管理者    2006-01-01    231    30    13.0%    1    1    2    0    24    2    10.4%
kame    2006-07-01    78    12    15.4%    1    0    2    0    8    1    10.3%
愛国主義者    2007-01-01    20    5    25.0%    0    0    3    0    2    0    10.0%

本日は以上です。

| | コメント (0) | トラックバック (0)

特定著者コメントのNグラム頻度集計

今回は、前回出した瀬戸氏コメント集をNグラム集計してみました。

まずは数が少ないのですが2005年分(コメント数:31)から。
8グラムのTOP2は以下の通りです。コメントに対して応答を返しているとすると納得行きます。
"8","ありがとう御座い",10
"8","りがとう御座いま",10

2グラムのTOP5は以下の通りです。文尾の形は共通になりやすいという事だと思います
"2","す。",106
"2","ます",77
"2","てい",68
"2","いま",64
"2","。 ",59

漢字2文字の2グラムのTOP5は以下の通りです。極右の政治ブログらしい熟語が並んでいます。
"2","主義",26
"2","日本",23
"2","極右",22
"2","社会",19
"2","国家",16

次は最も年間コメント数が多い2006年分(コメント数:1207)です。
8グラムの上位は以下の通りです。とおるさんと怒る小市民さんへの返答が多かった事が伺えます。
"8","ありがとう御座い",254
"8","りがとう御座いま",254
"8","がとう御座います",217
"8","とう御座います。",211
"8"," とおるさんへ ",124
"8","ではないでしょう",117
"8"," 怒る小市民さん",109
"8","る小市民さんへ ",107
"8","怒る小市民さんへ",107

このほか、特定の人へのコメントと思われるものとしては以下がありました。これはMultiSyncさんへのものでしょう。ハンドルネームが短い人の名前は他の語に紛れてしまうので、8グラムだけで取り上げるのは不公平かもしれません。
"8","iSync さん",42

6グラムの上位は以下の通りです。やはり、文尾の形は共通になりやすいという事でしょうか。
"6","と思います。",467
"6","とう御座いま",258
"6","ないでしょう",257

4グラムの上位は以下の通りです。「さんへ 」という相手への呼びかけを除けば文尾の形ばかりです。
"4","さんへ ",1906
"4","います。",1331
"4","でしょう",950
"4","しょう。",755
"4","ました。",720
"4","ます。 ",638
"4","ています",581
"4","ません。",568
"4","思います",566

漢字2文字の2グラムの上位は以下の通りです。中国・朝鮮・社会・共産といった熟語が上位に登場しており、瀬戸氏の主張と符合する感じです。
"2","日本",1018
"2","問題",372
"2","中国",301
"2","御座",296
"2","主義",276
"2","朝鮮",258
"2","国家",256
"2","社会",237
"2","今後",218
"2","共産",205
"2","韓国",204
"2","新聞",187
"2","本人",187
"2","極右",186
"2","米国",176
"2","市民",171
"2","左翼",168
"2","政治",161

三番目は2007年分(コメント数:375)です。
8グラム上位は以下の通りです。
"8","ありがとう御座い",39
"8","りがとう御座いま",39
"8","ありがとうござい",38

4グラムの上位は以下の通りです。やはり「さんへ 」以外は文尾の形です。
"4","います。",289
"4","さんへ ",262
"4","ました。",228
"4","ます。 ",172
"4","でしょう",166

漢字2文字の2グラムの上位は以下の通りです。「新風」が2位に「支持」が7位に来ており、選挙があった事を反映しているようです。
"2","日本",113
"2","新風",69
"2","問題",65
"2","御座",46
"2","投稿",46
"2","各位",45
"2","支持",42
"2","朝鮮",42
"2","極右",42
"2","主義",40
"2","今後",40
"2","批判",37
"2","政治",37
"2","本人",36
"2","活動",36
"2","出来",34
"2","国家",34
"2","意見",34
"2","政党",32
"2","現在",32

最後に2008年分(コメント数:391)です。
8グラムの上位は以下の通りです。なんとshinok30さんが8位に登場しています。ハンドルネームの短い人が埋もれている可能性はあるのですが、それでも瀬戸氏がshinok30さんに返答を返す頻度は高かったと言えるでしょう。
"8","ありがとう御座い",40
"8","りがとう御座いま",40
"8","ではありません。",32
"8","がとう御座います",26
"8","とう御座います。",26
"8","ありがとうござい",25
"8","りがとうございま",25
"8","shinok30",23

漢字2文字の2グラムの上位は以下の通りです。いきなり「創価」がトップに立った一方、新風・朝鮮・極右といった熟語は軒並み順位を下げています。
"2","創価",79
"2","学会",73
"2","価学",72
"2","日本",70
"2","問題",63
"2","投稿",55
"2","我々",46
"2","各位",45
"2","削除",44
"2","御座",43
"2","関係",43
"2","今後",42
"2","紹介",40
"2","記事",40
"2","出来",37
"2","今回",36
"2","裁判",35
"2","訂正",33
"2","新風",32

以上、ざっと頻度集計の上位を見てみました。直感的に分かりやすいのは固有名詞か漢字熟語ですね。ちなみに、予想はしていたのですが、創価のキーワードが圧倒的に多くなるのは2008年です。
com2gram1.1-2008-sort.txt(1847): "2","創価",79
com2gram1.1-2007-sort.txt(2044): "2","創価",25
com2gram1.1-2006-sort.txt(10307): "2","創価",35

他にも色々な分析ができると思いますし、他者との比較も大事なのですが今日はここまで。楽しかった正月休みも終わるので、記事投稿頻度はぐっと下がると思います。

最後に使用したプログラムをまとめておきます。

以下のようなバッチファイルで一括処理しました。

rem 2008
del com2gram1.1-result.txt com2gram1.1-ana.txt com2gram1.1-select.txt
com2gram1.1.pl cdb2008.txt -skip1
shunanalyze -s analyze.cfg -a anacond.txt < com2gram1.1-result.txt > com2gram1.1-ana.txt
shunselect -s select.cfg -q selectcond.txt < com2gram1.1-ana.txt > com2gram1.1-select.txt
shunsort -a sortcond.txt < com2gram1.1-select.txt > com2gram1.1-2008-sort.txt

rem 2007
del com2gram1.1-result.txt com2gram1.1-ana.txt com2gram1.1-select.txt
com2gram1.1.pl cdb2007.txt -skip1
shunanalyze -s analyze.cfg -a anacond.txt < com2gram1.1-result.txt > com2gram1.1-ana.txt
shunselect -s select.cfg -q selectcond.txt < com2gram1.1-ana.txt > com2gram1.1-select.txt
shunsort -a sortcond.txt < com2gram1.1-select.txt > com2gram1.1-2007-sort.txt

rem 2006
del com2gram1.1-result.txt com2gram1.1-ana.txt com2gram1.1-select.txt
com2gram1.1.pl cdb2006.txt -skip1
shunanalyze -s analyze.cfg -a anacond.txt < com2gram1.1-result.txt > com2gram1.1-ana.txt
shunselect -s select.cfg -q selectcond.txt < com2gram1.1-ana.txt > com2gram1.1-select.txt
shunsort -a sortcond.txt < com2gram1.1-select.txt > com2gram1.1-2006-sort.txt

rem 2005
del com2gram1.1-result.txt com2gram1.1-ana.txt com2gram1.1-select.txt
com2gram1.1.pl cdb2005.txt -skip1
shunanalyze -s analyze.cfg -a anacond.txt < com2gram1.1-result.txt > com2gram1.1-ana.txt
shunselect -s select.cfg -q selectcond.txt < com2gram1.1-ana.txt > com2gram1.1-select.txt
shunsort -a sortcond.txt < com2gram1.1-select.txt > com2gram1.1-2005-sort.txt

com2gram.plには、若干手を加えてcom2gram1.1.plとしました。主な変更点は-skip1オプションの導入で、これを指定すると、(1)最初の行を読み飛ばす、(2)行の最初と最後の引用符を読み飛ばす、という処理をします。

# com2gram1.1.pl [-skip1] file...
# fileのテキストを1~8グラム分割して以下のファイルに出力する
# $resultfilename ("D:\com2gram\com2gram1.1-result.txt")
# 入出力するファイルはUTF8の想定
#
# 引数にテキストファイルを複数指定可能
# -skip1 はオプションとして以下の意味を持つ
# (shunselectの出力を食うためのオプション)
# ・ 最初の1行をスキップ(カラム名のある行と見て)
# ・ 行の最初と最後にあるダブルクオートを削除

use strict;
use utf8;
use Encode;

my @filelist;
my $skip1 = 0; # skip1オプションフラグ
# 結果出力ファイルをフルパスで指定(UTF8の想定)
my $resultfilename = "D:\\com2gram\\com2gram1.1-result.txt";

# 引数を@filelistに読み込む。skip1オプションのみ特殊処理
foreach my $arg (@ARGV) {
  if( $arg eq "-skip1" ) {  $skip1 = 1; }
  else { push @filelist, $arg ; }
}

open(OUT,">:utf8",$resultfilename);
print OUT "num\tstring\n";

foreach my $file (@filelist) {
  open(IN, "<:utf8","$file") || die("cannot open $file\n");
  my @comlist = <IN>;
  close(IN);
  if (@comlist == 0) { next; }  # ファイルが空ならば次へ
  chomp(@comlist);
  if( $skip1 ) {        # -skip1 オプション指定の場合
    shift( @comlist ); # 最初の行を削除
    for(my $i =0; $i <= $#comlist; $i++  ) { # 各行の先頭と最後のダブルクオートを削除
      $comlist[$i] =~ s/^"//;
      $comlist[$i] =~ s/"$//;
    }
  }

  foreach my $com ( @comlist ) {
    # $j はグラム数を表す
    for( my $j = 1; $j <= 8; $j++ ) {
      # 文字列の先頭から1文字ずつずらして区切って行く
      for( my $i = 0; $i < ( length($com) - ($j-1) ); $i++ ) {
        print OUT $j, "\t", substr($com,$i,$j), "\n";
      }
    }
  }
  close OUT;
}

| | コメント (0) | トラックバック (0)

コメントデータベースから特定著者の発言抽出

今回は、前回作ったコメントデータベース(タブ区切りテキスト)から、特定のコメント著者の発言部分だけを抽出し、年別にファイルに分けてみます。

Data Effectorで提供されているshunselectコマンドに条件毎にファイルに振り分ける機能があったのでこれを使ってみます。中核となるコマンド行は以下です。
shunselect -s select.cfg -q selectcond.txt -o selectout.txt < commentdb.txt

各設定ファイルは以下のようにしました。

■selectcond.txt

1 { $body } $blogdate = "^2005" AND $comauthor = "弘幸$"
2 { $body } $blogdate = "^2006" AND $comauthor = "弘幸$"
3 { $body } $blogdate = "^2007" AND $comauthor = "弘幸$"
4 { $body } $blogdate = "^2008" AND $comauthor = "弘幸$"
5 (%1) OR (%2) OR (%3) OR (%4)

■selectout.txt

1> D:\scomgram\cdb2005.txt
2> D:\scomgram\cdb2006.txt
3> D:\scomgram\cdb2007.txt
4> D:\scomgram\cdb2008.txt
5> D:\scomgram\cdbOther.txt

■select.cfg

CharacterCode  UTF-8
InFileType     CSV
FieldSeparator "\t"
LogFile "D:\scomgram\Select.log"
ErrFile "D:\scomgram\selecterr.csv" 10

「shuncond.txt」で振り分けの条件と、結果として書かれる値を指定しています。
ここでは瀬戸弘幸氏の名前で書かれたコメントを抽出する事にして、コメント著者名の末尾が「弘幸」であるものをブログの日付の年別に振り分ける条件を書いています。「{ $body }」という記述は、出力されるファイルに書かれる内容が、コメントDBの「body」というカラムだけという指定です。つまり、コメント内容だけが出力されます。

この条件に応じた出力先のファイル名を「selectout.txt」に指定しています。5番目の「cdbOhter.txt」は後のチェック用に1~4番目の条件に該当するものの全カラムを出力しています。

Data Effectorの「体験版」には、記述できる振り分け条件数5以下という制約があるらしいのですが、上記を試すには丁度良い上限でした。

2008年12月までのコメントを処理して、最初のコメントDBは68.9MBありましたが、抽出後のファイルの大きさは以下のようになりました。
2005年分:20KB
2006年分:792KB
2007年分:190KB
2008年分:175KB
色々論争が多かった2008年分が多いと予想したのですが、これは間違ってました。実は2006年の方が記述量は遙かに多かったんですね。

なお、Data Effectorのマニュアルを読んだのですが、半角の引用符(")を一般の文字として扱うオプションを見つけられず、やむなく振り分け処理の前に半角引用符(")を全角ダブルプライム(″)に置き換えました。したがって、半角引用符と全角ダブルプライムについては今後の集計が正しく出ません。
(この辺の特殊文字の使い方も個人差が出そうです。私は今回初めて全角ダブル引用符(“”)と全角ダブルプライム(″)の差を意識しました。)

上記の文字変換のために以下のような簡単なPerlプログラムを書きました。

# convertquote.pl file1 file2
# file1の引用符(")(ダブルクオート)を全角のダブルプライム(″)に置き換えてfile2に書く
# file2を上書きするので要注意
use utf8;
my $file1 = shift;
my $file2 = shift;

open(IN, "<:utf8", $file1) || die("cannot read open $file1\n");
open(OUT,">:utf8", $file2) || die("cannot write open $file2\n");

while (my $line = <IN>) {
  $line =~ s/"/″/g;
  print OUT $line;
}
close(IN);
close(OUT);

最終的には以下のようなバッチファイルでコメントDB(commentdb.txt)から抽出を行いました。

rem コメントDBを年別にファイルに分割する
rem 事前に引用符(")を全角のダブルプライムに変換する
rem 分割先ファイル名はselectout.txtに、分割条件はselectcond.txtに指定

convertquote.pl commentdb.txt commentdb-noq.txt
shunselect -s select.cfg -q selectcond.txt -o selectout.txt < commentdb-noq.txt

この振り分けの結果、例えばcdb2005.txt(2005年分の瀬戸氏のコメント集)の冒頭部分は以下のようになりました。これで特定著者のNグラム頻度分析の準備がだいたいできた事になります。

"body"
" 投稿ありがとう。宋教仁については余り詳しくありませんが、石原莞爾と北一輝には興味があり、若かりし頃は北一輝の故郷であった佐渡に行きました。 しかし、佐渡の住民で北一輝のことを知る人とは会うことは出来ませんでした。 対して、石原莞爾の故郷を訪ねた時のことです。殆どの人が石原莞爾を「あの偉い先生」と呼んで尊敬していました。 先生の墓を訪ねた時のことは今でも忘れません、山の上に小高く盛られたその墓は、威厳に満ちていました。 夏の暑い日でした。蝉の鳴き声がうるさいにの、何故かシーンと静まり返っていたのを記憶しています。記帳のノートがあり、覗いてみると遠くは米国、ブラジルからも墓参りに来ていた人がおりました。"
" ある意味、日本は情ない。 戦略的思考がゼロです。"

文字分析を始めてから気がつきましたが、こういった事前のデータ振り分けは処理時間を減らすために重要です。著者と日時の情報を持っていれば、論理的には全データをひとまとめにして処理する事で著者別・日時別の集計も出せるのですが、現実には処理時間がかかり過ぎてしまい人間がついていけません。できるだけデータを小分けにして処理する算段をするのが分析の効率化には欠かせないと思いました。

それにしても、ブログが花盛りの昨今、ブログのデータを元にした研究も盛んに行われていると思うのですが、皆さん、どうやってデータ処理されているのでしょう? 定番があって良さそうですが、実はそうでもないのかなぁという気がしてます。

| | コメント (0) | トラックバック (0)

ブログのコメントのデータベース化

今回は、ブログのコメントをデータベース化する方法について書いてみます。
データベース化と言ってもデータベースシステムにデータを入れるのではなく、幾つかのキーを使った抽出や集計が行いやすいようにタブ区切りテキスト化するだけです。

題材としては、おなじみの「せと弘幸Blog『日本よ何処へ』」を使わせていただきます。

おそらく、コメントを記述するHTMLの構造はLivedoorのブログに共通していると思うので、Livedoorブログであれば他のブログにも応用可能だと思います。

タブ区切りテキストの形としては以下を想定します。(実際のコメントから内容例を引用しています)

filename	blogdate	comauthor	comdate	comtime	post	body
29704240.html 2005年08月05日 瀬戸弘幸 2005-08-05 20:22 Posted by 瀬戸弘幸 at 2005年08月05日 20:22 ある意味、日本は情ない。 戦略的思考がゼロです。
50282975.html 2005年11月28日 瀬戸弘幸 2005-12-01 17:01 Posted by 瀬戸弘幸 at 2005年12月01日 17:01 たしかにおっしゃられる点は理解します。ハンチントンにおかされているか、そうでないかは別にしても、不気味な世界情勢になっていることは確かではないでしょうか。

これらのカラムは以下の意味を持ちます。

filename: そのコメントが存在するブログのファイル名
blogdate: そのブログの記事が書かれた日付
comauthor: コメント著者(後ろのpostから抽出)
comdate: コメント日付(後ろのpostから抽出)
comtime: コメント時刻(後ろのpostから抽出)
post: コメント投稿情報(HTMLの<div class="comments-post">タグの内容)
body: コメント本文(HTMLの<div class="comments-body">タグの内容)

こういう形にしておくと、コメント著者名やコメント本文を区別した検索が簡単になります。
例えば、コメント著者名として「瀬戸弘幸」氏が現れるコメントを検索したいのであれば、
^.*\t.*\t瀬戸弘幸\t
という正規表現を使えばできます。ここまで正確にしなくても「\t瀬戸弘幸\t」でも十分でしょう。(ちなみに、瀬戸氏は「せと弘幸」や瀬の異字体を使った名前でもコメントされているので、もっと単純な「弘幸\t」がかなり正確で網羅的な検索条件になるかと思います)

また、例えば、「新風連ヲチスレテンプレ置き場」にある以下の指摘に出てくるコメントを検索するには「弘幸\t.*\t.*\t.*\t.*弘幸氏.*$」とすれば良いです。コメント著者名が「弘幸」で終わっており、かつ、コメント本文中に「弘幸氏」という文字が入っているコメントを検索しています。

(2)2008年3月、再び自演失敗。
ttp://s04.megalodon.jp/2008-0325-2253-05/blog.livedoor.jp/the_radical_right/archives/51862209.html
>ただし大阪の大衆は割合ざっくばらんです。まずは行動する集団を支持するのです。
>維新政党新風副代表瀬戸弘幸氏は、確かに「大阪というギルド」に風穴をあけました。
>
>Posted by せと弘幸 at 2008年03月25日 22:21

このデータベース化をするPerlプログラムは以下です。もちろん、何の動作保証もありませんので、試したい方は自己責任でお願いします。

use strict;
use utf8;
use HTML::TreeBuilder;
use Encode;

# 出力ファイル名(コメントDB)指定
my $cdbfile = "D:\\temp2\\commentdb.txt";

# コマンドの第一引数にディレクトリのパスが与えられていると仮定
my $dirname = shift;
my @filelist;
# 指定されたディレクトリをOpenし、99999999.htmlのファイル名のみを@filelistに入れる
# @filelistの中にあるファイルだけが処理対象
opendir(DIR, $dirname) || die("error: cannot open $dirname\n");
while (my $file = readdir(DIR)) { 
  if( $file =~ /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\.html$/ ) {
    push (@filelist, $file); 
    }
  }
closedir(DIR);
if( @filelist == 0 ) { die("error: filelist empty\n"); }

# ディレクトリパスの最後が\でなければ補っておく
if( $dirname !~ /\\$/ ) { $dirname = $dirname . "\\" ; }

open(CDBOUT, ">:utf8", $cdbfile); # UTF8指定を忘れずに
print CDBOUT "filename\tblogdate\tcomauthor\tcomdate\tcomtime\tpost\tbody\n";  # 見出し行

foreach my $file ( @filelist ) {
  print "$file\n";  # 進行状況が見えるように、ファイル名をコンソールに出力
  my $tree = HTML::TreeBuilder->new;
  my $filepath = $dirname . $file ;
  # Livedoor BlogはEUCなのでEUC指定しているつもりなのだが正しくないかも。
  #open(HTML, "<:euc_jp","$filename") || die("cannot open $filename\n");
  open(HTML,"<:encoding(euc-jp)","$filepath") || die("cannot open $filepath\n");

  my @line = ;
  close(HTML);
  foreach my $line1 (@line) {
    $tree->parse($line1);
  }
  $tree->eof();

  my $title = ($tree->find("title"))->as_text;    # titleタグの中身を抽出
  my $date = ($tree->find("h2"))->as_text;     # 最初のH2タグの中身は日付と思う

  # コメント本体とポスト日付・主名の抽出
  my @cbody = $tree->look_down("class","comments-body");
  my @cpost = $tree->look_down("class","comments-post");
  
  if( @cbody != @cpost ) {  # 両者の個数が違う場合は対応が崩れていると判断しスキップ
    print "skip!! number of body and post is not equal: $file\n";
    next;
  }
  if (@cbody == 0) { next; }  # コメント数が0なら次へ
  
  my $i;
  for( $i=0; $i < $#cbody ; $i++ ) {
    print CDBOUT "$file\t";    # 1カラム目:ファイル名
    print CDBOUT "$date\t";  # 2カラム目:日付(ブログ記事自体の)
    my $post = $cpost[$i]->as_text; # Post情報から改行とタブを削除
    $post =~ s/\n//g;
    $post =~ s/\t//g;
    my $body = $cbody[$i]->as_text; # Body情報から改行とタブを削除
    $body =~ s/\n//g;
    $body =~ s/\t//g;
    if( $post =~ "^Posted by *(.*) at ([0-9][0-9][0-9][0-9]).+([0-9][0-9]).+([0-9][0-9]).+([0-9][0-9]:[0-9][0-9])\$" ) {
      print CDBOUT "$1\t", "$2-$3-$4\t", "$5\t", "$post\t", "$body\n";
      # $1: 投稿者名、$2-$3-$4: yyyy-mm-dd、$5: hh:mm となっている筈
    } 
    else { die "posted by pattern mis match: $post\n"; }
  }
  $tree->delete; # Deleteは必須。こうしないとメモリが開放されない。
}
close CDBOUT;
print "finished\n";

このプログラムはコマンドの第一引数にgetHTMLで取得したarchivesディレクトリのパスが指定されると想定しています。例えば、このPerlプログラムのファイルがblog2cdb.plだとすると、以下のようなコマンドラインで起動します。
blog2cdb.pl "D:\temp2\getHTML\blog.livedoor.jp\the_radical_right\archives"
ちなみに、私のロートルPCでは2008年10月22日分までの記事で実行に1時間以上かかりました。
(getHTMLの話は、「テキスト処理の道具達(1):Webページの収集ツール」に載せました)

生成するファイルは以下のようにPerlの中に直に書いてますので、変更したい時はPerlプログラムを修正してください。
my $cdbfile = "D:\\temp2\\commentdb.txt";

コメントの認識は、HTML中に以下のような構造で記述されている事を利用しています。つまり、コメント本文は<div class="comments-body">というタグの中に現れ、著者情報は<div class="comments-post">というタグの中に現れるという構文です。

        <div class="comments-body">
たしかにおっしゃられる点は理解します。ハンチントンにおかされているか、そうでないかは別にしても、不気味な世界情勢になっていることは確かではないでしょうか。</div>
        <div class="comments-post">Posted by 瀬戸弘幸
at 2005年12月01日 17:01</div>

但し、この構造には例外があります。本文中でコメントを引用する際に、このタグが一緒にコピーされている例があります。この場合、現在のプログラムの作りでは、本文の中でのコメント引用なのか、コメント本体なのかを区別できません。また、本文中のコメント引用は、記事を書く人が勝手にできるのか、<div class="comments-body">と<div class="comments-post">が対をなさない構造も書けてしまうようです。こういう勝手な構造を作られると正常に認識できなくなるので、せめてもの対処として、両者の数が同じであるかをチェックしています。数が異なるHTMLがあった場合には、HTMLファイルの手修正で対応するしかありません。

| | コメント (0) | トラックバック (0)

Nグラム文字分割による単語頻度分析

あけましておめでとうございます。
年末は忙しいやら体調を崩すやらで何もできない状態でしたが、ようやく休みに入って少しまとまった時間ができたので、文字解析の続きをやってみました。

今回は、文の中に現れる「単語」の頻度を調べてみます。
文字分析の世界では、文章から切り出した1文字の文字列切片を1グラム、2文字の文字列切片を2グラム・・という風に呼ぶそうです。任意の自然数Nに対して、その長さの文字列切片が考えられるので、切片を切り出す方法そのものをNグラム方式などと称するようです。

このNグラム方式で「単語」らしきものを切り出してみて頻度を集計してみました。
対象とする文としては、ネットウォッチ大賞2008の「瀬戸ゼリ幸」さんへの投票の際の「投票理由」を選んでみました。これは、おそらく「うんこ」とか「ウンコ」の頻度が高く出てくるだろうという手堅い予測(笑)があったからです。まぁザッと見ただけで分かるのですが。なお、投票の際には投票者名も自由に記入できるのですが、今回は対象としていません。

http://www4.atpages.jp/watch2008/vote/vote.cgi?mode=comm&no=3
ネットウォッチ大賞2008 瀬戸ゼリ幸 の投票理由

処理の手順と手法は以下の通りです。
(1) 投票理由のテキストファイルを作る(一行に一理由とする)
  秀丸エディタで手作業
(2) 上記を切り刻んで1グラム~8グラムに分解したテキストファイルを作る
  Perlのプログラムで処理
(3) 上記を集計
  ShunAnalyzeコマンド(Data Effector体験版)利用
(4) 上記から頻度10以上の切片のみを抽出
  ShunSelectコマンド(Data Effector体験版)利用
(5) 上記を頻度順にソート
  ShunSortコマンド(Data Effector体験版)利用

この方法では、形態素解析のように単語の区切りや品詞を意識しないので、結果として得られるリストには単語ではない文字列も含まれます。例えば、「価学会のウンコ攻」(8グラム)とか「ャーナリ」(4グラム)などです。
したがって、どれを単語とみなすかは最終的に人間が目で見て判断する必要があります。

という訳で、結果のリストを見て意味のありそうな文字列を拾ってみました。各カラムは、それぞれグラム数,文字列,頻度の意味です。
"3","うんこ",86
"3","ウンコ",76
"3","だから",23
"2","ゼリ",30
"2","創価",20
"2","瀬戸",19
"1","!",92
"1","・",39
"1","w",37
"1","人",25
"1","糞",22

やはり今回はウンコ用語が圧倒的な存在感を示しています。これがなければ、創価学会関係とゼリー関係が上位に来たのかもしれません。残念ながら分かったのはそれだけです(笑)。

今回使った方法を以下に説明します。

(1) 投票理由のテキストファイルを作る(一行に一理由とする)
投票理由の一行は「・最強のブーメラン使い (2008/11/03(Mon) 00:54/nanomania)」のような形式になっているので、先頭の「・」と末尾の「 (2008/」以降を秀丸エディタで削除しました。この結果をcom.txtというテキストファイルに入れます。

■com.txt(354行)

ニコニコにうpされてたナノゼリーの動画が最高に面白かった
そろそろこの人がとってると面白そうなので
ゼリーだから
・・・

(2)から(5)までは以下のバッチファイルで一括実行します。この位のデータ量であればExcelでの処理も可能ですが、時間がかかるのと手操作の繰り返しが苦しいので、できるだけバッチ化するのが吉です。
私も文字分析をやり初めて分かったのですが、多量のデータを簡単に集められるので計算量も簡単に増大して手に負えなくなります。Excelに頼り過ぎない方が結果的には作業の効率が上がると思います。

■バッチファイル

rem テキストファイルから1~Nグラム文字列の頻度を求めるバッチ

rem 1~Nグラムの文字列を生成
rem 入力:com.txt
rem 出力:D:\temp\com2gram-result.txt
com2gram.pl com.txt

shunanalyze -s analyze.cfg -a anacond.txt < com2gram-result.txt > com2gram-ana.txt

shunselect -s select.cfg -q selectcond.txt < com2gram-ana.txt > com2gram-select.txt

shunsort -a sortcond.txt < com2gram-select.txt > com2gram-sort.txt

(2)で使ったPerlプログラムは以下です。処理の際の文字コードはUTF8に統一しておくのが吉です。Shift-JISやEUCでは表現できる文字の範囲が狭いので、もはや文字処理には使えないと思います。
PerlでのUTF8の使い方が分からずに苦労しましたが、以下のプログラムではOpenの際に明にUTF8である事を宣言しています。標準入出力でのUTF8の扱いが良く分からないので、ここでは入力も出力もファイルとしています。
また、このプログラムの中で1~8グラムの切片を切り出す事を決めてます。ここを変えれば、4グラムだけ、とか、3~5グラムを対象とするといった変更が可能(な筈)です。

■com2gram.pl

# com2gram.pl
# 引数にテキストファイル名(1個)を指定して実行
# 結果は $resultfilename ("D:\temp\com2gram-result.txt") に出力される

use strict;
use utf8;
use Encode;

# 結果出力ファイルをフルパスで指定(UTF8の想定)
my $resultfilename = "D:\\temp\\com2gram-result.txt";

# 第一パラメタは引数となるテキストファイル名(UTF8の想定)
# 内容を配列@comlistに読み込む
my $file = shift;
open(IN, "<:utf8","$file") || die("cannot open $file\n");
my @comlist = ;
close(IN);
chomp(@comlist);

# 出力ファイルは固定名、utf8指定
open(OUT,">:utf8",$resultfilename); 

print OUT "num\tstring\n";
foreach my $com ( @comlist ) {
  # $j はグラム数を表す
  for( my $j = 1; $j <= 8; $j++ ) {
    # 文字列の先頭から1文字ずつずらして区切って行く
    for( my $i = 0; $i < ( length($com) - ($j-1) ); $i++ ) {
      print OUT $j, "\t", substr($com,$i,$j), "\n";
    }
  }
}
close OUT;

このプログラムを通すと、例えば、最初の一行が以下のように1~8グラムに分割されます。こうやって処理過程でデータ量が何層倍にもなっていくのが醍醐味でしょうか(笑)。

■com2gram-result.txtの先頭(全体は29562行、約462KB)

num	string
1 ニ
1 コ
1 ニ
1 コ
1 に
1 う
1 p
1 さ
1 れ
1 て
1 た
1 ナ
1 ノ
1 ゼ
1 リ
1 ー
1 の
1 動
1 画
1 が
1 最
1 高
1 に
1 面
1 白
1 か
1 っ
1 た
2 ニコ
2 コニ
2 ニコ
2 コに
2 にう
2 うp
2 pさ
2 され
2 れて
2 てた
2 たナ
2 ナノ
2 ノゼ
2 ゼリ
2 リー
2 ーの
2 の動
2 動画
2 画が
2 が最
2 最高
2 高に
2 に面
2 面白
2 白か
2 かっ
2 った
3 ニコニ
3 コニコ
3 ニコに
3 コにう
3 にうp
3 うpさ
3 pされ
3 されて
3 れてた
3 てたナ
3 たナノ
3 ナノゼ
3 ノゼリ
3 ゼリー
3 リーの
3 ーの動
3 の動画
3 動画が
3 画が最
3 が最高
3 最高に
3 高に面
3 に面白
3 面白か
3 白かっ
3 かった
4 ニコニコ
4 コニコに
4 ニコにう
4 コにうp
4 にうpさ
4 うpされ
4 pされて
4 されてた
4 れてたナ
4 てたナノ
4 たナノゼ
4 ナノゼリ
4 ノゼリー
4 ゼリーの
4 リーの動
4 ーの動画
4 の動画が
4 動画が最
4 画が最高
4 が最高に
4 最高に面
4 高に面白
4 に面白か
4 面白かっ
4 白かった
5 ニコニコに
5 コニコにう
5 ニコにうp
5 コにうpさ
5 にうpされ
5 うpされて
5 pされてた
5 されてたナ
5 れてたナノ
5 てたナノゼ
5 たナノゼリ
5 ナノゼリー
5 ノゼリーの
5 ゼリーの動
5 リーの動画
5 ーの動画が
5 の動画が最
5 動画が最高
5 画が最高に
5 が最高に面
5 最高に面白
5 高に面白か
5 に面白かっ
5 面白かった
6 ニコニコにう
6 コニコにうp
6 ニコにうpさ
6 コにうpされ
6 にうpされて
6 うpされてた
6 pされてたナ
6 されてたナノ
6 れてたナノゼ
6 てたナノゼリ
6 たナノゼリー
6 ナノゼリーの
6 ノゼリーの動
6 ゼリーの動画
6 リーの動画が
6 ーの動画が最
6 の動画が最高
6 動画が最高に
6 画が最高に面
6 が最高に面白
6 最高に面白か
6 高に面白かっ
6 に面白かった
7 ニコニコにうp
7 コニコにうpさ
7 ニコにうpされ
7 コにうpされて
7 にうpされてた
7 うpされてたナ
7 pされてたナノ
7 されてたナノゼ
7 れてたナノゼリ
7 てたナノゼリー
7 たナノゼリーの
7 ナノゼリーの動
7 ノゼリーの動画
7 ゼリーの動画が
7 リーの動画が最
7 ーの動画が最高
7 の動画が最高に
7 動画が最高に面
7 画が最高に面白
7 が最高に面白か
7 最高に面白かっ
7 高に面白かった
8 ニコニコにうpさ
8 コニコにうpされ
8 ニコにうpされて
8 コにうpされてた
8 にうpされてたナ
8 うpされてたナノ
8 pされてたナノゼ
8 されてたナノゼリ
8 れてたナノゼリー
8 てたナノゼリーの
8 たナノゼリーの動
8 ナノゼリーの動画
8 ノゼリーの動画が
8 ゼリーの動画が最
8 リーの動画が最高
8 ーの動画が最高に
8 の動画が最高に面
8 動画が最高に面白
8 画が最高に面白か
8 が最高に面白かっ
8 最高に面白かった

次は(3)の集計ですが、これには「Interstage Data Effector Standard Edition 体験版」を使います。いつの間にかV9.0からV9.1になっていました。色々とエンハンスされているようですが、私にとってはタブ区切りテキストを読めるようになってくれたのが一番嬉しいですね。相変わらず正式サポートされてないWindowsXP上で動かしてます。
http://software.fujitsu.com/jp/middleware/softlook/interstage/is_dese.html

Analyze.cfgは以下の通り。LogFileやErrFileはデバッグ用なのでどうでも良いのですが、FieldSeparatorは重要です。このFieldSeparatorの指定でタブ区切りテキストを読めるようになります。

■Analyze.cfg

LogFile "D:\temp\analyze.log"
ErrFile "D:\temp\analyzeerr.csv" 10
FieldSeparator "\t"

Anacond.txtは以下の通り。GConditionで集計の切り口となる項目名を指定します。com2gram-result.txtの先頭には、numとstringを項目名とするための先頭行が加えてあります。RConditionで集計値として文字列の出現回数(count)を指定します。

■Anacond.txt

CharacterCode  UTF-8
InFileType     CSV
OutFileType    CSV
MemorySize     1500
GCondition  $num, substr($string,0,10)
RCondition  count($string) count

これで、以下のようなテキストファイルが出力されます。

■com2gram-ana.txt(20142行、約479KB)

"num","substr(string,0,10)","count"
"1"," ",5
"1","%",2
"1","(",6
"1",")",6
"1","0",7
"1","1",4
・・・

上記のcom2gram-ana.txtには、1回しか出現しないような文字列が大量に含まれています。そのため、(4)で頻度10未満のものを切り捨てます。これでテキストファイルの量は約100分の1くらいに縮小できます。以下の定義ファイルを使ってShunSelectを動かします。

■select.cfg

CharacterCode  UTF-8
InFileType     CSV
LogFile "D:\temp\Select.log"
ErrFile "D:\temp\selecterr.csv" 10

■selectcond.txt

1 $count >= 10

最後は(5)のソートです。以下の定義ファイルで、num(文字列長)とcount(頻度)の降順ソートを指定しています。

■sortcond.txt

CharacterCode  UTF-8
InFileType     CSV
OCondition     val($num) DESC, val($count) DESC

以上の結果が以下のテキストファイルとなります。同じ文章らしきものの8グラム文字列が繰り返し現れているのは、この同じ文章を理由として複数回の投票があったからです。逆に言うと、8グラムという長い切片になると、この程度の対象文章量では10回以上出現というハードルを越えられるものは少ないという事です。当たり前ではありますが面白いです。コピペされた文章をある程度自動的に検出できたと言う事もできるでしょう(汎用的に使えるかは別の問題として)。

■com2gram-sort.txt(256行、約5KB)

"num","substr(string,0,10)","count"
"8","会のウンコ攻撃に",12
"8","価学会のウンコ攻",12
"8","創価学会のウンコ",12
"8","学会のウンコ攻撃",12
"8","攻撃に負けないで",12
"8","に負けないで!!",11
"8","ウンコ攻撃に負け",11
"8","コ攻撃に負けない",11
"8","ンコ攻撃に負けな",11
"8","撃に負けないで!",11
"8","のウンコ攻撃に負",10
"7","のウンコ攻撃に",12
"7","会のウンコ攻撃",12
"7","価学会のウンコ",12
"7","創価学会のウン",12
"7","学会のウンコ攻",12
"7","撃に負けないで",12
"7","攻撃に負けない",12
"7","に負けないで!",11
"7","ウンコ攻撃に負",11
"7","コ攻撃に負けな",11
"7","ンコ攻撃に負け",11
"7","負けないで!!",11
"7","wwwwwww",11
"7","ジャーナリスト",10
"6","に負けないで",13
"6","ウンコ攻撃に",13
"6","wwwwww",13
"6","けないで!!",12
"6","のウンコ攻撃",12
"6","会のウンコ攻",12
"6","価学会のウン",12
"6","創価学会のウ",12
"6","学会のウンコ",12
"6","撃に負けない",12
"6","攻撃に負けな",12
"6","コ攻撃に負け",11
"6","ンコ攻撃に負",11
"6","負けないで!",11
"6","ジャーナリス",10
"6","ャーナリスト",10
"5","wwwww",15
"5","に負けない",13
"5","ウンコ攻撃",13
"5","ンコ攻撃に",13
"5","創価学会の",13
"5","攻撃に負け",13
"5","負けないで",13
"5","けないで!",12
"5","ないで!!",12
"5","のウンコ攻",12
"5","会のウンコ",12
"5","価学会のウ",12
"5","学会のウン",12
"5","撃に負けな",12
"5","コ攻撃に負",11
"5","ジャーナリ",10
"5","ャーナリス",10
"5","ーナリスト",10
"4","wwww",17
"4","のウンコ",16
"4","創価学会",15
"4","けないで",14
"4","に負けな",13
"4","ウンコ攻",13
"4","コ攻撃に",13
"4","ンコ攻撃",13
"4","価学会の",13
"4","撃に負け",13
"4","攻撃に負",13
"4","負けない",13
"4","いで!!",12
"4","ないで!",12
"4","会のウン",12
"4","学会のウ",12
"4","ジャーナ",10
"4","ナリスト",10
"4","ャーナリ",10
"4","ーナリス",10
"3","うんこ",86
"3","ウンコ",76
"3","だから",23
"3","www",19
"3","ないで",17
"3","のウン",16
"3","攻撃に",16
"3","に負け",15
"3","ゼリー",15
"3","価学会",15
"3","創価学",15
"3","けない",14
"3","学会の",14
"3","コ攻撃",13
"3","ンコ攻",13
"3","撃に負",13
"3","負けな",13
"3","いで!",12
"3","で!!",12
"3","会のウ",12
"3","nko",10
"3","です。",10
"3","ジャー",10
"3","ナリス",10
"3","ャーナ",10
"3","リスト",10
"3","ーナリ",10
"3","偽うん",10
"2","うん",96
"2","んこ",86
"2","ウン",78
"2","ンコ",77
"2","から",41
"2","ゼリ",30
"2","ない",27
"2","!!",27
"2","って",25
"2","だか",23
"2","です",23
"2","ww",23
"2","いで",20
"2","創価",20
"2","瀬戸",19
"2","リー",17
"2","・・",17
"2","攻撃",17
"2","して",16
"2","のウ",16
"2","学会",16
"2","撃に",16
"2","負け",16
"2","に負",15
"2","会の",15
"2","価学",15
"2","けな",14
"2","す。",14
"2","この",13
"2","コ攻",13
"2","スト",13
"2","リス",13
"2","で!",12
"2","ko",11
"2","った",11
"2","ャー",11
"2","nk",10
"2","un",10
"2","さい",10
"2","した",10
"2","んだ",10
"2","ジャ",10
"2","ナリ",10
"2","ーナ",10
"2","偽う",10
"1","ん",149
"1","の",138
"1","う",129
"1","い",120
"1","こ",120
"1","ン",102
"1","ー",92
"1","!",92
"1","ウ",87
"1","で",85
"1","に",84
"1","コ",84
"1","な",82
"1","か",81
"1","る",72
"1","て",68
"1","は",66
"1","だ",63
"1","ら",63
"1","を",55
"1","し",53
"1","す",52
"1","リ",51
"1","た",49
"1","っ",48
"1","、",44
"1","が",41
"1","も",40
"1","・",39
"1","と",38
"1","w",37
"1","ト",35
"1","。",34
"1","れ",33
"1","け",31
"1","ゼ",31
"1","ま",30
"1","さ",27
"1","よ",27
"1","ち",26
"1","お",25
"1","人",25
"1","り",24
"1","ス",24
"1","く",23
"1","糞",22
"1","き",20
"1","会",20
"1","価",20
"1","創",20
"1","大",20
"1","ナ",19
"1","戸",19
"1","撃",19
"1","瀬",19
"1","ぎ",18
"1","カ",18
"1","ロ",18
"1","あ",17
"1","イ",17
"1","タ",17
"1","偽",17
"1","学",17
"1","攻",17
"1","負",17
"1","k",16
"1","え",16
"1","そ",15
"1","ジ",15
"1","「",14
"1","」",14
"1","ね",14
"1","ャ",14
"1","国",14
"1","政",14
"1","せ",13
"1","党",13
"1","年",13
"1","思",13
"1","日",13
"1","n",12
"1","o",12
"1","ク",12
"1","ブ",12
"1","一",12
"1","右",12
"1","波",12
"1","票",12
"1","電",12
"1","(",12
"1",")",12
"1","u",11
"1","め",11
"1","グ",11
"1","ッ",11
"1","ノ",11
"1","ラ",11
"1","想",11
"1","笑",11
"1","者",11
"1","風",11
"1","ど",10
"1","わ",10

| | コメント (0) | トラックバック (0)

東村山市民新聞の文字レア度によるコメントの文書レア度評価

前回の記事に企画部長から意見をいただいていながら、何も返事をしなくてすみません。

まずは、今日の題材を片付けてからと思いつつ、始めてみるとPerlのプログラム書きと計算に思わぬ時間がかかってしまいました。

ご意見に対しては、別稿で議論させていただくとして、今回は東村山市民新聞の文字頻度分布(文字レア度)を使って、『日本よ何処へ』ブログのコメントのレア度を計算した結果を報告します。

今回の場合、レア度と言うより、逆に考えて「適合度」と言った方が分かりやすいかもしれません。レア度が低いほど、文字のある種の使い方/選び方が東村山市民新聞と近い(東村山市民新聞に適合度が高い)と考えました。

評価対象は、『日本よ何処へ』の2008年の記事に対して付けられたコメントです。コメント主が同じコメントを一括りにして一つの文書とみなし、東村山市民新聞の文字レア度を使って、文書レア度を計算しました。

2008年に限ってもテキスト量が多くなるのと、文字数が少ないものは評価が難しいと考えたため、コメント主当りの文字数が1万以上のものだけを対象としました(コメント主数は105)。参考までに、コメント主当りの文字数一覧を載せました。

結果は文書レア度の低い順に並べた一覧ですが、予想に反するものとなりました。

ちゃんと検算してないので計算間違い残る可能性はご容赦ください。
レア度30%以下と高い適合度を示したのは「G」「瀬戸シンパは○○(表現自粛)」「大韓王」の3氏です。意外な結果でした。
批判的な論調に立つとレア度が低くなるのかとも思ったのですが、「せと弘幸」氏も8番目にあるので、必ずしもそういう訳ではないようです。

間違いの有無の検証がてら、評価の元となった文字レア度の定義を変えたりして再計算してみるつもりですが、今日はこれで終わります。ここまで来るのに丸2日くらいかかりました。データ量が増えてくるとExcelでは遅くて全然使い物にならないので、計算にも色々工夫が必要になってきます。

ちなみに、今回評価に使った文字レア度一覧はここに示します。東村山市民新聞の文書レア度の結果を見て、レア度の高い10文書をレア度計算の対象から外してあります。

| | コメント (0) | トラックバック (0)

文字レア度と文書レア度

先日の記事「Google SpreadSheetで東村山市民新聞の字数カウントやってみた(追記2あり)」で、その題名の通り、東村山市民新聞で使われている文字を数えてみました。
これは、一群のWebページやらブログのコメントやらの文書を、その利用文字の傾向から分類できないかと考えたからです。インターネットで調べてみると、どうやら私のやりたいのはクラスタ分析と言われている事のようです。クラスタ分析の初心者向けの解説を読むと、まずは文書と文書の間の距離(どれだけ文書が類似/相違しているかの指標)を定義する必要がありそうです。
この準備のために、今回は、文字のレア度と文書のレア度を定義して計算してみる事にしました。

「文字レア度」は、文字毎に以下のように定義しました。

文字レア度= (総文書数-該当文字の出現する文書数)/総文書数

例えば、100個の文書があったとして、全部の文書に出現する文字の文字レア度は、(100-100)/100 = 0 % となります。全く珍しくないという事です。
逆に、どの記事にも出現しない文字の文字レア度は、(100-0)/100 = 100 % となります。30文書に出現する場合には、(100-30)/100 = 70 % です。
その文書群にとって珍しい字であればあるほど文字レア度は高くなります。

文字レア度を使って、「文書レア度」を、文書毎に以下のように定義しました。
文書レア度= (Σ文書中の文字のレア度)/文書中の文字数
(Σは総和を表す)

つまり、文書レア度とは、その文書に現れる文字の平均的なレア度です。一群の文書の中で、全体から見ると「そぐわない文書」ほどレア度が高くなると考えました。

先日の記事のデータを使って、東村山市民新聞のWebページ毎の文書レア度を計算してみた結果を示します。

これを見ると、結構直感にあった結果が得られているように思います。
文書レア度が高い文書は、目次であったり、洋蘭の紹介であったり、法律や判例の引用が多いものであったりします。逆に、文書レア度が低い文書は、いかにもこのサイトに載りそうな文書だと思うのは私だけでしょうか。

| | コメント (2) | トラックバック (0)