0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

nlp4j-local-searchで国交省の自動車不具合情報を検索・分析する ― ニッサンで相対的に多い故障装置を探す (Python)

0
Last updated at Posted at 2026-09-13

nlp4j-local-searchで国交省の自動車不具合情報を検索・分析する ― ニッサンで相対的に多い故障装置を探す (Python)

はじめに

nlp4j-local-search は、Pythonから Apache Lucene をローカルに利用できる検索ライブラリです。

Version 0.6.1.1 では、次のような対話型CLIも利用できます。

nlp4j-local-search --lang ja

検索サーバーを別途立ち上げる必要はなく、

JSONL
  ↓
nlp4j-local-search
  ↓
Apache Lucene

という形で、ローカルのJSONLデータをそのまま検索・分析できます。

今回は、国土交通省の自動車不具合情報を加工したサンプルデータを使って、

  1. データをロードする
  2. 「ニッサン」に関する文書を検索する
  3. malfunction_device_s を集計する
  4. 全体と比較して、相対的に頻度が高い故障装置を探す
  5. 気になった故障装置に絞って再検索する

という流れを試します。

単純な全文検索だけではなく、

検索結果の特徴を見つけ、その特徴を使ってさらに検索する

という使い方の例です。


使用するデータ

今回のサンプルデータはこちらです。

JSONL:

https://nlp4j-2.sakura.ne.jp/data/mlit/mlit_202501-202512.jsonl

gzip圧縮版:

https://nlp4j-2.sakura.ne.jp/data/mlit/mlit_202501-202512.jsonl.gz

今回はgzip版を使います。

wget https://nlp4j-2.sakura.ne.jp/data/mlit/mlit_202501-202512.jsonl.gz

nlp4j-local-search.jsonl.gz を直接読み込めるため、展開する必要はありません。


インストール

Version 0.6.1.1 を使います。

pip install -q nlp4j-local-search==0.6.1.1

CLIを起動します。

nlp4j-local-search --lang ja

すると対話モードになります。

nlp4j-local-search
Language: ja
Auto analyze: False
Type 'help' or '?' for help.

>>

今回は日本語データなので、

--lang ja

を指定しています。


データをロードする

まず、国交省データを読み込みます。

>> load("mlit_202501-202512.jsonl.gz")

今回のデータでは、次のように約2,800件が読み込まれます。

Loaded 2,782 documents in 0.98 seconds (2,834 docs/sec).

これでApache Luceneのインデックスが作成され、検索可能になります。


データの例

JSONLの1行は、例えば次のようになっています。

{
  "id": "2025-12-31_1",
  "date": "2025-12-31",
  "address_s": "大阪府",
  "via_s": "HP",
  "maker_s": "ニッサン",
  "registration_s": "2018/09",
  "type_s": "DAA-GFC27",
  "name_s": "セレナ",
  "odo_meter_s": "85,305 Km",
  "engine_type_s": "MR20-SM24",
  "malfunction_device_s": "燃料装置",
  "event_date_s": "",
  "text_ja": "ニッサン セレナ 燃料装置 インジェクターの故障により、エンジン警告ランプが点灯し、馬力不足になった。"
}

text_ja は日本語全文検索用のフィールドです。

一方、

maker_s
malfunction_device_s
name_s
address_s

などは、文字列をそのまま扱うKeywordフィールドです。


まず「ニッサン」を検索する

通常の全文検索から始めます。

>> search("text_ja:ニッサン")

例えば次のような結果が得られます。

[2025-07-29_1195] score=1.2078
ニッサン スカイライン その他 エアコンの温度調整が出来ない。

[2025-07-18_1276] score=1.2078
ニッサン セレナ エンジン 交差点でエンストした。

[2025-01-17_2672] score=1.2078
ニッサン ROOX エンジン 運転中、ノッキングすることがある。

...

この検索では420件の文書が該当しました。

しかし、420件を一件ずつ読んでいくのは大変です。

そこで次に、

ニッサンの不具合情報では、どの故障装置が全体と比較して多いのか?

を見てみます。


