[小ネタ]DuckDBに郵便番号データを読み込ませてみた

[小ネタ]DuckDBに郵便番号データを読み込ませてみた

DuckDBに郵便番号データのCSVファイルをインポートしてみました。データを理解する際に最適なツールです。
Clock Icon2025.05.11

はじめに

データ事業本部の藤川です。
データ分析のためにDuckDBを頻繁に使うため、備忘録としてブログにまとめておきます。
データを理解するための探索的データ解析(EDA; Exploratory Data Analysis)のフェーズでは、データ構造が分からない場合も多いです。取り込むデータの構造が分からない状態でも、DuckDBに取り込んでから解析できるため非常に便利です。

ここでは、日本郵便様提供の郵便番号データDuckDBにロードしてみました。

やってみた

DuckDBを単独で使用することもありますが、DataFrameに読み直す等、別の処理を行うと思います。他のツールとの連携を考慮し、私はmiseDuckDBをインストールしています。

DuckDBをインストール

  1. 最初にmiseをインストールします。miseについて、こちらのブログが詳しいです。

    $ brew install mise
    
  2. 作業用ディレクトリを作成し、miseDuckDBをインストールします。

    $ mkdir work && cd work
    $ mise trust
    $ mise install duckdb@latest
    $ mise use duckdb@latest
    
  3. 動作確認します。

    $ duckdb --version
    

郵便番号データをダウンロード

  1. 最もデータ利活用しやすい住所の郵便番号(1レコード1行、UTF-8形式)ファイルをダウンロードし、解凍します。今回使用するCSVファイルのエンコーディングはUTF-8ですが、他のデータではiconv等を使用して、エンコーディングを変換してください。

    $ wget https://www.post.japanpost.jp/zipcode/dl/utf/zip/utf_ken_all.zip
    $ unzip utf_ken_all.zip
    $ rm utf_ken_all.zip
    

郵便番号データをDuckDBにロード

  1. 郵便番号データをDuckDBでロードしてみます。コンソールに出力されるだけです。

    $ duckdb -c "SELECT * FROM 'utf_ken_all.csv';"
    
  2. SELECT句をCTASに変更し、ロードしてみます。テーブルを作成するため、データベースファイルを作成します。郵便番号データはカラム順が決まっているため問題ありませんが、他のCSVファイルではカラム順について注意が必要な場合があります。

    $ duckdb zipcode.duckdb
    
    CREATE TABLE zipcode_nohead AS FROM 'utf_ken_all.csv';
    
    SELECT * FROM zipcode_nohead WHERE column02 like '108%' LIMIT 3;
    
    $ duckdb zipcode.duckdb
    v1.2.2 7c039464e4
    Enter ".help" for usage hints.
    D CREATE TABLE zipcode_nohead AS FROM 'utf_ken_all.csv';
    D SELECT * FROM zipcode_nohead WHERE column02 like '108%' LIMIT 3;
    ┌──────────┬──────────┬──────────┬──────────────┬──────────┬──────────────────────┬───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
    │ column00 │ column01 │ column02 │   column03   │ column04 │       column05       │ … │ column09 │ column10 │ column11 │ column12 │ column13 │ column14 │
    │ varchar  │ varchar  │ varchar  │   varchar    │ varchar  │       varchar        │   │  int64   │  int64   │  int64   │  int64   │  int64   │  int64   │
    ├──────────┼──────────┼──────────┼──────────────┼──────────┼──────────────────────┼───┼──────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
    │ 13103    │ 108      │ 1080022  │ トウキョウト │ ミナトク │ カイガン(3チョウ…  │ … │        1 │        0 │        1 │        0 │        0 │        0 │
    │ 13103    │ 108      │ 1080075  │ トウキョウト │ ミナトク │ コウナン(ツギノビ…  │ … │        0 │        0 │        1 │        0 │        0 │        0 │
    │ 13103    │ 108      │ 1086090  │ トウキョウト │ ミナトク │ コウナンシナガワイ…  │ … │        0 │        0 │        0 │        0 │        0 │        0 │
    ├──────────┴──────────┴──────────┴──────────────┴──────────┴──────────────────────┴───┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┤
    │ 3 rows                                                                                                                          15 columns (12 shown) │
    └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    
  3. 郵便番号データにはヘッダーがないため、郵便番号データ(1レコード1行、UTF-8形式)の説明を参考に、カラム名を定義します。DuckDBは日本語カラム名も扱えますが、他のDBやツールと連携する際に英語カラム名も併記しておくと、良いかもしれません。

    CREATE TABLE zipcode (
        "全国地方公共団体コード" VARCHAR,
        "旧郵便番号" VARCHAR,
        "郵便番号" VARCHAR,
        "都道府県名【カナ】" VARCHAR,
        "市区町村名【カナ】" VARCHAR,
        "町域名【カナ】" VARCHAR,
        "都道府県名" VARCHAR,
        "市区町村名" VARCHAR,
        "町域名" VARCHAR,
        "一町域が二以上の郵便番号で表される場合の表示" TINYINT,
        "小字毎に番地が起番されている町域の表示" TINYINT,
        "丁目を有する町域の場合の表示" TINYINT,
        "一つの郵便番号で二以上の町域を表す場合の表示" TINYINT,
        "更新の表示" TINYINT,
        "変更理由" TINYINT
    );
    COPY zipcode FROM 'utf_ken_all.csv';
    
    SELECT * FROM zipcode WHERE 郵便番号 like '108%' LIMIT 3;
    
    D SELECT * FROM zipcode WHERE 郵便番号 like '108%' LIMIT 3;
    ┌──────────────────────┬────────────┬──────────┬────────────────────┬───┬──────────────────────┬──────────────────────┬────────────┬──────────┐
    │ 全国地方公共団体コ…  │ 旧郵便番号 │ 郵便番号 │ 都道府県名【カナ】 │ … │ 丁目を有する町域の…  │ 一つの郵便番号で二…  │ 更新の表示 │ 変更理由 │
    │       varchar        │  varchar   │ varchar  │      varchar       │   │         int8         │         int8         │    int8    │   int8   │
    ├──────────────────────┼────────────┼──────────┼────────────────────┼───┼──────────────────────┼──────────────────────┼────────────┼──────────┤
    │ 13103                │ 108        │ 1080022  │ トウキョウト       │ … │                    1 │                    0 │          0 │        0 │
    │ 13103                │ 108        │ 1080075  │ トウキョウト       │ … │                    1 │                    0 │          0 │        0 │
    │ 13103                │ 108        │ 1086090  │ トウキョウト       │ … │                    0 │                    0 │          0 │        0 │
    ├──────────────────────┴────────────┴──────────┴────────────────────┴───┴──────────────────────┴──────────────────────┴────────────┴──────────┤
    │ 3 rows                                                                                                                 15 columns (8 shown) │
    └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    

さいごに

ご覧の通り、簡単にデータ分析に着手できることが分かりました。
当初は小ネタのつもりでしたが、思ったよりも長くなりました。どなたかのお役に立てれば幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.