K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

氏名から敬称やカッコ書きを除去する

01.7.7

氏名から敬称やカッコ書きを除去する

最終更新 2020-04-22 読了時間 2 分
まとめ
「田中太郎 様」「佐藤花子(新担当)」のような氏名の文字列から、括弧書きの補足と末尾の敬称を取り除いて「田中太郎」「佐藤花子」に揃えます。括弧は正規表現 PAREN_PATTERN で、敬称は「様」「さん」「殿」など 7 語の HONORIFICS リストと endswith で削り、最後に全角スペースと連続空白を半角 1 つに揃えます。顧客名寄せや担当者の照合で「田中太郎」と「田中太郎 様」を同一人物として扱えるようにする前処理です。

直感 #

顧客名や担当者名には「田中太郎 様」「佐藤花子(新担当)」のように、名前そのもの以外の情報が付いていることがよくあります。名寄せは文字列の完全一致で行うことが多いので、「田中太郎」と「田中太郎 様」は別人として数えられてしまいます。残すのは名前の本体だけです。まず括弧とその中身を PAREN_PATTERN でまるごと消し、次に末尾に残った敬称を HONORIFICS のリストで削り、最後に空白の種類と個数を揃えます。括弧を先に処理するのは、「佐藤花子(新担当)様」のように括弧の後に敬称が来るケースで、括弧が消えてから endswith を見たいからです。

Python でクリーニングする #

次のコードは 7 種類の敬称リストと括弧用の正規表現を定義し、clean_name が括弧の除去、敬称の除去、空白の正規化の順に処理します。4 件のサンプルには、敬称ではなく役職が付いたものも混ぜています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import re

HONORIFICS = ["様", "さま", "さん", "ちゃん", "殿", "どの", "氏"]
PAREN_PATTERN = re.compile(r"(.*?)|\\(.*?\\)|\[.*?\]")

def clean_name(name: str) -> str:
    name = PAREN_PATTERN.sub("", name)
    for honorific in HONORIFICS:
        if name.endswith(honorific):
            name = name[: -len(honorific)]
            break
    name = name.replace(" ", " ").strip()
    return re.sub(r"\s+", " ", name)

samples = [
    "田中太郎 様",
    "佐藤花子(新担当)",
    "山本-次郎さん",
    "㈱ABC 営業本部 鈴木次長",
]

for s in samples:
    print(s, "→", clean_name(s))

実行結果の読み方 #

1 件目は末尾の「様」と直前の半角スペースが消えて「田中太郎」になります。2 件目は括弧ごと「(新担当)」が落ちます。3 件目の「山本-次郎」のハイフンは名前の一部として残り、4 件目の「鈴木次長」は役職なので HONORIFICS に該当せず、変化は全角スペースが半角になった点だけです。名寄せの前後で nunique() を比べると、この処理でどれだけ重複が束ねられたかを数値で確認できます。

使いどころと落とし穴 #

「部長」「課長」のような役職を残したい場合は HONORIFICS とは別の TITLES リストを用意し、削るのではなく別カラムへ切り出して保持します。カタカナやローマ字で書かれた敬称(サマ、SAMA)が混じる列では、先に NFKC 正規化と大文字小文字の統一をかけてからリストを拡張します。企業名と担当者名が同じカラムに入っている場合は、敬称除去をかけたあとに「2〜4 文字の漢字+空白+2〜4 文字の漢字」のような正規表現で人名らしさを判定し、人名だけを抽出する流れが実務では定番です。