view() で故障装置を分析する

malfunction_device_s を、

text_ja:ニッサン

に該当する文書だけで集計してみます。

>> view("malfunction_device_s","text_ja:ニッサン")

結果は次のようになりました。

View: malfunction_device_s
Lucene query: text_ja:ニッサン
Matched documents: 420 / 2,782
Values are ordered by relative rate.

Rank  Value                   Count  All Count  Relative Rate
----  -------------------- -------- ---------- --------------
   1  電動機(モーター)                  26         65          2.65x
   2  緩衝装置                       25         66          2.51x
   3  燃料装置                       35        122          1.90x
   4  制動装置                       83        292          1.88x
   5  その他                        45        229          1.30x
   6  動力伝達                       47        277          1.12x
   7  非装置                         1          6          1.10x
   8  電気装置                       21        149          0.93x
   9  排ガス・騒音                     8         65          0.82x
  10  かじ取り                       11         92          0.79x

ここで注目したいのが、

電動機(モーター)

です。


Relative Rateとは

今回、

電動機(モーター)

は、

ニッサン検索結果: 26件 / 420件
全データ:         65件 / 2,782件

でした。

nlp4j-local-searchview() では、この比率を比較してRelative Rateを計算します。

概念的には、

ニッサン文書での出現率
------------------------
全データでの出現率

です。

今回の場合、

(26 / 420) / (65 / 2782)

となり、約、

2.65x

です。

つまり、

「電動機(モーター)」という故障装置は、データ全体と比較すると、ニッサンに関する文書では約2.65倍の割合で現れている

と読めます。

単純な件数だけを見ると、

制動装置 83件

の方が多いですが、Relative Rateを見ることで、

そのメーカーに特有、あるいは相対的に特徴的な項目は何か

という観点からデータを見ることができます。


なぜ「電動機(モーター)」が多いのか?

この結果を見ると、

電動機(モーター)  2.65x

という値は少し興味深く見えます。

ニッサンは、

  • e-POWER
  • EV

など、電動モーターを駆動に利用する車種を比較的多く販売しています。

そのため、

ニッサン車では、他メーカーと比較して「電動機(モーター)」という故障装置分類が出やすいのではないか

という仮説は考えられます。

ただし、このデータだけから、

e-POWERやEVだから故障が多い

と結論づけることはできません。

Relative Rateが示しているのは、あくまで、

今回の不具合情報データの中で、その分類が相対的に多く現れている

という事実です。

車種構成、販売台数、登録台数、報告のされ方なども考慮する必要があります。

したがって、この結果は因果関係の証明ではなく、

次に詳しく調べるべき対象を見つけるための手がかり

として扱うのが適切です。


実際に「電動機(モーター)」で絞り込む

気になるカテゴリが見つかったので、今度はその文書を実際に検索します。

今回の値には、

(
)

が含まれています。

Lucene Query Parserでは括弧は特殊文字なので、そのまま、

malfunction_device_s:電動機(モーター)

と書くと、意図したKeyword検索になりません。

今回は次のように検索できます。

>> search('text_ja:ニッサン AND malfunction_device_s:""電動機(モーター)""')

これで、

ニッサン
AND
故障装置 = 電動機(モーター)

という条件で検索できます。


特殊文字をエスケープする方法もある

Lucene Query Syntaxとして括弧をエスケープする方法もあります。

>> search("text_ja:ニッサン AND malfunction_device_s:電動機\(モーター\)")

この方法でも検索できます。

このように、Lucene Query Syntaxをそのまま利用できるため、

全文検索
+
Keywordフィールド
+
AND条件

を一つのクエリで表現できます。


「検索 → 分析 → 再検索」

今回の操作で面白いのは、この流れです。

search("text_ja:ニッサン")
        ↓
ニッサンの文書を取得
        ↓
view("malfunction_device_s", "text_ja:ニッサン")
        ↓
特徴的な故障装置を発見
        ↓
電動機(モーター) = 2.65x
        ↓
search(
  ニッサン
  AND
  電動機(モーター)
)
        ↓
