日本語の「っ」から始まる送り仮名とSKK+AZIKによる日本語入力に関する考察

by

始めに

SKKという日本語入力システムがある。
元々はEmacsというエディタ向けに開発されたものだが、現在では各種OSのIMEや他のエディタの日本語入力システムとしても活用されている。

SKKの特徴は、ユーザーがどこまでが漢字でどこからが送り仮名かを明示しながら変換する仕組みだ。
文節の分析がないため、軽量に実装できるだけでなく、うまく変換できないケースのほとんどが己れの日本語力の不足であり、システム側に比べ改善しやすいというメリットがある。

これにローマ字を拡張したAZIKという記法を組み合わせると、非常に軽快に日本語入力できるので、私はいたく気に入っている。

最近使っているNeovimでは、skkeletonというSKK日本語入力システムが利用でき、愛用している。

しかし、送り仮名の始まりが「っ」となるパターンにおいて、やや使い勝手の悪さを感じているのでIssueを起票した。

JIS配列のキーボードであれば、:が「っ」として入力される。
SKKではShiftキーを使うと送り仮名の開始を指定できるので;が送り仮名としての「っ」の開始とするのが妥当だ。

しかし設定を工夫しても「った」などと促音にもう一字入力するまでは変換を実用的に利用できない問題がある。

SKK日本語入力FEPやfcitx-skkなど、他のSKK実装では「っ」で変換を開始できていたので、skkeletonでも同様にして欲しいというのが要望だ。

ところでSKKが漢字部分と送り仮名部分を受け取ったときに辞書を参照するわけだが、ここで「っ」の次に何がくるか分からないと、辞書のどの語にマッチすればいいか分からないという問題がある。

fcitx-skkでは「っ」の後はた行が続くと仮定を置いていそうだが、その妥当性を確認するため、livedoor ニュースコーパスデータセットを軽く分析してみることにした。

結論

送り仮名が「っ」で始まるものの90%以上は更にた行が続くと見て問題ない。
例外はあるが、それぞれユーザー辞書登録していけば間に合いそう。

分析

データセットの準備

この部分はシェルスクリプトでやっちゃいます。

ダウンロード

if [[ ! -d asset/dataset/text ]]; then
  mkdir -p asset/dataset
  curl -L https://www.rondhuit.com/download/ldcc-20140209.tar.gz | tar -xz -C asset/dataset
fi

絞り込み

漢字の後に「っ」と平仮名が続くパターンを絞り込んだテキストをasset/input.txtとして用意。

rgコマンドは\p{Han}で漢字にマッチするといったUnicode文字プロパティが使えて便利。

rg -oI "\p{Han}っ\p{Hiragana}" asset/dataset/text > asset/input.txt

データの整形と集計

ここからはR言語で。

漢字の後に「っ」と平仮名が続く文字列に対し、平仮名があ行、か行…とどれにあたるかでグループ分けしたデータフレームを用意

data <- readr::read_lines("asset/input.txt")

patterns <- c(
  あ行 = "[あいうえお]$",
  か行 = "[かきくけこ]$",
  が行 = "[がぎぐげご]$",
  さ行 = "[さしすせそ]$",
  ざ行 = "[ざじずぜぞ]$",
  た行 = "[たちつてと]$",
  だ行 = "[だぢづでど]$",
  は行 = "[はひふへほ]$",
  ば行 = "[ばびぶべぼ]$",
  ぱ行 = "[ぱぴぷぺぽ]$",
  ま行 = "[まみむめも]$",
  や行 = "[やゆよ]$",
  ら行 = "[らりるれろ]$",
  わ行 = "[わをん]$"
)

df <- tibble::tibble(
  group = names(patterns),
  data = patterns |> lapply(function(pat) data[grepl(pat, data)])
) |>
  dplyr::mutate(
    data_unique = lapply(data, unique),
    count_occurrence = lengths(data),
    count_unique = lengths(data_unique)
  )

