はじめに
不動産収益試算CLI revenue-kun を作っています。
GitHub:
https://github.com/signal-yield/revenue-kun
revenue-kun は、不動産の直接還元法ベースで、NOIや収益試算値を確認するための研究・検証用CLIです。鑑定評価、投資助言、法律助言、実務判断の代替を目的としたものではありません。
今回、v0.4.0 / v0.4.1 で、レントロールPDFの読み取りまわりを少し固めました。
この記事では、その中でも特に地味だけど重要だった次の2点について書きます。
-
入居者名や入居日を status column と誤認しない -
合計/小計/TOTALなどの summary row を賃貸区画行として読まない
派手なAI機能の話ではなく、PDF表抽出で起きる地味な事故をどう防いだか、という実装ログです。
背景:レントロールPDFは「表」に見えるが、そのまま読めない
レントロールは、人間が見ると普通の表です。
例えば、以下のような列が並びます。
- 区画番号
- 用途
- 面積
- 賃料
- 共益費
- 入居者名
- 入居日
- 契約満了日
- ステータス
人間なら、どれが賃料で、どれが入居状況で、どれが集計行かを文脈で判断できます。
しかし、PDFから機械的に表を抽出すると、そう簡単ではありません。
特に問題になったのは、次の2つです。
問題1:入居者名 を status column と誤認する
レントロールには、入居状況を表す列があります。
例えば、
ステータス
入居中
空室
募集中
満室
のような列です。
一方で、別の列として以下のような列もあります。
入居者名
入居者
入居日
契約満了日
これらは status column ではありません。
しかし、単純に「入居」という文字列を含む列を status column 候補にしてしまうと、入居者名 や 入居日 を status column と誤認する可能性があります。
これはかなり危険です。
なぜなら、入居・空室の判定は、その後の収益試算に影響するからです。
対応:status column の判定を deny-set で守る
v0.4.0 では、次のような列名を status column と誤認しないようにしました。
入居者名
入居者
入居日
契約満了日
逆に、ステータス のように明示的な status column がある場合は、それを正しく認識するようにしています。
また v0.4.1 では、この挙動を regression test として固定しました。
確認対象にした status value は以下です。
入居中
空室
募集中
満室
ここで重要なのは、「列名」と「値」を混同しないことです。
入居者名 は列名としては status column ではありません。
一方で、入居中 は status value として扱うべきです。
この違いをテストで固定しました。
問題2:合計 行を賃貸区画として読んでしまう
もう一つの問題は、summary row です。
レントロールの末尾には、次のような行がよく出ます。
合計
合 計
合 計
小計
総計
計
TOTAL
subtotal
これらは賃貸区画ではありません。
集計行です。
ところが、PDFから表を抽出した後に、行単位で処理していると、これらの集計行を通常の区画行として扱ってしまうことがあります。
その結果、以下のような事故が起きます。
- 区画数が増える
- 賃料合計が二重計上される
- monthly GPI が膨らむ
- 空室・入居数の集計がずれる
収益試算では、これはかなりまずいです。
対応:summary row filtering を追加
v0.4.0 では、summary row を区画行から除外する処理を追加しました。
対象にした表記は以下です。
合計
合 計
合 計
小計
総計
計
TOTAL
subtotal
v0.4.1 では、これらの回帰テストを追加しました。
特に 合 計 は全角スペース入りです。
日本語PDFでは、半角スペース・全角スペース・文字間スペースの揺れが出ることがあります。
そのため、合計 だけでなく 合 計 や 合 計 も明示的にテスト対象にしました。
ただし、強く除外しすぎても危険
summary row filtering には、別の危険があります。
それは、計 という文字が含まれているだけで、通常の区画行まで除外してしまうことです。
例えば、普通のテキストや備考欄に 計 が含まれているケースがあります。
計画棟101
合計算
あるいは、room field 以外の通常フィールドに 計 が含まれる場合もあります。
このような行は、summary row ではありません。
そのため v0.4.1 では、false-positive guard も追加しました。
つまり、
- summary row は除外する
- しかし、通常行に
計が含まれるだけでは除外しない
という挙動をテストで固定しています。
GPIへの影響もテストした
今回の修正では、単に「行が落ちるかどうか」だけでなく、monthly GPI への影響も確認しました。
summary row が混入すると、賃料合計が過大計上されます。
そこで、v0.4.1 では、
summary row が monthly GPI を膨らませない
ことを regression test として追加しました。
この手のツールでは、抽出処理の小さな誤読が、最終的な試算値にそのまま波及します。
そのため、PDF parsing のテストだけでなく、試算値への影響も見る必要があります。
v0.4.1 の結果
v0.4.1 では、以下を実施しました。
- stale CLI wording の修正
- summary row filtering regression test の追加
-
合 計のような全角スペース表記の確認 -
計を含む通常行を誤除外しない false-positive guard の追加 - summary row が monthly GPI を膨らませない regression test の追加
- status column detection / normalization regression test の追加
テスト結果は以下です。
161 passed, 0 failed
リリースはこちらです。
まだやっていないこと
重要なので、明示しておきます。
revenue-kun は現時点で、以下を主張しません。
- real-world PDF verified
- 実務PDF検証済み
- OCR対応
- スキャンPDF対応
- 鑑定評価
- 投資助言
- 法律助言
- 実務判断の代替
v0.4.1 は、あくまで PDF ingestion 周辺の regression hardening です。
実務PDFに対する追加検証は、qualifying real-world text-based rent roll PDF が入手できてから行う予定です。
まとめ
PDF表抽出では、人間には当たり前に見えるものが、プログラムには当たり前ではありません。
今回の修正で特に重要だったのは、次の2点です。
-
入居者名や入居日を status column と誤認しない -
合計/小計/TOTALなどの summary row を区画行として読まない
さらに、除外ルールを強くしすぎて、通常行まで落とさないように false-positive guard も入れました。
地味ですが、収益試算の前処理としてはかなり重要な部分です。
revenue-kun はまだ研究・検証用CLIですが、こうした小さな誤読を一つずつ潰しながら、不動産実務の確認作業を補助するツールとして育てていきます。