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

Rを通じて統計学を学ぶ備忘録ブログ

SPSSからRに移行したい私のような人向けのR解説ブログ兼学習用備忘録。

テキストマイニングはじめました〜その8〜

今回の目的は、以下の通りです。

テキストの長さを比較し、Brunner-Munzel Testで差を調べる

今回使用するデータは、石田先生著「テキストマイニング入門」からお借りしています。このデータもとは徳島大学の岸江先生の「日本語の配慮表現」に関する研究の際に回収したアンケートのようです。石田先生は、その中でも、Region、Sex、Q1A1、Q1A2、Q2A1、Q2A2を利用しています。細かい質問内容は以下の通りです。

Q1A1:中学生の少年に記念写真を撮ってもらおうとする時に、どのように頼みますか? Q1A2:その時に、どの程気を遣うのか(5件法) Q2A1:中年男性に記念写真を撮ってもらおうとする時に、どのように頼みますか? Q2A2:その時に、どの程気を遣うのか(5件法)

石田先生は、性別、出身地、配慮する程度を関連させ、日本語の使い方の地域差や性差を調査しています。 大変勉強になるので、興味がある方は書籍を購入してください。今回のブログでは、Q1A1&Q2A1のみを利用し、その自由記述の長さに着目し、中年男性と少年では配慮する程度が異なるのかどうかを調べます。つまり、文章の長い(=形態素の多さ)ほど、頼みごとをする際に配慮している、ということになります。例えば、少年には「写真撮って?」と尋ねる一方で、中年男性に「申し訳ありません。記念写真を撮影したいので、シャッターを押していただけないでしょうか?」と配慮するのかどうか、という仮説を検討していきます。今回使用するフォントは「数式フォント」です。 f:id:teruaki-sugiura:20160521140403p:plain

Brunner-Munzel検定は、ノンパラ検定の1つです。マンホイットニーU検定と異なり、2標本の等分散性を仮定しなくてもよい!という利点があります。テキストマイニングで得られるデータは正規性を仮定する事が難しい場合が多いので、そんな時には役立ちそうです。また、このブログでも紹介されているように、検定精度も良いようです。

計算の仮定を簡単に紹介すると、以下のような感じです。

1. 2標本のデータについて、2標本をあわせ、小さいデータから順位をつける。同順位の場合、該当順位の平均値をつける。 2. 各標本内での順位を各データに割り当て、全データの順位と各標本内での順位、およびデータのサンプルサイズ(n1,n2)から、統計量を求める。 3. 両側検定を行い、統計量が有意水準以下の場合に、帰無仮説「2標本の間に差がない」が棄却される。

理論的な説明は奥村先生のHPで解説がありますので、そちらを参考ください。

f:id:teruaki-sugiura:20160521140234p:plain

では、テキストマイニングを行ってまいります。

library(RMeCab)
dat <- read.csv("dat.csv")
dat <- na.omit(dat)
#自由回答の列にNA(空白)があっても、その行は削除されない。
attach(dat)
boy <- RMeCabDF(dat, "Q1A1")
#boy <- RMeCabDF(dat, 3)と同じ
middle.aged <- RMeCabDF(dat, "Q2A1")
boy1

まずはデータフレームから自由記述の列を抽出します。中身はこのようになっています。12個の形態素に分解された状態になっています。この形態素の数が文章の長さになります。

f:id:teruaki-sugiura:20160521144423p:plain

そして、for文を使って、リスト内の各行の長さを調べていきます。

boy.length <- NULL
for(i in 1: length(boy)){
  if(any(is.na(boyi))) {
    boy.length[i] <- NA
  }else{
    boy.length[i] <- length(boyi)
  }
}

middle.aged.length <- NULL
for(i in  1: length(middle.aged)){
  if(any(is.na(middle.agedi))) {
    middle.aged.length[i] <- NA
  }else{
    middle.aged.length[i] <- length(middle.agedi)
  }
}

うっ…….となるコードですが、そんなに難しくありません。一行づつ見ていきましょう。難しい問題でもとりあえず、分解して小さくしていけばなんとかなります。

boy.length <- NULL
#これは、各列の形態素の長さを測定した際に、その結果を「boy.length」という名前がついている箱に入れたいので、その箱を作り空にした状態です。つまり、for文の結果を詰め込んでいくために、空にして準備しておきます。
for(i in 1: length(boy)){
#これは、「iは1〜boyの行数分」ありますと定義しています。
if(any(is.na(boyi))) {
boy.length[i] <- NA
#ifelse文の「if」の部分です。any()関数は、与えられた論理ベクトルの要素に TRUE が一つでもあれば TRUE を返す。is.na()関数は、欠損値 NAであれば、TRUEを返す。なので、まずis.na()関数で、形態素を調べ、欠損値であれば、any()関数が最終的に欠損値かどうかを判断するという感じ。下の画像を参照。
}else{
boy.length[i] <- length(boy[i])
#上のチェックでFALSE(=欠損値ではない)であれば、形態素の個数を数えて、箱の中に入れる。
 }
}

f:id:teruaki-sugiura:20160521151019p:plain

summary(boy.length)
summary(middle.aged.length)

f:id:teruaki-sugiura:20160521151421p:plain

少年の方では、平均は11.26形態素、中年男性の方は12.45形態素のようです。この結果をもとに、配慮に違いがあるのかどうか、Brunner-Munzel検定で見ていきましょう。

library(lawstat)
brunner.munzel.test(boy.length, middle.aged.length)

f:id:teruaki-sugiura:20160521151727p:plain

Brunner-Munzel検定の結果を見る限り、差がありそうですね。つまり、少年と中年男性では、配慮する程度が、「言葉の長さ」の観点から異なるということがわかりました。

f:id:teruaki-sugiura:20160521172351p:plain 少しばかり天辺のピークが左右で異なっているようです。

以上で今回はおしまい。

 

広告を非表示にする