「そりゃ姓名分離できねえわ」って思った野球選手名ランキング

# 概要
[とある事情](https://twitter.com/gobotennfire/status/1361283269883359233?s=20)で、スペース区切りなしで書かれた<b>日本人野球選手のフルネームを苗字（姓）と名前（名）に分離する</b>必要に駆られていました。このために、<b>ある程度プログラムで自動的に分離してから目視で修正する</b>という作業を行っていたのですが、その過程で<b>「これはプログラムが正しく姓名分離できなくても仕方ないなあ」</b>と感じた野球選手名を紹介したいと思います。
# 背景
日本人の名前を姓と名に分離することは、単語の区切りが明確な外国人名の姓名分離と比べて一般に難易度が高いです。日本人名を姓名分離する方法として

* <b>手法1. 苗字辞書と比較して姓がどこまでかを判定する</b>
    * 例：[yuki_marketing様の実装](https://twitter.com/yuki_marketing/status/1211075889032617984?s=20)
* <b>手法2. 固定の苗字辞書はもたずに統計的に姓と名の切れ目を判定する</b>
    * 例：rskmoi様の[NameDivider](https://github.com/rskmoi/namedivider-python)

の大きく２つが提案されており、それぞれ一長一短があります。
今回は、<b>両方の手法で姓名分離してみて、単体での信頼度が低いものや二者の結果が異なるものにフラグを建てる</b>ことで、プログラムが姓名分離を上手くできなかった名前を見つけやすくしました。（実装コードは末尾に記載します）

以下、目視で修正作業をしているときに、プログラムが上手く姓名分離できなくても正直仕方ないと思った名前たちをランキング形式で紹介していきます。ランキングの基準は完全な主観です。

# 一覧
今回ランクインした選手の一覧です。もしよかったら、いくつくらい苗字を当てられるか試してみてください。

* 赤根谷飛雄太郎
* 今久留主功
* 南牟礼豊蔵
* 瀧安治
* 戒能朶一
* 万波中正
* 上水流洋
* 加賀美希昇
* 東新昇
* 東郷幸

それでは以下より、ランキング紹介兼正解発表です。
# ランキング
## 10位. 赤根谷飛雄太郎
10位は、東急フライヤーズ（現 日本ハムファイターズ）に在籍された赤根谷 飛雄太郎（あかねや ひゅうたろう）選手です。
手法１は「赤根 谷飛雄太郎」、手法２は「赤根谷飛 雄太郎」と出力し、どちらも間違いでした。
巨人の星を知っていれば「飛雄太郎」を見抜くのはそう難しくありませんが、そのような知識を持たないプログラムが「赤根」のあとや、「雄太郎」の前で区切ってしまうのは、やむなしな気がします。
## 9位. 今久留主功
9位は、毎日オリオンズ（現 千葉ロッテマリーンズ）や、の近鉄バールス（現 近鉄バファローズ）に在籍された「今久留主 功」（いまくるす いさお）選手です。
手法1は「今 久留主功」、手法２は「今久留 主功」と出力し、どちらも間違いでした。
４文字の姓というのが珍しく、プログラムには難易度高かったと思われます。
人間が判断する場合でも、「功」が名前っぽいことがなんとなくわかるものの「主功」という名前もありえないとは言い切れず、結構迷いそうです。なお、実兄の今久留主 淳（いまくるす じゅん）選手もいますが、こちらは（人間が見る分には）「淳」が名前っぽい分、少し簡単な気がします。
## 8位. 南牟礼豊蔵
8位は、阪急ブレーブス（現 オリックス・バファローズ）や中日ドラゴンズ、阪神タイガースに在籍された南牟礼 豊蔵（みなみむれ とよぞう）選手です。
手法1は「南 牟礼豊蔵」と間違え、手法２は「南牟礼 豊蔵」と正解しました。「南牟礼」という苗字自体を知らなくても、「豊蔵」が下の名前っぽいことに気付けると分離可能なので、手法２のような統計的な手法が上手く機能したケースかと思います。
人間が推測する場合、まず南牟礼という苗字が難しすぎて読めませんし、全体的にどこで区切るかもわかりにくいです。
## 7位. 瀧安治
読売ジャイアンツに在籍された瀧 安治（たき やすはる）選手です。
手法１は「瀧 安治」と正解し、手法２は「瀧安 治」と間違えました。
３文字のシンプルな名前ながら、下の名前が「治」でも「安治」でもいけそうなので、判断に困ってしまう名前かと思います。
## 6位. 戒能朶一
中日ドラゴンズの前身である名古屋軍に在籍された戒能 朶一（かいのう だいち）選手です。
手法1は「戒能 朶一」と正解し、手法２は「戒能朶 一」と間違えました。
人間の場合、「戒能」という苗字を知らないと、とりあえず名前を最後の「一（はじめ）」だと思って、手法2と同じように間違うケースが多そうです。
## 5位. 万波中正
5位は、北海道日本ハムファイターズ所属の万波 中正（まんなみ ちゅうせい）選手です。
手法１は「万波 中正」と正解し、手法２は「万波中 正」と間違えました。「中正」よりも「正」が下の名前っぽいので、手法２は間違えたのだと考えられます。全体的に、手法２は人間的にも納得感のある間違え方をすることが多いです。
## 4位. 上水流洋
4位は、ヤクルトスワローズに所属された上水流 洋（かみずる ひろし）選手です。
手法１は「上水流 洋」と正解し、手法２は「上水 流洋」と間違えました。
「流洋」も読み方の想像がつきにくいものの下の名前としてありえないとは言い切れないので、基本的には「上水流」という苗字を知っているかどうかが、正しく判断できるかの分かれ目と思います。
なお、似たパターンで、下水流 昂（しもずる こう）選手（東北楽天ゴールデンイーグルス）もいますが、こちらは「下水」という苗字はなんとなくなさそうな気がするので、人間にとっては、少し難易度は下がるかもしれません。
## 3位. 加賀美希昇
3位は、横浜DeNAベイスターズに在籍された加賀美 希昇（かがみ きしょう）選手です。
手法１は「加賀美 希昇」と正解し、手法２は「加賀 美希昇」と間違えました。
「加賀」も「加賀美」も実在する苗字であり、かつ、「美希昇」も「希昇」も下の名前としては同程度にありえそうなので、苗字から攻めても名前から攻めても非常に判別が難しいです。
## 2位. 東新昇
2位は、近鉄バファローズに在籍された東新 昇（とうしん のぼる）選手です。
手法１は「東新 昇」と正解し、手法２は「東 新昇」と間違えました。
３位の希昇がいけるなら新昇もいけるかと思いきや、「東新 昇」です。東新という苗字が珍しいので、知らずに「東」で区切ってしまったとしても誰も責められないでしょう。
## 1位. 東郷幸
1位は、大阪タイガース（現 阪神タイガース）や国鉄スワローズ（現 ヤクルトスワローズ）に在籍された東 郷幸（あずま さとゆき）選手です。
手法１も手法２も「東郷 幸」と間違えました。両手法が同じ間違え方をしたケースはかなりレアです。しかも信頼度もそこそこ高く、<b>手法１も手法2も自信をもって間違えています</b>。
人間でも、ほとんどの人は「東郷」さんだと思うのではないかと思います。「郷幸（さとゆき）」という名前もあまり浮かびませんし、初見で間違える確率はランキングのなかでも圧倒的上位と推察されます。文句なしの1位です。

# ギリギリランクインしなかった選手名
おまけとして、今回惜しくもランク外となった難姓名分離選手の方々を紹介します。姓名分離のしにくさはあくまで主観なので、こちらのほうが難しいと感じる人もいるかもしれません。

* 田代須恵雄 選手 （巨人 (1937 - 1939))
* 大慈彌功 選手 （西武ライオンズ (1976 - 1979))
* 日暮矢麻人 選手 （福岡ソフトバンクホークス (2018 - 2020) )
* 真栄喜正和 選手 （日本ハムファイターズ (1991 - 1995) )
* 嘉弥真新也 選手 （福岡ソフトバンクホークス (2018 - )
* 朝樹一義世 選手 （阪神タイガース (1960 - 1967), 広島東洋カープ (1968 - 1970))
* 奥浪鏡 選手 (オリックス・バファローズ (2014 - 2017))
* 作道烝 選手 (日拓ホームフライヤーズ (1964 - 1973))
* 谷繁元信 選手 (横浜ベイスターズ (1989 - 2001), 中日ドラゴンズ (2002 - 2015))
* 上福元勤 選手 （読売ジャイアンツ (1984 - 1986))

