要点

  • コロラド州のBoulder Countyとトライカウンティは同じ56項目の検査フォームを使っているのに、違反件数は2.65倍違う。Boulderの検査官はフォームの58%を未記入のまま残し、トライカウンティの形式では「未確認」を記録できない。
  • Marin Countyの1検査あたり違反件数は1年で74%下落した。検査官も対象レストランも同じで、データ移行では説明がつかない。
  • レストランと年を統制した後でも、どの検査官が訪問するかによって件数は平均値の172%分動く。
  • 違反件数が意味を持つのは、1つの管轄、1つの時代、1人の検査官の内部に限られる。そのいずれをまたいだ比較も成立しない。

米国の保健当局はどこもレストランの検査結果を公表しており、食事する店を選ぶその瞬間にそれを目の前に出そうとするアプリが次々と現れてきた。前提にあるのは、違反件数が厨房について何かを教えてくれるという考えだ。

私はいくつかの管轄を比較して、基準が郡ごとにどれほど違うのかを見たかった。ところが分かったのは、その比較はそもそも成り立たないということであり、その理由のほうが比較結果よりも面白かった。

以下はすべて稼働中の公開APIから得たものだ。コードはこちらにあり、標準ライブラリだけで、APIキーなしに、すべての数値を再生成できる。

2つの郡、同じフォーム、2.65倍の開き

Boulder Countyとトライカウンティ(Adams、Arapahoe、Douglas)はどちらもコロラド州のオープンデータポータルに公表しており、どちらも同じ56項目のFDAフードコード・チェックリストを運用している。同じ測定器具、同じ違反コードFC01からFC56、同じ州だ。

両者のデータセットが重なる2019年から2022年10月までの定期検査:

  1検査あたり違反件数 n
Boulder County 2.10 1,984
トライカウンティ 5.57 7,886

最初に思ったのは、トライカウンティのほうが厳しいということだった。データもそう見えた。トライカウンティは3郡をカバーする単一の機関であり、これは地理と規制当局を切り分けてくれる。そしてその内部で3郡は5.83、5.36、5.54に並ぶ。1つの機関の下では、2本の郡境をまたいでも開きは約9%だ。機関をまたぐと165%になる。

次にレストランを固定した。Subwayはどこでも Subway だ。同じ企業手順、同じ設備、同じ監査体制である。

チェーン Boulder トライカウンティ
Subway 2.42 4.41
Starbucks 0.65 2.18
Chipotle 0.69 1.94
McDonald’s 1.47 3.11
Taco Bell 1.00 3.36
Wendy’s 0.11 4.47
合算 1.15 3.16

9チェーン、9つすべてが同じ方向を向き、合算で2.76倍。この時点で私は、隣り合うコロラドの2つの保健当局の間に執行上の実質的な差があると確信していた。

その数字は分数であり、私が持っていたのは分子だけだった

Boulderはチェックリスト項目ごとに1行を公表し、各行にステータスが付いている。トライカウンティは1検査につき1行を、56個の二値フラグとともに公表している。

違いは、それぞれの形式が何を表現できるかにある。

検査官が記録した内容 Boulder トライカウンティ
指摘あり Out, Out-High, Out-Medium, Out-Low flag = 1
確認して問題なし In 区別不能
確認していない Not Observed 区別不能
該当しない Not Applicable 区別不能

Boulderは「確認したが問題なかった」と「これは一度も確認していない」を言い分けられる。トライカウンティの形式は両方をゼロに潰してしまう。

そこで、Boulderの検査官が実際にフォームのどれだけを評価しているかを数えた。

  フォームの項目数 評価された項目数 違反件数 評価項目あたりの割合
Boulder 56.8 24.1 2.10 8.7%
トライカウンティ 56 知りえない 5.57 56項目すべてとすれば9.9%

Boulderの検査官はフォームの58%に手をつけていない。実際に確認された分で割ると、2.65倍は約1.14倍になる。

それでも残差を過大に見せている。トライカウンティの分母は復元できないからだ。仮に彼らの検査官も24項目程度を評価しているなら、真の割合はおよそ23%で、これはBoulderの2倍以上であり、効果の符号が反転する。Boulderの割合には上下の境界がある。トライカウンティにはない。

メリーランド州Montgomery Countyは同じ3値の語彙を持つ15項目のフォームを運用しており、Boulderが58%を「Not Observed」と記す場面で、記すのは項目の2%から6%だ。正規化のよりどころとなる全国的な慣行は存在せず、まさにそれゆえに、公表件数を比較する人にはこの問題が見えない。

