月末になると、販売管理・勤怠・在庫のCSVを集め、表計算ソフトで集計する仕事が発生します。1行抜けた、同じ伝票が2回入った、金額列に文字が混ざった、といった小さな崩れは集計後まで見つからないことがあります。
機密情報を含むCSVを、用途の分からないオンライン変換サイトへ渡すのも避けたいところです。ブラウザには、利用者が選んだローカルファイルを読み取るFile APIがあります[2]。静的なHTMLとJavaScriptだけでも、ファイルをサーバーへ送らず、その場で検査結果を作れます。
この記事では、月次CSVを外部送信せずに点検する最小設計を、欠損・重複・日付・数値・IQR・前期間比較の順に整理します。目的はデータを自動修正することではなく、人が集計を確定する前に「確認すべき行」を狭めることです。
「ブラウザだけ」の処理境界を決める
最小構成のデータフローは次の形です。
CSVを選択
→ ブラウザのメモリへ読み込む
→ 文字コードを指定してデコードする
→ CSVを行・列へ解析する
→ ルールを順番に実行する
→ 件数表と確認対象CSVを端末へ保存する
ここにサーバーやデータベースは必要ありません。ただし、「ブラウザで開く」ことと「通信しない」ことは同義ではありません。外部CDNやアクセス解析を使わず、開発者ツールでネットワーク要求が発生しないことまで確認します。
文字コードも明示します。Encoding StandardではTextDecoderの既定がUTF-8で、Shift_JIS用デコーダーも定義されています[3]。利用者が文字コードを選び、デコード失敗時は止めます。
単純な「カンマで分割」では、引用符内のカンマや改行を扱えません。RFC 4180が文書化した共通形式に沿って解析し[1]、列数が途中で変わる行は書式エラーとして返します。
月次業務で先に固定するもの
チェックを始める前に、「どの列が何を表すか」を業務側で決めます。たとえば売上CSVなら、次のような定義です。
| 列 | 役割 | 例 |
|---|---|---|
sales_date | 売上日。必須 | 2026-07-01 |
slip_id | 伝票を識別するキー。必須 | S-10482 |
store_id | 店舗コード | TOKYO-01 |
item_id | 商品コード | ITEM-204 |
quantity | 数量。整数 | 3 |
amount | 金額。整数または小数 | 2980 |
「1行が伝票か商品明細か」で重複の意味は変わります。必須列、キー列、日付列、数値列は自動推測せず設定し、ルールの版番号も結果へ残します。
欠損と重複を分けて数える
欠損はゼロと区別する
空欄、空白だけの文字列、列自体の不足を欠損候補として数えます。数量0や金額0は欠損ではありません。ゼロを許さない場合は、別の許容範囲ルールで警告します。
列ごとの件数と行番号を出し、slip_idの欠損はエラー、備考の欠損は情報、と重要度を分けます。
重複は業務キーで見る
重複には、全列が同じ完全重複と、業務上同じ対象を指すキー重複があります。売上明細ならslip_id + item_id、勤怠ならemployee_id + work_dateの組み合わせが候補です。
キーが同じでも、返品や訂正として正しい場合があります。重複行は自動削除せず、同じキーの行を並べた要確認リストにします。
日付と数値は厳密に解釈する
日付は形式と実在性を確認します。YYYY-MM-DDでも、存在しない日付は受け付けません。未来日、対象月外の日付、日付ごとの行数も表示すれば、期間の抽出漏れを探せます。
数値列は、次を別々に記録します。
- 数値として解釈できない文字列
- 空欄
- 業務上許可されない負数
- 小数を許可しない列の小数
- 設定した最小値・最大値の外側
桁区切りや全角数字を正規化しても、raw_valueとnormalized_valueを残します。負数は返品を表す場合があるため、業務ルールなしに異常と断定しません。
IQRは「外れ候補」を見つけるルール
数値の極端な値を探す簡単な方法が四分位範囲(IQR)です。値を小さい順に並べ、25パーセンタイルをQ1、75パーセンタイルをQ3とすると、IQRは次の差です。
IQR = Q3 - Q1
下側の境界 = Q1 - 1.5 × IQR
上側の境界 = Q3 + 1.5 × IQR
NISTも、この境界を外れ値候補の識別に使う方法と、除外前に発生理由を調べる必要性を説明しています[4]。境界外の値は、大口注文や返品など重要な出来事かもしれません。
全店舗・全商品をまとめず、店舗、商品、曜日など意味の近いグループで計算します。件数が少ない、またはIQRが0なら「判定材料不足」とします。
ただし、最初の試作ではファイル全体のIQRから始めても構いません。その場合は「全体を基準にした候補」であることを明示し、商品構成や店舗規模が大きく違うデータでは過検出が起きる前提で人が確認します。
この処理はAIではありません。決めた式を同じ入力へ適用すれば、毎回同じ結果になる統計ルールです。異常検知入門で扱う学習型の異常検知とは、正常範囲の作り方が異なります。
前月比較は件数と品質を並べる
単月だけでは、数値が通常範囲か判断しにくいことがあります。前月や前年同月と、少なくとも次を並べます。
| 指標 | 確認できること |
|---|---|
| 行数・営業日数 | 抽出漏れ、対象期間の違い |
| 金額・数量の合計 | 全体規模の変化 |
| 1日あたり・1件あたりの値 | 月の日数差を除いた変化 |
| 欠損率・重複候補数 | データ作成工程の劣化 |
| ゼロ・負数・IQR候補数 | 特殊処理や入力傾向の変化 |
| 新規・消失した店舗や商品 | マスタ変更、抽出条件の違い |
実数差と増減率を併記し、前期間が0なら率は「算出不可」とします。営業日、曜日、セール条件も違うため、大きな差だけで誤りとは断定しません。
将来予測へ進む場合も、この比較が土台になります。時系列予測の実務で説明したように、時間順序を無視した検証や、季節性を見ない比較は判断を誤らせます。まずは「前月と違う理由を現場が説明できるか」を確認します。
ルールベースとAIを混同しない
今回のチェックは、説明可能な条件が中心です。
| 観点 | ルールベースのCSVチェック | AI・機械学習 |
|---|---|---|
| 判断 | 必須列、重複キー、範囲、IQR | 過去データから複雑な傾向を学習 |
| 再現性 | 同じ入力・設定なら同じ結果 | モデルと推論条件に依存 |
| 根拠 | どのルールに違反したか示せる | スコアの解釈が別途必要な場合がある |
| 得意 | 既知の不備を漏れなく列挙 | 単純な式にしにくいパターンの候補抽出 |
| 限界 | 未定義の不備は見つけない | 誤検知・見逃しと評価データが必要 |
欠損や日付形式は先にルールで確認し、単純な式にできない傾向が残ったときだけ学習手法を検討します。AIを追加する場合も、評価指標と人が確認できる件数を先に決めます。設計手順はモデル評価設計入門と同じです。
月次運用に組み込む
チェックツールだけでは、元データの問題は直りません。月次業務には次の順で組み込みます。
- 基幹システムから出した元CSVを変更せず保存する
- 対象月、文字コード、列の役割、業務キーを選ぶ
- チェックを実行し、概要件数と確認対象を出す
- エラーは元システムまたは抽出処理で修正する
- 警告は担当者が理由を記録し、採用・除外を決める
- 再度チェックし、エラーが解消した版を集計へ渡す
- 前期間との差とルール版を月次記録へ残す
確認対象にはrow_number、rule_id、column、raw_value、severity、messageを持たせます。元CSVを上書きせず、元データと指摘を分けることで再実行できます。
まとめ
- ブラウザのFile APIを使えば、利用者が選んだCSVを端末内で処理できる
- CSVは引用符内のカンマ・改行を扱えるパーサーで読み、文字コードも明示する
- 欠損、重複、日付、数値は別ルールにし、元の値を保持する
- IQRが示すのは外れ候補であり、入力ミスや業務異常の断定ではない
- 前月比較は合計だけでなく、件数、営業日、欠損率、対象マスタの変化も並べる
- 既知の品質条件はAIより先にルールで確認し、修正と承認は人が行う
最初の一歩は、毎月使っているCSVについて「必須列」「重複を判断するキー」「許可する負数」の3点を書き出すことです。ルールが言葉になれば、月次チェックを再現可能な手順へ変えられます。
参考文献・一次情報
- [1]STANDARDRFC 4180 — Common Format and MIME Type for Comma-Separated Values (CSV) Files
引用符、改行、区切り文字を含むCSVフィールドの共通形式とtext/csvの登録
- [2]
- [3]
- [4]