1. HOME
  2. ブログ
  3. R
  4. だれでも分かるRを使ったテキストマイニング(ECアンケート活用編)

BLOG

ブログ

R

だれでも分かるRを使ったテキストマイニング(ECアンケート活用編)

 

R  テキストマイニング(対応分析)

(オンラインショップ利用状況アンケートを活用してみる)

 

 

テキストマイニング とは

テキストマイニングtext mining)は、文字列を対象としたデータマイニングのことである。通常の文章からなるデータを単語文節で区切り、それらの出現の頻度や共出現の相関、出現傾向、時系列などを解析することで有用な情報を取り出す、テキストデータの分析方法である。

Wikipeida テキストマイニング 

 

 

本日のゴール

本日は、弊社で収集したオンラインショッピング利用状況アンケート の一部を使い、Rを使ったテキストマイニング (対応分析)を実施してみます。ここから性別・年代による利用傾向を捉え、ウェブ改善に活かすことが今回のゴールです。

 

 

今回データ傾向をTableauでもさっと確認してみましょう

* Prep x Tableau x R連携は別セクションでご紹介します。

① 今回データ構造  *抜粋

 

Q1. 欲しい商品がモールおよび、直営公式サイトの両方に置いてありました。その場合、どちらで購入したいですか?

Q2. 一般的にオンラインショッピングを活用して不満・不便・不安に思うことは何ですか?

ID:識別子

gender:性別

site type:Q1を、モール / 公式サイトの二者択一で選択回答

reason:Q1で回答した理由を自由記述で回答

problem:Q2を自由記述で回答

 

② 性別年代別の有効回答数

10代、60代、70代のアンケート回収が少なめです。

テキストマイニング の段階では採否検討した方が良さそうです。

 

 

③ モール / 公式サイトどちらを使いたいですか?

圧倒的にモールを選択する方が多いです。

 

④ (モールまたは公式サイトを使いたい)その理由は?

100件の自由記述アンケートを全部読むのはもちろん重要ですが、自由記述テキストをRで形態素解析し、その頻出ワードでフィルタしながら都度確認できるようにすると良いです。

*形態素解析を本格実施する場合は、除外するワード、表記ゆれを吸収するワードを選定し、クレンジングしながら精度をさらに高めていきます。Tableau Prepの利用が良いです。

 

実際のコメントをみると、ポイント利用のメリット送料(無料)価格優位会員登録が済んでいる(都度登録は手間)使い慣れている幅広い商品を比較・選択できる がモールを使いたい主な理由となります。

*公式サイトでは、圧倒的な信頼感で利用する、というのが理由となります。

公式サイトでは、モールで対応できないことを徹底的に対応していくサイトづくりが必要そうです。

付加価値だけでは足らないと感じます。

下記で、さらに詳細を確認してみると良いでしょう。

 

[公式サイトを使いたい]

信頼性、正規品であることの安心感、アフターフォローが主な理由

 

[モール / ポイントが重要]

貯まっているポイントが、積極的あるいは、消極的な誘引要因になっております。

 

[モール / 無料が重要]

カート時点で送料に愕然として断念することは確かに経験則でも多いです。

また、公式サイトごとに登録するのはとても手間ですね。

 

[モール / 価格が重要]

価格を比較できることで後でがっかりしないという安心感から満足度は高まります。

公式サイトでは付加価値で勝負する必要がありますが、付加価値に幻想を抱きすぎという意見もありました。

 

[モール / 比較・商品点数が重要]

比較検討ができる、多数の商品から選べる、何より、使い慣れており利便性が高いという点も重要です。

 

[モール /登録メリット・利便性が重要]

都度、会員登録が必要な公式サイトのデメリットを補うにはAmazon Payの導入はもはや必須ですね。

購入履歴も確認できます。導入していない直営公式サイトは強くおすすめします。

 

⑤ 不満、不便な点は?

[不満・不安・不便に思うこと全般]

全体として送料無料、時間指定、支払い方法、ポイント抹消、質感のギャップ、返品の手間、会員登録の手間が多そうですね。

 

[送料に関する不満・不便]

送料無料閾値を超えたかどうかの計算の煩わしさ、余計なものを買わないといけないなどが面倒ですよね。送料込みや送料無料で慣れてしまうと他で買えなくなるという意見もあります。

 

[ポイントに関する不満・不便]

