何語の文字列かを判定するためのRパッケージ

概要
統計処理ソフト R の franc パッケージを使うと、どんな言葉の文字列かを判定することができる。

franc パッケージ

統計処理ソフト R で、ある文字列が何語の文字列かを判定したい場合、franc というパッケージで判定できる。例えば、"To be or not to be, that is the question." という文字列から、これが英語であると判定することができる。

インストール方法

このパッケージはCRAN上に存在しているので、普通に install.packages を使ってインストールすることが可能である。具体的には以下のコードで franc パッケージをインストールすることができる。

install.packages("franc")

franc 函数を使った言語判定

franc パッケージでは、franc という函数で言語を判定することができる。具体的には、以下に示すソースコードのように、franc 函数の引数に文字列を入れれば、何語か判定される

# パッケージの読み込み
library("franc")

# franc による言語判定
# 結果は、"jpn"(日本語)
franc("ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。")
# 結果は、"cmn"(中国語)
franc("我要给阿Q做正传,已经不止一两年了。")
# 結果は、"eng"(英語)
franc("To be or not to be, that is the question.")
# 結果は、"fra"(フランス語)
franc("Soldats, songez que du haut de ces monuments quarante siècles vous contemplent.")

なお、franc は常に正しく言語を判定できるわけではない。例えば、以下のコードを実行すると、日本語の文字列が誤って "cms"(中国語)と判断される。

# 結果が "cmn"(中国語) となってしまう
franc("下人の行方は、誰も知らない。")

略称から言語名を調べる

franc の結果は、"jpn" や "eng" のようにラテン文字3つの略称で表示される。こうした略称から言語名を知りたい場合、franc パッケージに付属している speakers というデータフレームを見る必要がある。speakers データフレームには、言語ごとに、このパッケージでの略称(language列)、話者数(speakers列)、言語名(name列)などの情報が入っている。

"jpn" という略称が何なのかを調べたければ、以下のコードを実行すれば良い。

subset(speakers, language == "jpn")

これを実行すると、次のような結果が返される。

>    language  speakers     name iso6391 iso6392
> 10      jpn 125000000 Japanese      ja     jpn

ここから、"jpn" は Japanese(日本語)の略称であることが分かる。

略称でなく、言語名を直接得る

もし、"jpn" や "eng" のような略称ではなく、直接 "Japanese" や "English" という言語名を知りたかったら、以下のソースコードに示す函数 franc_long_name を定義すれば良い。この函数では、franc が求めた言語の略称を、speakers データフレームと照らし合わせて、言語名を出力するところまでを一気に行うことができる。

# 函数 franc_long_name の定義
franc_long_name <- function(x, ...){
    short_lang_name <- franc(x, ...)
    if(short_lang_name == "und"){
      long_name <- "Undefined"
    } else {
      long_name <- as.vector(
        unlist(
          subset(speakers, language == short_lang_name, "name")
        )
      )
    }
    return(long_name)
}

# 実行例
# 結果として、"Japanese"が返される。
franc_long_name("ある日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。")

Web上のテキストの言語判定

上記のように単純な文字列を使うだけでは面白くないので、Web上からテキストを抽出して、その言語を判定するということをやってみよう。言語判定の対象の事例として、世界人権宣言第1条の前半部分を5つの言語で表したものを用意した。

Web上からテキストを抽出するには、rvest パッケージが便利だ。もし、rvest パッケージがインストールされていなければ、install.packages("rvest") でインストールすればよい。

さっそく実行してみよう。以下に記してあるソースコードを実行すれば、Web上にある世界人権宣言第1条の前半部分を5つの言語で表したものを読み取り、そこから読み取ったものがそれぞれ何語かを判定することができる。

# パッケージの読み込み
library("franc")
library("rvest")

# Web上にあるHTMLの読み取り
html <- read_html("http://fnshr.info/toolbox/html/univ_decl_human_rights.html")
# 読み取ったHTMLの中で、pタグで囲まれている文字列を順に
# 抽出し、extracted_text の中にベクトルとして格納する。
extracted_text <- html %>%
  html_nodes(xpath = '//p') %>%
  html_text()
# extracted_text の中身は、
# [1] "すべての人間は、生れながらにして自由であり、かつ、尊厳と権利とについて平等である。"
# [2] "All human beings are born free and equal in dignity and rights."
# [3] "Tous les êtres humains naissent libres et égaux en dignité et en droits."
# [4] "人人生而自由,在尊严和权利上一律平等。"
# [5] "모든 인간은 태어날 때부터 자유로우며 그 존엄과 권리에 있어 동등하다. "
# となっている。

# extracted_text ベクトルの中に入っている文字列について
# 1つずつ franc を使って何語かを判定する。
unlist(lapply(extracted_text, franc))
# 判定結果として、
# [1] "jpn" "eng" "fra" "cmn" "kor"
# が得られる。

つまり、順に日本語、英語、フランス語、中国語、韓国語であると判定されたわけである。

なお、先ほどのソースコードで unlist(lapply(extracted_text, franc)) とする代わりに、franc(extracted_text) とした方が楽なのではないかと考えた人がいるかもしれない。だが、franc は長さ1の文字列ベクトルしか受け付けないので、長さが5である extracted_text をそのまま引数に取ることができない。このため、lapply のような apply 系函数を使って1つずつ処理しないとうまくいかない。

補遺

franc 函数のデフォルト

franc 函数は、デフォルトでは与える文字列が短い場合、具体的には10字に満たない場合は何語か判定せずに、"und"を返す。"und"は未定義を意味する“Undefined”の略であろう。

franc 函数のオプションとして、min_length を指定すれば、その値以上の長さの文字列に対して何語か判定する。

# 短いので、"und" が返される
franc("Very good")
# 3字以上の文字列に対して何語か判定するようになり、
# ここでは "eng" が得られる。
franc("Very good", min_length = 3)

また、デフォルトでは話者数が100万人以下の言語と判定されることはない。100万人以下の言語も対象にしたければ、franc 函数のオプションの1つ min_speakers に適宜小さな値を設定すれば良い。

franc_all 函数

franc 函数で返ってくるのは、最も可能性が高い言語1つだけである。これに対して、franc_all 函数を使うと、可能性がある言語の候補が、可能性の強さを示す数値とともに複数出てくる(ただし場合によっては、franc_all を使っても1つの言語しか候補として出てこないこともある)。