# 考察
プログラム的に姓名分離しにくい名前とはどういうものかを考察しました。
ランキングを眺めていると以下のような要因がありそうです。

* <b>長い名前のとき</b>
    * 例： 赤根谷飛雄太郎、今久留主功
    * 長い名前はどこで区切るかの候補が多くなるので、必然的にプログラムがミスをする確率が上がります。
* <b>(辞書にない)珍しい苗字のとき</b>
    * 例： 南牟礼豊蔵、今久留主功
    * 辞書に存在しない苗字の場合、手法１のような辞書ベースの方法はまったく通用しなくなります。概算になりますが、今回は対象とした7000名ほどのうち、40名ほどは辞書に含まれない苗字の選手でした。
* <b>下の名前が正解より少ない文字数で作れるとき</b>
    * 例：万波中正、瀧安治、戒能朶一
    * 「正」「治」「一」などはそれ単体でも下の名前として成立するため、手法２のような統計的な方法を用いたときに、その直前で区切られる確率が上がってしまいます。
* <b>苗字の一部が別の存在する苗字になるとき</b>
    * 例：東郷幸、東新昇、加賀美希昇
    * 前項目の苗字バージョンです。苗字の部分文字列も存在する苗字のときは、プログラムが間違う確率がぐっと高まります。