同じ問題は時間軸上にも現れる

記録の慣行が動くと数字が動くのなら、ある管轄が記録の仕方を変えたときには、その管轄の内部でも数字は動くはずだ。

カリフォルニア州Marin Countyは12年分の検査結果を公表している。年別の、定期検査1件あたり違反件数:

Marin Countyの年別・定期検査1件あたり違反件数と、2019年前後の同一8名の検査官 左:系列は2019年で断絶し、二度と戻らない。右:断絶の両側で働いた検査官は全員が低下している。

2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025
4.08 3.73 4.97 5.02 3.63 1.42 1.21 0.74 0.95 0.93 1.01 1.07

1つの年の境目をまたいで4.30から1.11へ。 同じ期間に検査件数はむしろ増えており、2018年の定期検査1,351件から2019年には1,514件になっている。違反コードの語彙は変わっていない。掲示プログラムは2015年からすでに運用されていた。

Marinはすべての行に検査官名を記している。これをやっている管轄はほとんどない。おかげで職員が入れ替わったかどうかを確認できた。断絶の両側で定期検査を40件以上行った検査官:

検査官 2019年以前 2019+ 変化
A 7.90 1.42 −6.48
B 5.17 1.27 −3.90
C 4.32 1.10 −3.22
D 3.89 2.09 −1.79
E 3.60 0.91 −2.68
F 2.65 0.90 −1.75
G 1.43 0.81 −0.62
H 1.02 0.93 −0.09

8人中8人が低下。合算で−69%。検査官Aは1人の人間が1つの仕事をしているだけなのに、1検査あたり7.90件から1.42件になっている。

そしてレストランを固定すると、断絶の両側で検査を受けた1,059の事業者は4.58から1.11へ動いた。

同じ人。同じレストラン。同じコード。違反は4分の1。

実際に変わったものは、検査がどう分類されたかに見える。何も見つからなかった割合はほとんど動かず、11〜16%から13〜26%へ。重大と分類された割合は23〜39%から8〜15%へ落ち、その差を軽微が吸収し、違反のあった検査1件あたりに列挙された違反数は約4.1〜5.8から1.1〜2.1へ下がった。検査が問題を見つける確率はほぼ横ばいのままだ。1検査あたりに書き留められた問題の数が崩落した。

データ移行を見ているのではないかの確認

この話を潰しうる説明は来歴だ。2019年以前の行が別のシステムから出てきて移行されたものなら、断絶は実務ではなくデータセットの産物ということになる。

3つの検証、いずれも否定的だった。

レコードIDが連続している。 13年すべてにわたって単調に進む1本の連番であり、境界で範囲が重なっている。2018年は25,039から37,081、2019年は24,518から42,338。再スタートも欠落もない。

スキーマが動かない。 inspector、placard、correct_by_date、corrected_on_site、inspector_comments、inspection_frequency、license_number はすべて2014年から2026年までのどの年でも充足率100%だ。変化する唯一のフィールドは違反コードで、96〜97%から67〜90%へ動くが、これはスキーマ変更ではなく今回の発見そのものである。

抽出処理の指紋は別の場所で変わっている。 このデータセットの一部の文字列値はリテラルの引用符で囲まれている。この産物は2024年までの行では0%、2025年では83%、2026年では100%に現れる。

これが本稿で最も強い証拠だ。パイプラインは明らかに変わったが、それは2019年ではなく2025年である。74%の下落が移行によるものだったなら、書式上の署名も一緒に動いていたはずだ。

これは私が最初に踏んだバグの原因でもあった。引用符を取り除かずに検査官でグループ化すると46人になる。実際は40人だ。うち6人は同一人物が、引用符付きと無しで2回現れているだけである。

Marinのような断絶はどれくらい一般的か

ここで妥当な反論は、私が不連続を探しに行って見つけただけであり、保健当局は書類を絶えず改訂しているというものだ。そこで、他の長期系列3つを同じやり方で調べた。

管轄 指標 期間 最大の年次変動
コロラド州Boulder County 定期検査1件あたり違反件数 2013-2025 13年で1.60から2.35、断絶なし
シカゴ 不合格となった検査の割合 2010-2026 16.0%から24.9%、緩やかな漂移、断絶なし
ニューヨーク市 重大と分類された違反の割合 2022-2026 52.4%から56.7%、断絶なし

