DuckDBで「由比ヶ浜結衣」を探す
はじめに
ライトノベル『やはり俺の青春ラブコメはまちがっている。』には「由比ヶ浜結衣(ゆいがはま ゆい)」という人物が登場します。
彼女の名前は「姓が地名で、かつ、名の読みが姓の読みの接頭辞」になっています。「雪ノ下雪乃(ゆきのした ゆきの)」もそうですね。このような名前をDuckDBと計算機の力を借りて探してみましょう。
最初は自前のスクリプトでやっていたのですが、DuckDBを使うとかなり簡単に実現できることがわかりました。早速試してみましょう。
準備
DuckDB
DuckDBはインプロセスのデータ分析用データベースです。SQL風の言語でクエリできます。先日バージョン1.0.0が公開されました 🎉。
https://duckdb.org/#quickinstall を参照してインストールしておいてください。
データの準備
まず地名の一覧と、人名の一覧を用意します。そこから条件を満たす名前を抽出することにしましょう。
地名と人名のデータとして、形態素解析器Sudachiの辞書であるSudachiDictを使うことにします。
DuckDBで読み込むためには、Sudachi用にビルドされたバイナリファイルの辞書ではなく、その元データとなるcsvファイルが必要です。http://sudachi.s3-website-ap-northeast-1.amazonaws.com/sudachidict-raw/ から small_lex.zip
, core_lex.zip
, notcore_lex.zip
をダウンロードします。今回は20240409
のバージョンを使用しました。
DuckDBにはgzipされたファイルであればそのままクエリする機能があります(https://duckdb.org/docs/guides/performance/file_formats#loading-csv-files 参照)。しかし、zipファイルには対応していないようです。unzipしておきます。
使ったコマンドは以下の通りです。
wget http://sudachi.s3-website-ap-northeast-1.amazonaws.com/sudachidict-raw/20240409/small_lex.zip
wget http://sudachi.s3-website-ap-northeast-1.amazonaws.com/sudachidict-raw/20240409/core_lex.zip
wget http://sudachi.s3-website-ap-northeast-1.amazonaws.com/sudachidict-raw/20240409/notcore_lex.zip
unzip core_lex.zip
unzip small_lex.zip
unzip notcore_lex.zip
これで準備は完了です。
試してみる
csvファイルをテーブルのように扱う
まずはクエリしてみます。SELECT
の前にあるD
はDuckDBのプロンプトです。
❯ duckdb
v1.0.0 1f98600c2c
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
D SELECT * FROM 'core_lex.csv';
┌──────────────┬──────────┬──────────┬──────────┬───┬──────────────────────┬──────────────────────┬──────────────────────┬──────────┐
│ column00 │ column01 │ column02 │ column03 │ … │ column15 │ column16 │ column17 │ column18 │
│ varchar │ int64 │ int64 │ int64 │ │ varchar │ varchar │ varchar │ varchar │
├──────────────┼──────────┼──────────┼──────────┼───┼──────────────────────┼──────────────────────┼──────────────────────┼──────────┤
│ #9 │ 4785 │ 4785 │ 6000 │ … │ * │ * │ * │ 005889 │
│ .com │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 100 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 1000本 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 1000本ノック │ 5139 │ 5131 │ 1305 │ … │ 765610/229558 │ 765610/229558 │ 765610/229558 │ * │
│ 100yen plaza │ 4785 │ 4785 │ 3000 │ … │ * │ * │ * │ * │
│ 100年企業 │ 4794 │ 5146 │ 5500 │ … │ 765609/407980/287879 │ 765609/407980/287879 │ 765609/407980/287879 │ * │
│ 114 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ 003983 │
│ 11条 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 12 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 12チャンネル │ 4794 │ 5144 │ 1025 │ … │ 765616/218934 │ 765616/218934 │ 765616/218934 │ * │
│ 13丁目 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 14条 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 16 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 16条 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 181丁目 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 181丁目駅 │ 4791 │ 5146 │ 2559 │ … │ 765622/755332 │ * │ 765622/755332 │ * │
│ 18丁目 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 19条 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ * │
│ 1位 │ -1 │ -1 │ 0 │ … │ * │ * │ * │ 000521 │
│ · │ · │ · │ · │ · │ · │ · │ · │ · │
│ · │ · │ · │ · │ · │ · │ · │ · │ · │
│ · │ · │ · │ · │ · │ · │ · │ · │ · │
│ 龝丸 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝井 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝元 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝利 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝原 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝吉 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝和 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝場 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝好 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝宗 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝岡 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝月 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝本 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝村 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝永 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝池 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝津 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝田 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝葉 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
│ 龝谷 │ 4790 │ 4790 │ 10000 │ … │ * │ * │ * │ * │
├──────────────┴──────────┴──────────┴──────────┴───┴──────────────────────┴──────────────────────┴──────────────────────┴──────────┤
│ 858359 rows (40 shown) 19 columns (8 shown) │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
いいですね。完璧です。
複数ファイルを一度に検索する
でも、辞書ファイルは3つあったのでした。大丈夫です。実はFROM
のところにワイルドカードが使えます。
D SELECT * FROM '*.csv';
┌──────────────┬──────────┬──────────┬───┬──────────────────────┬──────────────────────┬──────────────────────┬───────────────┐
│ column00 │ column01 │ column02 │ … │ column15 │ column16 │ column17 │ column18 │
│ varchar │ int64 │ int64 │ │ varchar │ varchar │ varchar │ varchar │
├──────────────┼──────────┼──────────┼───┼──────────────────────┼──────────────────────┼──────────────────────┼───────────────┤
│ #9 │ 4785 │ 4785 │ … │ * │ * │ * │ 005889 │
│ .com │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 100 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 1000本 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 1000本ノック │ 5139 │ 5131 │ … │ 765610/229558 │ 765610/229558 │ 765610/229558 │ * │
│ 100yen plaza │ 4785 │ 4785 │ … │ * │ * │ * │ * │
│ 100年企業 │ 4794 │ 5146 │ … │ 765609/407980/287879 │ 765609/407980/287879 │ 765609/407980/287879 │ * │
│ 114 │ -1 │ -1 │ … │ * │ * │ * │ 003983 │
│ 11条 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 12 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 12チャンネル │ 4794 │ 5144 │ … │ 765616/218934 │ 765616/218934 │ 765616/218934 │ * │
│ 13丁目 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 14条 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 16 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 16条 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 181丁目 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 181丁目駅 │ 4791 │ 5146 │ … │ 765622/755332 │ * │ 765622/755332 │ * │
│ 18丁目 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 19条 │ -1 │ -1 │ … │ * │ * │ * │ * │
│ 1位 │ -1 │ -1 │ … │ * │ * │ * │ 000521 │
│ · │ · │ · │ · │ · │ · │ · │ · │
│ · │ · │ · │ · │ · │ · │ · │ · │
│ · │ · │ · │ · │ · │ · │ · │ · │
│ ' │ 5969 │ 5969 │ … │ * │ * │ * │ * │
│ 𢌞っ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ら │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞り │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞りゃ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞りゃ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞る │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞る │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞れ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞れ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ろ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ろ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ろう │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ろっ │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ん │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ん │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ん │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𢌞ん │ -1 │ -1 │ … │ * │ * │ * │ 000402/023239 │
│ 𣗄代 │ 4792 │ 4792 │ … │ * │ * │ * │ * │
│ 𥝱 │ 5128 │ 5128 │ … │ * │ * │ * │ * │
├──────────────┴──────────┴──────────┴───┴──────────────────────┴──────────────────────┴──────────────────────┴───────────────┤
│ 2880250 rows (40 shown) 19 columns (7 shown) │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
3つの辞書を同時に検索できていることがわかります。
名前探しに必要なパーツ
さっそく名前探しに入っていきましょう。
地名の抽出
まず地名の一覧を取り出します。
手始めに最初のカラムが「由比ヶ浜」となっているものをクエリして、どこに品詞情報があるかを見てみましょう。
横長の表が出力されると見づらいので、ドットコマンド.column
を使ってカラムごとの表示にしてみます。
D .column
D SELECT * FROM '*.csv' WHERE column00 = '由比ヶ浜';
┌──────────┬─────────┬────────────┐
│ Column │ Type │ Row 1 │
├──────────┼─────────┼────────────┤
│ column00 │ varchar │ 由比ヶ浜 │
│ column01 │ int64 │ 4792 │
│ column02 │ int64 │ 4792 │
│ column03 │ int64 │ 9219 │
│ column04 │ varchar │ 由比ヶ浜 │
│ column05 │ varchar │ 名詞 │
│ column06 │ varchar │ 固有名詞 │
│ column07 │ varchar │ 地名 │
│ column08 │ varchar │ 一般 │
│ column09 │ varchar │ * │
│ column10 │ varchar │ * │
│ column11 │ varchar │ ユイガハマ │
│ column12 │ varchar │ 由比ヶ浜 │
│ column13 │ varchar │ * │
│ column14 │ varchar │ A │
│ column15 │ varchar │ * │
│ column16 │ varchar │ * │
│ column17 │ varchar │ * │
│ column18 │ varchar │ * │
└──────────┴─────────┴────────────┘
-
column05
が「名詞」 -
column06
が「固有名詞」 -
column07
が「地名」 -
column08
が「一般」
になっていることがわかります。https://qiita.com/sakamoto_mi/items/c1787973dd1a591c9957 を参考に、色々クエリしてみると、今回の用途では column07
が「地名」であるという条件だけで十分そうです。
それから、column11
に「読み」が入っていることも覚えておきましょう。
.row
で行ごとの出力に戻して、地名をクエリしてみます。
D .row
D SELECT column00, column11 FROM '*.csv' WHERE column07 = '地名';
┌───────────────┬──────────────────────────────┐
│ column00 │ column11 │
│ varchar │ varchar │
├───────────────┼──────────────────────────────┤
│ 11条 │ ジュウイチジョウ │
│ 13丁目 │ ジュウサンチョウメ │
│ 14条 │ ジュウヨジョウ │
│ 16条 │ ジュウロクジョウ │
│ 181丁目 │ ヒャクハチジュウイチチョウメ │
│ 18丁目 │ ジュウハッチョウメ │
│ 19条 │ ジュウクジョウ │
│ 1号北 │ イチゴウキタ │
│ 1号南 │ イチゴウミナミ │
│ 28丁目 │ ニジュウハチチョウメ │
│ 33丁目 │ サンジュウサンチョウメ │
│ 5thアベニュー │ フィフスアベニュー │
│ 7丁目 │ ナナチョウメ │
│ 9条 │ クジョウ │
│ akiba │ アキバ │
│ albion │ アルビオン │
│ apia │ アピア │
│ arabia │ アラビア │
│ arezzo │ アレッツォ │
│ asturias │ アストゥリアス │
│ · │ · │
│ · │ · │
│ · │ · │
│ 龍敦 │ ロンドン │
│ 龍河 │ リュウガ │
│ 龍王 │ リュウオウ │
│ 龍王塘 │ リュウオウトウ │
│ 龍田 │ タツタ │
│ 龍神 │ リュウジン │
│ 龍言 │ リュウゴン │
│ 龍郷 │ タツゴウ │
│ 龍野 │ タツノ │
│ 龍頭 │ ヨンドウ │
│ 龍飛 │ タッピ │
│ 龜井戸 │ カメイド │
│ 龜住町 │ カメズミチョウ │
│ 龜埼 │ カメサキ │
│ 龜岡 │ カメオカ │
│ 龜川 │ カメカワ │
│ 龠 │ ユエ │
│ 神南備 │ カンナビ │
│ 都斯麻 │ ツシマ │
│ 𣗄代 │ タラノキダイ │
├───────────────┴──────────────────────────────┤
│ 606548 rows (40 shown) 2 columns │
└──────────────────────────────────────────────┘
悪くないですね。英数字のエントリもあるんですね。
人名の抽出
同様に今度は「結衣」でクエリしてみましょう。
D .column
D SELECT * FROM '*.csv' WHERE column00 = '結衣';
┌──────────┬─────────┬──────────┐
│ Column │ Type │ Row 1 │
├──────────┼─────────┼──────────┤
│ column00 │ varchar │ 結衣 │
│ column01 │ int64 │ 4789 │
│ column02 │ int64 │ 4789 │
│ column03 │ int64 │ 10620 │
│ column04 │ varchar │ 結衣 │
│ column05 │ varchar │ 名詞 │
│ column06 │ varchar │ 固有名詞 │
│ column07 │ varchar │ 人名 │
│ column08 │ varchar │ 名 │
│ column09 │ varchar │ * │
│ column10 │ varchar │ * │
│ column11 │ varchar │ ユイ │
│ column12 │ varchar │ 結衣 │
│ column13 │ varchar │ * │
│ column14 │ varchar │ A │
│ column15 │ varchar │ * │
│ column16 │ varchar │ * │
│ column17 │ varchar │ * │
│ column18 │ varchar │ * │
└──────────┴─────────┴──────────┘
-
column05
が「名詞」 -
column06
が「固有名詞」 -
column07
が「人名」 -
column08
が「名」
になっています。人名リストのほうは column08
が「名」であるものを抽出すればよさそうです。
D .row
D SELECT column00, column11 FROM '*.csv' WHERE column08 = '名';
┌──────────────┬────────────────┐
│ column00 │ column11 │
│ varchar │ varchar │
├──────────────┼────────────────┤
│ fujioka │ フジオカ │
│ jingbo │ jingbo │
│ katsu │ カツ │
│ koo │ コー │
│ lu zhonglian │ チュウレン │
│ mitsu │ ミツ │
│ masahiro │ マサヒロ │
│ mongjun │ ムジュン │
│ seiji │ セイジ │
│ voildemort │ ヴォルデモート │
│ あいな │ アイナ │
│ あいの │ アイノ │
│ あいみ │ アイミ │
│ あいら │ アイラ │
│ あい佳 │ アイカ │
│ あい実 │ アイミ │
│ あい梨 │ アイリ │
│ あい音 │ アイネ │
│ あい香 │ アイカ │
│ あおこ │ アオコ │
│ · │ · │
│ · │ · │
│ · │ · │
│ 龍逢 │ リュウホウ │
│ 龍郎 │ タツロウ │
│ 龍門 │ リュウモン │
│ 龍雄 │ タツオ │
│ 龍雲 │ リュウウン │
│ 龍音 │ リュウオン │
│ 龍顔 │ リュウガン │
│ 龍馬 │ リョウマ │
│ 龍鳳 │ リュウホウ │
│ 龍麿 │ タツマロ │
│ 龜吉 │ カメキチ │
│ 龜太郎 │ カメタロウ │
│ 龜夫 │ カメオ │
│ 龜松 │ カメマツ │
│ 龜藏 │ カメゾウ │
│ 龝良 │ アキヨシ │
│ 隆三 │ リュウゾウ │
│ 凞 │ ヒロシ │
│ 神楽 │ カグラ │
│ 敏郞 │ トシロウ │
├──────────────┴────────────────┤
│ 149333 rows (40 shown) │
└───────────────────────────────┘
よさそうですね。
部分文字列の判定
「名の読み」が「姓の読み」の接頭辞になっている(「姓の読み」が「名の読み」から始まる)、という条件はどうすればいいでしょうか?
https://duckdb.org/docs/sql/functions/char を見てみると starts_with(string, search_string)
という関数があることがわかります。これをつかいましょう。
試しに「ユイ」から始まる地名を抽出してみます。
D SELECT column00, column11 FROM '*.csv' WHERE column07 = '地名' AND starts_with(column11, 'ユイ');
┌──────────────┬──────────────────────┐
│ column00 │ column11 │
│ varchar │ varchar │
├──────────────┼──────────────────────┤
│ ゆいの杜 │ ユイノモリ │
│ ゆいの杜中央 │ ユイノモリチュウオウ │
│ ゆいの杜東 │ ユイノモリヒガシ │
│ ゆいの杜西 │ ユイノモリニシ │
│ 柚井 │ ユイ │
│ 油井 │ ユイ │
│ 油井ケ島 │ ユイガシマ │
│ 油池 │ ユイケ │
│ 涌井 │ ユイ │
│ 湯井 │ ユイ │
│ 湯日 │ ユイ │
│ 由比ケ丘 │ ユイガオカ │
│ 由比今宿 │ ユイイマジュク │
│ 由比入山 │ ユイイリヤマ │
│ 由比北田 │ ユイキタダ │
│ 由比寺尾 │ ユイテラオ │
│ 由比東倉澤 │ ユイヒガシクラサワ │
│ 由比東山寺 │ ユイヒガシヤマデラ │
│ 由比町 │ ユイマチ │
│ 由比町屋原 │ ユイマチヤハラ │
│ 由比西倉澤 │ ユイニシクラサワ │
│ 由比西山寺 │ ユイニシヤマデラ │
│ 由比阿僧 │ ユイアソウ │
│ 油井ヶ島沼 │ ユイガシマヌマ │
│ 油井小島 │ ユイコジマ │
│ 油井川 │ ユイガワ │
│ 湯日川 │ ユイガワ │
│ 由井 │ ユイ │
│ 由比ヶ丘 │ ユイガオカ │
│ 由比川 │ ユイガワ │
│ ゆいがはま │ ユイガハマ │
│ ユイスト │ ユイスト │
│ 由比 │ ユイ │
│ 由比ガ浜 │ ユイガハマ │
│ 由比ケ浜 │ ユイガハマ │
│ 由比ヶ浜 │ ユイガハマ │
│ 由比浜 │ ユイガハマ │
├──────────────┴──────────────────────┤
│ 37 rows 2 columns │
└─────────────────────────────────────┘
いい感じです。
「由比ヶ浜結衣」を探す
それでは、これまで見てきた部品を組み合わせてクエリを組み立てましょう。
SELECT
地名.column00, 名.column00, 地名.column11, 名.column11
FROM
'*.csv' AS 地名, '*.csv' AS 名
WHERE
地名.column07 = '地名'
AND
名.column08 = '名'
AND
starts_with(地名.column11, 名.column11);
これで終わりです!簡単ですね。ただ、このクエリは地名と名のすべての組み合わせを見るわけで、けっこう時間がかかります。.timer on
を使って実行時間を計測してみると、私のPCでは80秒弱かかりました。消費メモリは最大で2GBくらいのようです。待っていれば結果が出るのはすごいですね。
D .timer on
D SELECT
地名.column00, 名.column00, 地名.column11, 名.column11
FROM
'*.csv' AS 地名, '*.csv' AS 名
WHERE
地名.column07 = '地名'
AND
名.column08 = '名'
AND
starts_with(地名.column11, 名.column11);
100% ▕████████████████████████████████████████████████████████████▏
┌──────────────────────────────────────┬──────────┬────────────────────────────────────────────────────────────────────────────┬────────────┐
│ column00 │ column00 │ column11 │ column11 │
│ varchar │ varchar │ varchar │ varchar │
├──────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────────────────────┼────────────┤
│ 富士岡 │ fujioka │ フジオカ │ フジオカ │
│ 藤岡口 │ fujioka │ フジオカクチ │ フジオカ │
│ 藤岡奥 │ fujioka │ フジオカオク │ フジオカ │
│ 藤岡市 │ fujioka │ フジオカシ │ フジオカ │
│ 藤岡市三ツ木 │ fujioka │ フジオカシミツギ │ フジオカ │
│ 藤岡市三本木 │ fujioka │ フジオカシサンボギ │ フジオカ │
│ 藤岡市三波川 │ fujioka │ フジオカシサンバガワ │ フジオカ │
│ 藤岡市上大塚 │ fujioka │ フジオカシカミオオヅカ │ フジオカ │
│ 藤岡市上戸塚 │ fujioka │ フジオカシカミトヅカ │ フジオカ │
│ 藤岡市上日野 │ fujioka │ フジオカシカミヒノ │ フジオカ │
│ 藤岡市上栗須 │ fujioka │ フジオカシカミクリス │ フジオカ │
│ 藤岡市上落合 │ fujioka │ フジオカシカミオチアイ │ フジオカ │
│ 藤岡市下大塚 │ fujioka │ フジオカシシモオオヅカ │ フジオカ │
│ 藤岡市下戸塚 │ fujioka │ フジオカシシモトヅカ │ フジオカ │
│ 藤岡市下日野 │ fujioka │ フジオカシシモヒノ │ フジオカ │
│ 藤岡市下栗須 │ fujioka │ フジオカシシモクリス │ フジオカ │
│ 藤岡市中 │ fujioka │ フジオカシナカ │ フジオカ │
│ 藤岡市中大塚 │ fujioka │ フジオカシナカオオヅカ │ フジオカ │
│ 藤岡市中島 │ fujioka │ フジオカシナカジマ │ フジオカ │
│ 藤岡市中栗須 │ fujioka │ フジオカシナカクリス │ フジオカ │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ 竜ヶ石 │ 龍 │ リュウガシ │ リュウ │
│ 竜北 │ 龍 │ リュウホク │ リュウ │
│ 竜地 │ 龍 │ リュウジ │ リュウ │
│ 竜川 │ 龍 │ リュウセン │ リュウ │
│ 竜江 │ 龍 │ リュウコウ │ リュウ │
│ 竜洋 │ 龍 │ リュウヨウ │ リュウ │
│ 竜王 │ 龍 │ リュウオウ │ リュウ │
│ りゅうきゅう │ 龍 │ リュウキュウ │ リュウ │
│ 竜地 │ 龍二 │ リュウジ │ リュウジ │
│ 竜地 │ 龍司 │ リュウジ │ リュウジ │
│ 竜江 │ 龍子 │ リュウコウ │ リュウコ │
│ 竜江 │ 龍宏 │ リュウコウ │ リュウコウ │
│ 竜地 │ 龍次 │ リュウジ │ リュウジ │
│ 竜地 │ 龍治 │ リュウジ │ リュウジ │
│ 辰巳 │ 龍美 │ タツミ │ タツミ │
│ 辰巳台西 │ 龍美 │ タツミダイニシ │ タツミ │
│ 広島三育学院高等学校中学校大和小学校 │ 凞 │ ヒロシマサンイクガクインコウトウガッコウチュウガッコウダイワショウガッコウ │ ヒロシ │
│ 広島平野 │ 凞 │ ヒロシマヘイヤ │ ヒロシ │
│ 広島都市圏 │ 凞 │ ヒロシマトシケン │ ヒロシ │
│ 広柴川 │ 凞 │ ヒロシバガワ │ ヒロシ │
├──────────────────────────────────────┴──────────┴────────────────────────────────────────────────────────────────────────────┴────────────┤
│ 12033669 rows (40 shown) 4 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Run Time (s): real 79.419 user 934.674003 sys 1.212205
結果も大体意図通り...でしょうか。色々な発見がありますね。
「由比ヶ浜結衣」を探してみましょう。WHERE
句に条件を足してみます。
D .timer on
D SELECT
地名.column00, 名.column00, 地名.column11, 名.column11
FROM
'*.csv' AS 地名, '*.csv' AS 名
WHERE
地名.column07 = '地名'
AND
名.column08 = '名'
AND
starts_with(地名.column11, 名.column11)
AND
地名.column00 = '由比ヶ浜';
┌──────────┬──────────┬────────────┬──────────┐
│ column00 │ column00 │ column11 │ column11 │
│ varchar │ varchar │ varchar │ varchar │
├──────────┼──────────┼────────────┼──────────┤
│ 由比ヶ浜 │ 佑依 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 佑唯 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 佑泉 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 佑生 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 佑維 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 侑唯 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 侑衣 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優以 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優依 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優偉 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優唯 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優惟 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優意 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優維 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優郁 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 友伊 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 友依 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 友唯 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 友惟 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 友維 │ ユイガハマ │ ユイ │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ 由比ヶ浜 │ 釉生 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 侑生 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 友彪 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 由 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 由唯 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 結 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 羽 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 諭委 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ ゆい │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ ユイ │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 佑衣 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 優衣 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 唯 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 瑜 │ ユイガハマ │ ユ │
│ 由比ヶ浜 │ 由依 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 由比 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 由衣 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 結以 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 結依 │ ユイガハマ │ ユイ │
│ 由比ヶ浜 │ 結衣 │ ユイガハマ │ ユイ │
├──────────┴──────────┴────────────┴──────────┤
│ 106 rows (40 shown) 4 columns │
└─────────────────────────────────────────────┘
Run Time (s): real 0.712 user 1.495268 sys 0.564565
こちらは一瞬で結果が返ってきました。
│ 由比ヶ浜 │ 結衣 │ ユイガハマ │ ユイ │
確かに居ますね!
「雪ノ下雪乃」も探してみましょう。
D SELECT
地名.column00, 名.column00, 地名.column11, 名.column11
FROM
'*.csv' AS 地名, '*.csv' AS 名
WHERE
地名.column07 = '地名'
AND
名.column08 = '名'
AND
starts_with(地名.column11, 名.column11)
AND
地名.column00 = '雪ノ下';
┌──────────┬──────────┬────────────┬──────────┐
│ column00 │ column00 │ column11 │ column11 │
│ varchar │ varchar │ varchar │ varchar │
├──────────┼──────────┼────────────┼──────────┤
│ 雪ノ下 │ ゆきの │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ ゆき乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ ゆき野 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 佑季 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 佑季乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 佑希乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 佑紀乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 佑貴乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 侑 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 侑喜 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑城 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑姫 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑季 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑希 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑樹 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑生 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑紀 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 侑輝 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 優喜 │ ユキノシタ │ ユキ │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ 雪ノ下 │ 由姫 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由季 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由岐 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由希 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由枝 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由樹 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由紀 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由紀乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 由記 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由貴 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 由起 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 祐季 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 結生 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 裕季 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 裕貴 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 遊亀 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 雪 │ ユキノシタ │ ユキ │
│ 雪ノ下 │ 雪乃 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 雪之 │ ユキノシタ │ ユキノ │
│ 雪ノ下 │ 雪野 │ ユキノシタ │ ユキノ │
├──────────┴──────────┴────────────┴──────────┤
│ 249 rows (40 shown) 4 columns │
└─────────────────────────────────────────────┘
Run Time (s): real 0.636 user 1.437770 sys 0.510966
こちらも一瞬です。
│ 雪ノ下 │ 雪乃 │ ユキノシタ │ ユキノ │
居ますね。やりました。
おまけ
たとえば、「亭」が入っている名前を探したい、というような場合もお手の物です。
D SELECT
地名.column00, 名.column00, 地名.column11, 名.column11
FROM
'*.csv' AS 地名, '*.csv' AS 名
WHERE
地名.column07 = '地名'
AND
名.column08 = '名'
AND
starts_with(地名.column11, 名.column11)
AND
地名.column00 LIKE '%亭%';
┌──────────────────────────┬──────────┬────────────────────────────────────────────────┬────────────┐
│ column00 │ column00 │ column11 │ column11 │
│ varchar │ varchar │ varchar │ varchar │
├──────────────────────────┼──────────┼────────────────────────────────────────────────┼────────────┤
│ 清華亭 │ せいか │ セイカテイ │ セイカ │
│ 清閑亭 │ せいか │ セイカンテイ │ セイカ │
│ 九亭 │ きゅう │ キュウテイ │ キュウ │
│ 陶然亭 │ とう │ トウゼンテイ │ トウ │
│ 山本亭 │ やま │ ヤマモトテイ │ ヤマ │
│ 清流亭 │ 世竜 │ セイリュウテイ │ セイリュウ │
│ 清流亭 │ 世龍 │ セイリュウテイ │ セイリュウ │
│ 清華亭 │ 世霞 │ セイカテイ │ セイカ │
│ 清閑亭 │ 世霞 │ セイカンテイ │ セイカ │
│ 福岡市友泉亭 │ 二九雄 │ フクオカシユウセンテイ │ フクオ │
│ 福岡市城南区友泉亭 │ 二九雄 │ フクオカシジョウナンクユウセンテイ │ フクオ │
│ 福岡県友泉亭 │ 二九雄 │ フクオカケンユウセンテイ │ フクオ │
│ 福岡県城南区友泉亭 │ 二九雄 │ フクオカケンジョウナンクユウセンテイ │ フクオ │
│ 福岡県福岡市友泉亭 │ 二九雄 │ フクオカケンフクオカシユウセンテイ │ フクオ │
│ 福岡県福岡市城南区友泉亭 │ 二九雄 │ フクオカケンフクオカシジョウナンクユウセンテイ │ フクオ │
│ 愛晩亭 │ 亜伊 │ アイバンテイ │ アイ │
│ 愛晩亭 │ 亜位 │ アイバンテイ │ アイ │
│ 愛晩亭 │ 亜唯 │ アイバンテイ │ アイ │
│ 愛晩亭 │ 亜惟 │ アイバンテイ │ アイ │
│ 愛晩亭 │ 亜異 │ アイバンテイ │ アイ │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ · │ · │ · │ · │
│ 新亭 │ 進二 │ シンジョン │ シンジ │
│ 新亭ネゴリ │ 進二 │ シンジョンネゴリ │ シンジ │
│ 松亭 │ 遜 │ ソンジョン │ ソン │
│ 陶然亭 │ 鐙 │ トウゼンテイ │ トウ │
│ 城南区友泉亭 │ 錠 │ ジョウナンクユウセンテイ │ ジョウ │
│ 擁翠亭 │ 陽 │ ヨウスイテイ │ ヨウ │
│ 擁翠亭 │ 陽水 │ ヨウスイテイ │ ヨウスイ │
│ 友泉亭 │ 雄 │ ユウセンテイ │ ユウ │
│ 新亭 │ 震 │ シンジョン │ シン │
│ 新亭ネゴリ │ 震 │ シンジョンネゴリ │ シン │
│ 清流亭 │ 青流 │ セイリュウテイ │ セイリュウ │
│ 清流亭 │ 静 │ セイリュウテイ │ セイ │
│ 清華亭 │ 青花 │ セイカテイ │ セイカ │
│ 清華亭 │ 静 │ セイカテイ │ セイ │
│ 清閑亭 │ 青花 │ セイカンテイ │ セイカ │
│ 清閑亭 │ 静 │ セイカンテイ │ セイ │
│ 軒亭口 │ 顕 │ ケンテイコウ │ ケン │
│ 軒亭口 │ 顯庭 │ ケンテイコウ │ ケンテイ │
│ 行形亭 │ 食其 │ イキナリヤ │ イキ │
│ 後亭 │ 鴻 │ コウテイ │ コウ │
├──────────────────────────┴──────────┴────────────────────────────────────────────────┴────────────┤
│ 1131 rows (40 shown) 4 columns │
└───────────────────────────────────────────────────────────────────────────────────────────────────┘
結果の全件を眺めてみたり、色々条件を変えたりして、あなたも素敵な名前を探してみてください。
まとめ
DuckDBをつかって、「由比ヶ浜結衣」のような「姓が地名で、名の読みが姓の読みの接頭辞になっている」という構造をもつ人名を抽出する例を示しました。
DuckDBは高速に反応してくれるので、このようなアドホックな分析を行う際にも快適に使うことができます。
Discussion