df
# A tibble: 14 × 5
   group data           data_unique  count_occurrence count_unique
   <chr> <named list>   <named list>            <int>        <int>
 1 あ行  <chr [0]>      <chr [0]>                   0            0
 2 か行  <chr [109]>    <chr [22]>                109           22
 3 が行  <chr [0]>      <chr [0]>                   0            0
 4 さ行  <chr [12]>     <chr [8]>                  12            8
 5 ざ行  <chr [0]>      <chr [0]>                   0            0
 6 た行  <chr [23,650]> <chr [843]>             23650          843
 7 だ行  <chr [0]>      <chr [0]>                   0            0
 8 は行  <chr [0]>      <chr [0]>                   0            0
 9 ば行  <chr [1]>      <chr [1]>                   1            1
10 ぱ行  <chr [322]>    <chr [81]>                322           81
11 ま行  <chr [0]>      <chr [0]>                   0            0
12 や行  <chr [0]>      <chr [0]>                   0            0
13 ら行  <chr [0]>      <chr [0]>                   0            0
14 わ行  <chr [0]>      <chr [0]>                   0            0

た行が圧倒的に多く、ぱ行、か行、さ行、ば行が続くことがわかる

「立って」、「戦った」、「反った」など、促音にた行が続くパターンは多いと想像がつくことと矛盾しない

漢字に促音+た行以外が続くパターンについて深堀り

もう少し見てみよう。
まずはデータを一覧しやすいようにしておく。

vec <- df |> dplyr::select(group, data_unique) |> tibble::deframe() |> lapply(sort)

ば行

「甘酸っばい」の1件のみ。
「甘酢っぱい」のタイポの模様1

vec["ば行"]
$ば行
[1] "酸っば"

さ行

「っす」で終わるパターンがほとんど。

vec["さ行"]
$さ行
[1] "人っす" "加っす" "引っさ" "愛っす" "真っす" "薄っす" "足っす" "雨っす"

か行

送り仮名なパターンもあれば、そうじゃないものもある

vec["か行"]
$か行
 [1] "丸っこ" "乗っか" "乗っけ" "人っき" "初っか" "取っか" "吹っか" "大っき"
 [9] "女っこ" "姪っこ" "引っか" "引っこ" "懐っこ" "抱っこ" "根っか" "根っこ"
[17] "甥っこ" "端っこ" "脂っこ" "落っこ" "追っか" "隅っこ"

など

ぱ行

名詞に「ぽい」や「ぽく」が続くパターンが多そう

vec["ぱ行"]
$ぱ行
 [1] "人っぽ" "今っぽ" "代っぽ" "会っぷ" "供っぽ" "俗っぽ" "兆っぽ" "化っぷ"
 [9] "化っぽ" "司っぽ" "問っぽ" "嘘っぱ" "嘘っぽ" "団っぽ" "国っぽ" "夏っぽ"
[17] "外っぽ" "女っぷ" "女っぽ" "妙っぷ" "娘っぽ" "子っぽ" "安っぽ" "家っぽ"
[25] "崖っぷ" "年っぽ" "引っぱ" "性っぽ" "朝っぱ" "本っぽ" "様っぷ" "毛っぽ"
[33] "気っぷ" "水っぽ" "油っぽ" "派っぽ" "潔っぽ" "熱っぷ" "熱っぽ" "犬っぷ"
[41] "犯っぽ" "狗っぷ" "球っぽ" "生っぽ" "男っぷ" "男っぽ" "疎っぷ" "症っぽ"
[49] "痴っぽ" "白っぽ" "砂っぽ" "秀っぽ" "秋っぽ" "空っぽ" "童っぷ" "肉っぽ"
[57] "良っぽ" "色っぽ" "艶っぽ" "落っぷ" "葉っぱ" "薄っぺ" "要っぽ" "親っぽ"
[65] "訳っぽ" "話っぽ" "語っぽ" "談っぽ" "貌っぷ" "走っぷ" "足っぽ" "近っぽ"
[73] "通っぽ" "進っぷ" "酔っぱ" "酸っぱ" "長っぷ" "雄っぱ" "集っぷ" "黄っぽ"
[81] "黒っぽ"

終わりに

本分析結果を元にskkeletonでは「っ」で変換を開始するimmediatelyOkuriConvertオプション(既定値:true)が追加されました#139
作者のkuuoteさんに感謝。


  1. 初稿で見落としてました。教えていただいたaki_itoさんに感謝 ↩︎