Marinが外れ値だ。Boulderはより長い期間にわたる同じ指標なのできれいな比較対象になり、前年比で約20%を超えて動くことは一度もない。

この表には2つの留保がある。シカゴの合否とニューヨーク市の重大割合は違反件数より粗い指標であり、当局がどれだけ細かく列挙するかを変えても、どちらも動かないことがありうる。またニューヨーク市の公表系列は2022年までしかさかのぼれず、検証と呼ぶには心もとない。

まとめると、Marinのような断絶はこのデータの通常の姿ではないが、無視してよいほど稀でもない。長期系列を持つ4つの管轄のうち1つに存在し、しかも公表データの中にそれを告げるものは何もない。

このことはコロラドの比較も補強する。Boulderが13年間横ばいだということは、2.65倍の差のうちBoulder側は、私がたまたま選んだ年の産物ではないということだ。

誰が来るかは、どのレストランかとほぼ同じくらい予測力がある

シカゴは検査優先順位付けモデルをオープンソース化しており、独立したレビューは、影響の最大の単一要因は誰が検査を実施したかであることを見いだした。それは内部データだった。Marinの検査官列は、それを公開の場で検証可能にする。

15,888件の定期検査、1,645の事業者、40人の検査官にわたって、検査官ごとの生の平均は0.74から5.99まで広がる。その大半は時代の効果だ。検査官は異なる期間に働いており、2019年の断絶がその真ん中に位置しているからである。

そこで、2人以上の異なる検査官が検査した1,453の事業者を使って事業者平均を引き、続いて年平均を引いた。

統制 検査官間の開き sd
生データ 8.1倍 1.41
事業者平均を差し引き 5.18件 1.27
事業者と年を差し引き 3.81件、平均2.22の172% 0.86

年を統制すると順位が入れ替わる。これが純粋な時代効果という説明を排除する。統制後に最も厳しい検査官は2025年に着任しており、断絶の緩い側にいる。最も緩い検査官は2018〜2019年に働いており、厳しい側にいた。

生の系列における粗い分散の寄与:事業者の識別が約24%、検査官の識別が約21%。

これはフィットさせたモデルではなく算術的な平均差し引きなので、標準誤差ではなく方向と大きさとして扱ってほしい。検査官と年は部分的に共線であり、断絶をまたぐ8人の検査官が識別を担っている。他の2つの発見にはこの問題がない。厳密な統制の下での生の平均だからだ。

ここから見えてくるもの

3つの軸があり、件数はそのすべてで破綻する。管轄をまたぐと、記録の慣行ひとつで2.65倍動く。時間をまたぐと、同じ人が同じレストランを検査しているのに74%動く。検査官をまたぐと、統制後でも平均の172%動く。

これらは検査が機能しているかどうかを測るものではない。検査官は実在の問題を見つけ、実在の厨房を閉鎖しており、本稿はそのどちらの側についても何も語らない。私が測ったのは数字であり、その数字はまさに一方と他方を比べるときに破綻する。そして下流の誰もが、それにやっていることはその比較だけなのだ。

本当のリスクは検索アプリの下流にある。違反の結果で訓練された都市の予測モデルや、地域間あるいは政策実施日をまたいで格付け制度を比較する研究だ。シカゴのモデルはこの種の結果で訓練され、自前の監査で検査官が最上位の予測因子だと判明した。目的変数の一部が事務的な産物であるなら、それは予想どおりの結果である。ある管轄自身の記録方式変更をまたぐ研究は、Marinの問題に直撃する。世界が静止しているのに系列が動いてしまうからだ。

実用的な言い方をすれば、違反件数を解釈できるのは、1つの管轄の内部で、1つの時代において、誰が訪問したかを調整したうえでのことだ。それ以外の場所ではできない。このデータの上に何かを作るなら、最初に確認すべきは数字ではなく、出典が「未確認」を表現できるかどうか、そしてその慣行が対象期間を通じて静止していたかどうかである。

これはレストランに固有の話ではまったくない。公表された件数は、ある機関が何を書き留めたかを記録したものであり、私が見た4つの当局のうち1つは、何も告げずに書き留め方を変えていた。

2019年にMarin Countyで何が変わったのかをご存じなら、ぜひ教えてほしい。本稿を更新する。ここにある数字はすべてコードから稼働中のAPIに対して再生成できるので、私の作業を検証してほしい。