ポイント二重取りのための手法など、余計に悩ませているケースがありますね。特に段ボール問題もポイント還元で対応できると単純に嬉しいですね。失効で無理やり使おうとしても欲しい商品がないときも面倒です。

 

 

[価格に関する不満・不便]

以前と比べて、価格トラブルはだいぶ解消されてきているように思います。

 

[サイズに関する不満・不便]

女性の鞄など、細かな採寸が欲しいという意見が複数ありました。実際にノートパソコンを入れた場合のイメージ写真なども欲しいようです。

 

[返品・配送に関する不満・不便]

返品無料でも返品率は以前と大きく変わらないということをよく伺います。公式サイトでも強みになると思います。

 

[支払方法に関する不満・不便]

Amazon Payに対応した公式サイトに活路があると思います。公式サイト分、クレジットカード情報を預ける、あるいは毎回入力させるのは不便すぎます。

 

 

 

Rによるテキストマイニング (対応分析)

アンケートデータの全体概要は以上となります。

それでは、所感どおりかどうか、早速、Rを使ってテキストマイニングしてみます。

 

【今回手順】

今回手順の前に、RのインストールMeCabの導入RStudioの導入  をしておくと良いです。*これらの手順は割愛します。

あわせて、『Rによるテキストマイニング入門』を参照しておくと理解度が高まります。

本作業は、再現性を重視し、おおむね、こちらの書籍の手順を参照しております。

なお、今回のR環境は、MACでVMwareFusionを使って、Windows10にて仮想環境を構築しております。

 

  1. RMeCabの導入
  2. CSVファイルを読み込む
  3. dplyr, magrittrパッケージの導入
  4. 自由記述テキストのデータ整形
  5. 対応分析を実施する

 

手順1 RMeCabの導入

getwd()
#[1] “C:/Users/info/Documents”