実際の文書を確認

最初から、

電動機(モーター)

を検索しようと思っていたわけではありません。

まずデータを検索し、

view()

で特徴を確認し、

そこから新しい検索条件を見つけています。

これは、全文検索エンジンを単なる「文書検索」だけではなく、

テキストデータを探索するための道具

として使う例だと思います。


件数だけでは分からないこと

例えば今回、

制動装置

はニッサン文書で83件あります。

一方、

電動機(モーター)

は26件です。

単純な件数だけなら、

83 > 26

なので制動装置の方が目立ちます。

しかしデータ全体では、

制動装置          292件
電動機(モーター)    65件

です。

全体の分布を考慮すると、

電動機(モーター)  2.65x
制動装置          1.88x

となります。

このようにRelative Rateを見ることで、

件数が多い項目

と、

その検索条件に対して特徴的な項目

を分けて見ることができます。


Luceneをローカル分析にも使う

Apache Luceneというと、

検索キーワード
  ↓
検索結果一覧

という使い方をイメージしがちです。

しかし、検索結果に対して集計を組み合わせると、

検索
  ↓
部分集合
  ↓
フィールド集計
  ↓
全体との比較
  ↓
特徴発見

という使い方もできます。

nlp4j-local-search ではこれを、

search()
view()

というシンプルなCLIで試せるようにしています。


サーバーを立てなくてもLuceneを試せる

従来、このような検索・集計を試そうとすると、

  • Elasticsearch
  • OpenSearch
  • Apache Solr

などをインストールしたり、検索サーバーを起動したりする構成が一般的でした。

これらは非常に強力ですが、ローカルのJSONLを少し分析したいだけなら、もっと小さな構成でも十分な場合があります。

nlp4j-local-search では、

pip install nlp4j-local-search

して、

nlp4j-local-search --lang ja

を起動するだけです。

あとは、

load(...)
search(...)
view(...)

でLuceneを利用できます。


今回のコマンドまとめ

インストール

pip install -q nlp4j-local-search==0.6.1.1

データ取得

wget https://nlp4j-2.sakura.ne.jp/data/mlit/mlit_202501-202512.jsonl.gz

CLI起動

nlp4j-local-search --lang ja

データロード

>> load("mlit_202501-202512.jsonl.gz")

ニッサンを検索

>> search("text_ja:ニッサン")

故障装置を分析

>> view("malfunction_device_s","text_ja:ニッサン")

電動機(モーター)でさらに絞り込む

>> search('text_ja:ニッサン AND malfunction_device_s:""電動機(モーター)""')

または、

>> search("text_ja:ニッサン AND malfunction_device_s:電動機\(モーター\)")

まとめ

今回は国土交通省の自動車不具合情報を使って、

検索
↓
特徴分析
↓
再検索

という流れを試しました。

ニッサンに関する420件を分析すると、

電動機(モーター)

は、

26 / 420

件。

全体では、

65 / 2,782

件でした。

その結果、Relative Rateは、

2.65x

となりました。

これは、

ニッサンに関する文書では、「電動機(モーター)」という分類がデータ全体より相対的に多い

ことを示しています。

e-POWERやEVなど、ニッサンの商品構成との関連は考えられそうですが、このデータだけで因果関係を結論づけることはできません。

むしろ重要なのは、

検索結果から「気になる特徴」を発見し、それを次の検索につなげられる

という点です。

nlp4j-local-search では、Apache Luceneをローカルで利用しながら、

search()
view()

だけで、このような探索を手軽に試すことができます。


Links

PyPI

https://pypi.org/project/nlp4j-local-search/0.6.1.1/

GitHub

https://github.com/oyahiroki/nlp4j-local-search

MLIT sample data (JSONL)

https://nlp4j-2.sakura.ne.jp/data/mlit/mlit_202501-202512.jsonl

MLIT sample data (gzip)

https://nlp4j-2.sakura.ne.jp/data/mlit/mlit_202501-202512.jsonl.gz

Qiita tags

Python
Lucene
全文検索
NLP4J
データ分析
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?