からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

RとTreeTaggerで日本語英語混合文をテキスト分析するための前処理(複数文書)

〇はじめに

 ディレクトリ内の日本語と英語が混じった文書を、MeCabとTreeTggerとで一括で処理するためのコードです。処理の詳細は前回の記事をご覧ください。といいますか、基本時に前回の内容をforでくっつけたものです。最終的に単語文書行列が作成されます(前回は頻度表でした)。
www.anarchive-beta.com


 ありがたいことにこの記事は検索に引っかかるようでそれなりにアクセスがあります。ただ1年以上前に書いたもので、RMeCab::docDF()はフォルダ単位で処理できることを知らなかったり、かなり拙いです(でも当時としてはよく頑張ったと思います!)。書き直すつもりではいます。その一環で、(おそらく)この記事の核となる内容を別の記事にまとめました。せめて↑の記事か、最近書いた↓の記事を参考にしてください。

www.anarchive-beta.com


〇日英混合文の処理

library(RMeCab)
library(dplyr)
library(stringr)
library(koRpus)
library(koRpus.lang.en)
kRp.env <- set.kRp.env(TT.cmd = "C:/TreeTagger/bin/tree-tagger.exe", lang = "en") #TreeTaggerを使うための設定

#ファイル関連
folder_name1 <- "kbtb"   #テキスト保存場所を指定
file_name1   <- list.files(folder_name1)
file_path1   <- paste(folder_name1, file_name1, sep = "/")
folder_name2 <- "tmp"   #加工中データの一時書き出し先
file_path2 <- paste(folder_name2, file_name1, sep = "/")
delete_word1 <- c("[\\-,.!?_……“”*・×、。「」]")   #削除ワード(記号類)を指定
delete_word2 <- c("\\'s|\\'m|\\'re|\\'t|\\'ll")

#第一段階の処理(記号類)
for(i in 1:length(file_path1)) {
  tmp1 <- scan(file_path1[i], what = "char", sep = "\n")
  tmp2 <- gsub("\\(.*?\\)|≪.*?≫", "", tmp1)   #ルビ等の削除
  tmp3 <- tmp2 %>% 
          str_to_lower() %>% 
          str_replace_all(delete_word1, " ") %>% 
          str_replace_all(delete_word2, " ") %>% 
          str_squish()
  write(tmp3, file_path2[i])   #MeCabにかける為に一旦書き出し
}

#処理本番
result1 <- data.frame()
for(i in 1:length(file_path2)) {
  #英文を抜き出す
  mixed_text1 <- RMeCabText(file_path2[i])
  mixed_df    <- as.data.frame(mixed_text1) %>% t()              #リストからデータフレームに変換後、列操作するために転置
  token_lemma <- data.frame(token = unname(mixed_df[, 1]), 
                            lemma = unname(mixed_df[, 8]))       #文中の単語列(token)と原形に直された単語列(lemma)からなるデータフレームを作成
  token       <- token_lemma$token[token_lemma$lemma == "*"] %>% 
                 as.character()                                  #原形(lemma列)が"*"なのを英単語と判断してtoken列から文字列ベクトルを作成
  english_text1 <- paste(token, collapse = " ")                  #単語間をくっつけて文章形式にする
  english_text1[english_text1 == ""] <- "からっぽ"               #オブジェクトがc("")なら何かしら入れて、taggedText()のエラー回避

  #除外英単語の抽出
  english_text2 <- taggedText(treetag(english_text1, treetagger = "manual", format = "obj", lang = "en", 
                                      TT.options = list(path = "c:/TreeTagger", preset = "en"))) #TreeTaggerによる形態素解析

  english_text3 <- english_text2 %>% 
                   filter(!grepl("<unknown>|@card@", lemma)) %>%  #"lemma"列に記号類のある行を削除
                   filter(!grepl("NN|PP|NP|VB|VD|VH|VV|JJ", tag)) #"tag"列に名詞,動詞,形容詞のある行を削除
  del_english   <- english_text3 %>% 
                   distinct(token, .keep_all = TRUE)              #重複を削除
  delete_word3  <- paste(del_english$token, sep = "", collapse = "$|^")
  delete_word3  <- paste(paste("^", delete_word3, "$", sep = "", collapse = ""))

  #混合テキストの処理
  mixed_text2 <- docDF(file_path2[i], type = 1, pos = c("名詞", "動詞", "形容詞"))
  mixed_text3 <- filter(mixed_text2, !grepl(delete_word3, TERM)) #不要な英単語を削除
  mixed_text4 <- mixed_text3 %>% 
                 filter(!grepl("非自立|接尾|数", POS2)) %>%      #不要な単語を削除
                 select(TERM, FREQ = file_name1[i]) %>%          #summarise()が変数を認識しないようなのでいったん列名を"FREQ"にする
                 group_by(TERM) %>%                              #POS列を落とすので重複する単語を統合
                 summarise(FREQ = sum(FREQ))
  names(mixed_text4)[2] <- file_name1[i]                         #列名をテキスト名に戻す
  result1 <- merge(result1, mixed_text4, all = TRUE)             #単語文書行列を作成
}
result1[is.na(result1)] <- 0   #"NA"を0に変換

以上です!最終的に単語文書行列ができあがるようになっているので、目的に応じて最後の方(docDF()辺り)から変更してください。

f:id:anemptyarchive:20181209232346p:plain
単語文書行列
ちなみに、混入した日本語文を取り除けるなら、混合文のまま taggedText()に渡せばいいのでは?と思ったのですが、試したら英単語の前後にスペースが入っていると問題なくできそうですが、スペースがなければセットで"unknown"と返ってきちゃいます。つまり、アルファベットの前後にスペースを加える処理ができれば処理がかなり楽になりそうです。私にはまだ。。。
 
 

〇おわりに

 今後このブログで取り上げるテキスト分析ではこの処理を通したものを使って料理したものになるでしょう。知識が増えるごとに改善していきます。

 効果検証についてを次回以降行いたかったのですが、やはりR自体の入門書からちゃんと進めていくことが必要だと感じたので、テキストマイニングに関する記事はペースが落ちそうです。残念です。これから『RStudioではじめるRプログラミング入門』『RユーザーのためのRStudio[実践]入門』を進めていきます。なので、初学者目線での参考書籍の紹介記事とかになるでしょうか。

 最後まで読んでいただきありがとうございました。頑張ります!


2018.12.16.『RStudioではじめるRプログラミング入門』で得た知識をもとに記事を加筆修正しました。ところで次は『宇宙本』でいいですか?『Rではじめるデータサイエンス』がいいでしょうか??とりあえず『リーダブルコード』を読み始めました。テキストマイニングの理論の勉強も進めたいしなぁ。
 それと、原因不明だったエラーの原因も分かりました。そもそも英語が混じっていない文章だと、英語解析器に空のテキストを投げてしまい当然のようにエラーという具合でした。しかし全文日本語だとエラーならすぐに気付きそうなものですが、MeCabのタグ付け具合によって頻繁に日本語が混じって空にならずエラーが起こらなかったので、エラーが出る元データと出ない元データの違いが分からなかったということでした。いやまずエラーメッセージを読めよ、、、これも勉強!

 今後もどんどん改善していく所存です。それでは!