install.packages(“RMeCab”, repos = “http://rmecab.jp/R”)

library(RMeCab)

 

手順2 CSVファイルの読み込み

#ファイル配置前提:C:/Users/info/R/research.csv

result <-read.csv(“C:/Users/info/R/research.csv”)

colnames(result)
#[1] “ID” “gender” “site.type” “reason” “problem” “age”

 

手順3   dplyr, magrittrパッケージの導入

#filterと、%>%演算子を使うために、それぞれパッケージを導入。

library(dplyr)

library(magrittr)

 

#特定列でサマリ集計して確認する

result %>% select(gender,site.type,age) %>% summary()

 

#ID列を除去して上書きする(%<>%は処理結果で上書きする演算子)

result %<>% select(-ID)

#欠損値を除去して上書き

result %<>% na.omit()
colnames(result)
[1] “gender” “site.type” “reason” “problem” “age”

 

#性別と年齢によって有効回答数に差があるかみておく

result %>% xtabs(~ gender+age,data=.)

 

手順4   自由記述テキストのデータ整形

#map()を使うために、purrrパッケージを導入する

library(purrr)

 

#年代別にレコード数を再集計し、少ない年代のレコード数を除外することにする

AgeL <- result %>% use_series(age) %>% levels()

AgeL %>% map(~filter(result, age==.x) %>% NROW())
[[1]]
[1] 2

[[2]]
[1] 15

[[3]]
[1] 28

[[4]]
[1] 34

[[5]]
[1] 17

[[6]]
[1] 2

[[7]]
[1] 2

 

#今回レコード数が少ない[1],[6],[7]は除外する

AgeL <- AgeL[-c(1,6,7)]
AgeL
[1] “20代” “30代” “40代” “50代”

 

#年齢、性別、site.typeを同一カテゴリとして、自由記述テキストをまとめてみる

#ここでは、[20,30,40,50] x [male, female] の掛け合わせ8ファイルを作成する

setwd(“C:/Users/info/R/doc”)

getwd()
[1] “C:/Users/info/R/doc”

 

#男性/モール/年代別 でモールを使う理由をファイルに出力する

AgeL %>% map(~ filter(result,
age==.x,
gender == “male”,
site.type==”モール”)
%>%
{tmp<-use_series(data=.,reason)%>%as.character()
writeLines(text=tmp,con=paste0(“MM”,(2:5)[AgeL==.x],”0.txt”))})

 

#女性/モール/年代別 でモールを使う理由をファイルに出力する

AgeL %>% map(~ filter(result,
age==.x,
gender == “female”,
site.type==”モール”)
%>%
{tmp<-use_series(data=.,reason)%>%as.character()
writeLines(text=tmp,con=paste0(“FM”,(2:5)[AgeL==.x],”0.txt”))})

 

(ファイル出力結果)

 

library(RMeCab)

 

#生成された8個のファイルから文字単語行列を作る

#形態素(typeで1を指定)、必要な品詞(名詞、動詞、形容詞)を指定

ALL<-docDF(“C:/Users/info/R/doc”,type=1, pos=c(“名詞”,”動詞”,”形容詞”))

colnames(ALL)
 [1] “TERM” “POS1” “POS2” “FM20.txt” “FM30.txt” “FM40.txt” “FM50.txt” “MM20.txt” “MM30.txt” “MM40.txt” “MM50.txt”

head(ALL,n=3)
TERM POS1 POS2 FM20.txt FM30.txt FM40.txt FM50.txt MM20.txt MM30.txt MM40.txt MM50.txt
1 ! 名詞 サ変接続 0 0 0 0 0 0 1 0
2 ANA 名詞 一般 0 1 0 0 0 0 0 0
3 Amazon 名詞 一般 2 0 0 0 0 0 0 0

 

#さらに一般名詞、固有名詞、自立動詞、形容詞を残すように設定する

ALL2 <- ALL %>% filter(POS2 %in% c(“一般”,”固有”,”自立”))

 

#ストップワードを削除する

ALL2 <- ALL2 %>% filter(! TERM %in% c(“ある”,”いう”,”いる”,”する”,”できる”,”なる”,”思う”,”感じる”,”とき”,”あと”,”!”,”わかる”,”考える”,””))

*今回はあまり表記ゆれを吸収していないので、実戦ではしっかりと考慮してください。

ALL %>% NROW()

ALL2 %>% NROW()

[1] 287
[1] 142

 

#頻度が3回以上の単語に絞る。ついでに、“TERM” “POS1” “POS2″のカラムを計算対象から除外する

ALL2$SUMS <- rowSums(ALL2[,-(1:3)])

ALL3 <- ALL2 %>% filter(SUMS >=3)

ALL3 %>% NROW()
[1] 49

ALL3$TERM

  “ためる” “つく” “ない” “もらえる”
[6] “アマゾン” “キャンペーン” “サイズ” “サイト” “ショップ”
[11] “ネット” “ブランド” “ポイント” “メーカー” “メリット”
[16] “モール” “モールネットショップ” “安い” “価格” “会員”
[21] “楽天” “慣れる” “金額” “個人” “口コミ”
[26] “使う” “使える” “住所” “商品” “情報”
[31] “制度” “選べる” “選択肢” “送料” “他”
[36] “多い” “沢山” “貯まる” “貯める” “店”
[41] “得” “買う” “買える” “付く” “幅広い”
[46] “複数” “無料” “理由” “良い”

 

#この段階でALL3の型を確認しておく

class(ALL3)
[1] “data.frame”

 

#対応分析を実行する前提で行列に変換する

#また、正規表現を使って数値列(MM20.txtなど)だけを抽出してALL4へ格納する

library(stringr)

ALL4 <- ALL3 %>% select(matches(“[FM][M]\\d\\d”))

colnames(ALL4)
[1] “FM20.txt” “FM30.txt” “FM40.txt” “FM50.txt” “MM20.txt” “MM30.txt” “MM40.txt” “MM50.txt”

 

#str_extract関数を使って、指定したパターンにマッチしない部分は取り除く

colnames(ALL4)<-str_extract(colnames(ALL4), “[FM][M]\\d\\d”)

colnames(ALL4)
[1] “FM20” “FM30” “FM40” “FM50” “MM20” “MM30” “MM40” “MM50”

 

#行列の名前設定

rownames(ALL4)
[1] “1” “2” “3” “4” “5” “6” “7” “8” “9” “10” “11” “12” “13” “14” “15” “16” “17” “18” “19” “20” “21” “22” “23” “24” “25” “26” “27” “28” “29” “30” “31” “32” “33” “34” “35” “36”
[37] “37” “38” “39” “40” “41” “42” “43” “44” “45” “46” “47” “48” “49” 

rownames(ALL4)<-ALL3$TERM
rownames(ALL4)
“たまる” “ためる” “つく” “ない” “もらえる”
[6] “アマゾン” “キャンペーン” “サイズ” “サイト” “ショップ”
[11] “ネット” “ブランド” “ポイント” “メーカー” “メリット”
[16] “モール” “モールネットショップ” “安い” “価格” “会員”
[21] “楽天” “慣れる” “金額” “個人” “口コミ”
[26] “使う” “使える” “住所” “商品” “情報”
[31] “制度” “選べる” “選択肢” “送料” “他”
[36] “多い” “沢山” “貯まる” “貯める” “店”
[41] “得” “買う” “買える” “付く” “幅広い”
[46] “複数” “無料” “理由” “良い”

 

head(ALL4,n=3)

FM20 FM30 FM40 FM50 MM20 MM30 MM40 MM50
たまる 0 3 1 1 0 1 1 0
ためる 1 1 0 1 0 0 0 0
つく 0 0 1 1 1 1 0 0

 

#次元(行数および、列数)を確認する(52行、16列)

dim(ALL4)

[1] 49 8

 

手順5   対応分析を実施する

install.packages(c(“FactoMineR”,”factoextra”))

library(FactoMineR)

ALL4ca <- CA(ALL4, graph=FALSE)
library(factoextra)
fviz_ca_biplot(ALL4ca)

 

[モールを使いたい理由]

年齢・性別の分布状況)

