★データ解析備忘録★

ゆる〜い技術メモ

RMeCabの顔文字の誤解析を後処理で消す

顔文字を含んだ文の解析

{RMeCab}、日本語の形態素解析に便利なのですが顔文字の分類は苦手です。
例えば、

words
ふう。お腹いっぱい( ´•౪•`)
暇だな(☝ ՞ਊ ՞)☝
試験頑張るぞ\\\\ ٩( ‘ω’ )و ////

というデータフレームを解析して単語の頻度を数えるとします。

words <- c("ふう。お腹いっぱい( ´•౪•`)",
           "暇だな(☝ ՞ਊ ՞)☝",
           "試験頑張るぞ\\\\ ٩( ‘ω’ )و ////")

dat <- data.frame(words)

res1 <- docDF(target = dat, column = 1, type = 1)

結果

> res1
       TERM   POS1           POS2 Row1 Row2 Row3
1         (   名詞       サ変接続    1    0    1
2        (☝   名詞       サ変接続    0    1    0
3         )   名詞       サ変接続    0    0    1
4        )☝   名詞       サ変接続    0    1    0
5    ////   名詞       サ変接続    0    0    1
6       ´•   名詞       サ変接続    1    0    0
7        ω   記号 アルファベット    0    0    1
8         ՞   記号           一般    0    1    0
9        ՞ਊ   記号           一般    0    1    0
10        و   記号           一般    0    0    1
11        ٩   記号           一般    0    0    1
12        ౪   記号           一般    1    0    0
13       ‘   記号         括弧開    0    0    1
14       ’   記号         括弧閉    0    0    1
15      •`)   名詞       サ変接続    1    0    0
16       。   記号           句点    1    0    0
17 いっぱい   名詞           接尾    1    0    0
18     お腹   名詞           一般    1    0    0
19       ぞ   助詞         終助詞    0    0    1
20       だ 助動詞              *    0    1    0
21       な   助詞         終助詞    0    1    0
22     ふう   動詞           自立    1    0    0
23       暇   名詞           一般    0    1    0
24     試験   名詞       サ変接続    0    0    1
25   頑張る   動詞           自立    0    0    1
26       \   記号           一般    0    0    1
27     \\\   名詞       サ変接続    0    0    1

と、顔文字が正しく解析できていません。
顔文字の部分が記号だったり名詞だったりします。
これでは名詞に絞ってもゴミが混じったままです。
前処理的に消そうと思っても色々な顔文字や機種依存文字が混じっていると全てを正しく前処理で消せません。
ですので、後処理的に消すことを考えます。
必要なのはHadley先生でおなじみの{dplyr}と同じくHadley先生の{stringr}です。


顔文字を消すには正規表現を使います。
正規表現については
http://www.mnet.ne.jp/~nakama/
R における正規表現 - RjpWiki
あたりをご覧ください。

今回の場合はstringr::str_detectが使えます。これは、str_detect(string, pattern)でpatternにマッッチする箇所があるかどうかをlogicalな形式で出してくれる関数です。
今回の場合では、名詞に絞った後にこの関数を使ってパンクチュエーション文字( ! " # $ % & ' ( ) * + , - . / など)以外を取り出すことでゴミ掃除ができます。

res2 <- filter(res1, POS1 == "名詞", 
                     str_detect(res1$TERM, '[:punct:]') == 'FALSE'
               )

結果

>res2
      TERM POS1     POS2 Row1 Row2 Row3
1 いっぱい 名詞     接尾    1    0    0
2     お腹 名詞     一般    1    0    0
3       暇 名詞     一般    0    1    0
4     試験 名詞 サ変接続    0    0    1

顔文字の部分を綺麗に消せました。

関数化

解析する量がそこそこ多く、かつ顔文字(や🍣などのUnicode文字)を消す際はこの辺りを関数化して一気にやってしまうと楽です。

trush_delete <- function (x) {
  x <- filter(x, POS1 == "名詞", 
                 str_detect(x$TERM, '[:punct:]') == 'FALSE', 
                 str_detect(x$TERM, '[A-z0-9]') == 'FALSE', #アルファベットと数字
                 str_detect(x$TERM, '[Α-ω]') == 'FALSE', #ギリシャ文字
                 str_detect(x$TERM, '[А-я]') == 'FALSE', #キリル文字
                 str_detect(x$TERM, '[ヲ-ン]') == 'FALSE' #半角カタカナ
              )
}

res3 <- trush_delete(res1)