# おわりに
プログラムが姓名分離を間違えた選手の中から、特に分離が難しそうな野球選手名をランキング形式で紹介してみました。またどのような名前が姓名分離しにくいのかを考察してみました。
姓名分離を試みるときに考察で述べたような特徴を意識しておくと、自動姓名分離の間違いに気づきやすくなるかもしれません。

# 補足
以下、プログラムによる姓名分離に用いたコードを載せておきます。

## 環境

```
macOS Big Sur バージョン11.1
python 3.8.0
```

## 手法1. 苗字辞書と比較して姓がどこまでかを判定する
[yuki_marketing様のGoogleSheetsによる実装](https://twitter.com/yuki_marketing/status/1211075889032617984?s=20)をpythonに移植して実現しました。苗字辞書は[myoji-yurai.net](https://myoji-yurai.net/)の情報をもとにyuki_marketing様が作成したものをお借りしました。

```:family.txt
佐藤
鈴木
高橋
田中
伊藤
渡辺
山本
中村
小林
加藤
... (以下、苗字を1行に一つずつ)
```

```Python
UNKNOWN = "unknown"
with open("family.txt") as f:
  families = f.read().splitlines()

def divide_with_dict(name):
  family, given = UNKNOWN, UNKNOWN
  #1文字の場合、解析不可
  if len(name)<=1: return family, given, 0
  #4文字以下ならマッチした苗字のうち最も長いものを採用
  #信頼度はマッチした苗字の個数の逆数
  if len(name)<=4:
    cnt = 0
    for i in range(len(name)):
      if name[:i] in families:
        family, given = name[:i], name[i:]
        cnt += 1
    if cnt ==0: return family, given, 0
    #scoreはマッチした苗字の個数の逆数
    else: return family, given, 1/cnt

```
## 手法2. 固定の苗字辞書はもたずに統計的に姓と名の切れ目を判定する

rskmoi様の[NameDivider](https://github.com/rskmoi/namedivider-python)を利用させていただきました。

```
pip install namedivider-python
```

```Python
from namedivider import NameDivider

def divide_without_dict(name):
  family, given = UNKNOWN, UNKNOWN
  if len(name)<=1: return family, given, 0
  rslt = name_divider.divide_name(name).to_dict()
  return rslt["family"], rslt["given"], rslt["score"]
```

## 手法1と手法2の出力を比較しフラグを立てる
手法1と手法2の出力結果に応じたフラグ変数を含むリストを返す関数を作りました。
フラグは、f1とf2がunknownなら1、どちらか一方がunknownなら2、f1とf2が両方unknownでなく、かつ、それぞれ異なるときは0、f1とf2が両方unknownでなく、かつ、それぞれ同じときは3としました。

```Python
def divide_name(name):
  f1,g1,s1 = divide_with_dict(name)
  f2,g2,s2 = divide_without_dict(name)
  if f1 == UNKNOWN and f2 == UNKNOWN: flag=1
  elif f1 == UNKNOWN or f2 == UNKNOWN: flag=2
  elif f1 != f2: flag=0
  else: flag=3
  
  return [f1,g1,s1,f2,g2,s2,flag]
```

あとは野球選手名のリストに対して`divide_name`を実行して、各手法のスコアやフラグなど任意の基準で並べ替えをすれば、出力の怪しいものから優先的にチェックすることができます。