・男性と女性でおおむね、左右に別れている

・20,30,40の女性が近接しているものの、50とは離れている

・20,30の男性が近接、40の男性は女性側に寄った、女性同様、50が離れている

 

TERMの分布状況)

・MM20,30 :安さ、得

・MM40 :価格、ポイント、(ポイント)貯まる

・MM50 :選択、幅広い、(ポイント)付く

・FM20 :価格、ポイント、(ポイント)貯まる

・FM30 :ポイント、メリット、(ポイント)たまる

・FM40 :会員登録、ポイント制度、ポイント

・FM50 :慣れる、(いろいろな)店

 

[オンラインショップの不満・不便・不安点]

年齢・性別の分布状況)

・男性と女性でおおむね、近接している

・20,40の女性が近接しているものの、30と50はやや離れている

・おおむね、30, 40, 50の男性が近いものの、20の男性は離れた

 

TERMの分布状況)

・MM20 :日数

・MM30 :業者、商品、ない

・MM40 :質感

・MM50 :送料、かかる

・FM20,40 :無料、安い、実物、送料

・FM30 :異なる、口コミ、画像、手間

・FM50 :(物を)入れる、(物が)入る、悪い

 

 

まとめ

今回は、アンケート(自由記述)に対して、テキストマイニング (対応分析)でアプローチしてみました。

細かいニュアンスは一言一句確認する必要がありますが、俯瞰しながら詳細部分を確認できるようになることはとても重要です。

今回の作業については、文字単語行列の精度をあげられそうですが、年齢・性別とTERM のプロットについてはおおむね、参考にできるレベルと感じました。

実際の作業フローは、Tableau Prepで前処理、TableauからR連携でデータを返してもらってビジュアライズが良さそうです。ただし、インサイトを手っ取り早く欲しい場合は、R単体、あるいはTableau単体でも十分だと感じます。

アンケートなどの自由記述部分は集計がなかなか難しいため、今回のように対応分析によるアプローチは有効です。

 

みなさまも、自社ECサイトのお客様アンケートを定量的に分析できるように試してみてください!

また、モールの自社商品の口コミは、「ウェブスクレイピング」という技術で一斉収集が可能な技術があります。

Rでもパッケージがありますので、そちらでデータ集計をしたら、同様にテキストマイニング すると良いでしょう。

※今回のアンケートでは、モール優位でした。現実問題、公式サイトでもかなり売れているブランド・企業はやはりあります(感覚では10社に1社くらいの1割合でしょうか)。そこには必ず理由があります。その理由は弊社のコンサルテーションで触れておりますので、ぜひ、あわせてご活用ください。

 

 

調査概要

  • 実施期間:2018年06月25日~28日
  • 調査対象:スクリーニングなし。モールまたは直営公式サイトを利用したことのある10代~70代の男女
  • 有効回答数:99 / 100
  • 調査方法:セルフ型ネットリサーチシステムを活用したアンケート調査

今回使用したロウデータを活用したい方は有料にてお譲りいたします(法人様の場合は請求書対応可)。

お問い合わせより、お気軽にお声がけくださいませ。

 

[contact-form-7 id=”4500″ title=”お問い合わせフォーム(最新)”]

 

 

 

 

関連記事