この記事を読んだら分かること
- 感染症発生動向(NESID)の概要と取得方法
- 感染症発生動向のCSVデータをPower Query/Power BIを使って整形・可視化する方法
感染症発生動向調査(NESID)とは
感染症発生動向調査(NESID: National Epidemiological Surveillance of Infectious Diseases)として、全国の医療機関・検査機関から報告される感染症データが収集・集計されています。厚生労働省および国立感染症研究所が運用しており、この取り組みによってインフルエンザ、感染性胃腸炎、手足口病、COVID-19 など、多数の感染症の発生動向をモニタリングすることができます。
調査は「全数把握」と「定点把握」の2種類に分類されます。
全数把握の仕組みと対象疾患
全数把握は、患者が1名でも確認されれば必ず報告される方式です。名前のとおり全てが報告されるため、全国の発生状況について網羅的に把握できます。
1類感染症~5類感染と呼ばれる感染症が対象となっており、代表例は以下の通りです。
| 類型 | 概要 | 代表的な感染症(例) |
|---|---|---|
| 1類感染症 | 感染力・重篤性が 極めて高い 感染症。直ちに保健所への届出が必要。 | ・エボラ出血熱 ・クリミア・コンゴ出血熱 ・痘そう(天然痘) ・南米出血熱 ・ペスト ・マールブルグ病 ・ラッサ熱 |
| 2類感染症 | 重篤かつ集団発生のリスクが高い感染症。早期対応が必要。 | ・急性灰白髄炎(ポリオ) ・結核 ・ジフテリア ・重症急性呼吸器症候群(SARS) ・中東呼吸器症候群(MERS) ・鳥インフルエンザ(H5N1、H7N9) |
| 3類感染症 | 主に 食中毒など経口感染 経路が中心の感染症。届出義務あり。 | ・コレラ ・細菌性赤痢 ・腸管出血性大腸菌感染症 ・腸チフス ・パラチフス |
| 4類感染症 | 動物・媒介生物(蚊・ダニ等)を介する感染症など多様な病原体。 | ・E型肝炎 ・A型肝炎 ・黄熱 ・Q熱 ・狂犬病 など |
| 5類感染症 | 日常的に発生する一般的な感染症。「7日以内」の届出が基本。 | ・アメーバ赤痢 ・ウイルス性肝炎(E型・A型以外) ・急性脳炎 ・後天性免疫不全症候群(AIDS) ・百日咳 ・麻しん(はしか) ・風しん など |
定点把握の仕組みと対象疾患
定点把握は指定された医療機関のみが報告する方式です。統計的に代表性を持ったデータとなります。
代表例は以下の通りです。
| 分類 | 概要 | 定点把握対象疾患(例) |
|---|---|---|
| インフルエンザ/COVID-19 定点(急性呼吸器感染症) | 主要な呼吸器感染症の動向を把握 | ・インフルエンザ ・新型コロナウイルス感染症 ・急性呼吸器感染症(一般的な呼吸器感染) |
| 小児科定点 | 子どもに多い感染症を中心に把握 | ・RSウイルス感染症 ・咽頭結膜熱(プール熱) ・A群溶血性レンサ球菌咽頭炎 ・感染性胃腸炎(ノロ・ロタ等) ・水痘 など |
| 眼科定点 | 目の感染症の発生状況を監視 | ・急性出血性結膜炎 ・流行性角結膜炎 |
| 性感染症定点 | 性感染症の動向を継続観察 | ・性器クラミジア感染症 ・性器ヘルペスウイルス感染症 ・尖圭コンジローマ ・淋菌感染症 |
| 基幹定点/その他 | 月報対象として別枠で報告される疾患もあり | ・クラミジア肺炎 ・RSウイルス以外の感染性胃腸炎(病原体指定型)など |
NESIDオープンデータとして公開されている情報
感染症発生動向調査のデータは、インターネット上で誰でも無料で取得できるオープンデータとして公開されています。公開されているデータには患者情報 と病原体情報 があります。
-
患者情報(IDWR:Infectious Diseases Weekly Report)
感染症法に基づき報告された患者数・流行状況をまとめ、週1回公表されます。 -
病原体情報(IASR:Infectious Agents Surveillance Report)
検査機関から報告された病原体(ウイルス・細菌など)の検出状況をまとめ、月1回公表されます。
データは厚生労働省のHPからCSV形式で簡単にダウンロードできます。
データの特性上、NESIDオープンデータには以下のようなメリットがあり、企業・研究者による二次利用が進んでいます。
- 公的データのため信頼性が高い
- CSVのため、様々なツールで分析可能
- 時系列分析や地域別分析が可能
今回はNESIDオープンデータを使って、インフルエンザの感染数に関するダッシュボードをPower BIで作成してみます。
Power BIでNESIDデータを取り込む手順
今回の分析では、IDWR速報データ 2025年第47週 の「定点把握疾患(週報告)、(1週から当該週まで)報告数・定点当たり報告数」のファイルを使用しました。
Power BIのデスクトップアプリはこちらからダウンロードできます。
CSVデータをPower BIに読み込む
CSVファイルをダウンロードしたら、まずはPower BIにデータを取り込みます。「データを取得」>「テキスト/CSV」でダウンロードしたファイルを選択。
CSVファイルの内容が表示されたら、「データの変換」 をクリック
画像のようにCSVファイルが表示されたら取り込みは完了です。
Power Queryによる前処理
ダウンロードしたCSVのままだとグラフ化が難しいため、データの前処理を行います。今回は手順が複雑なため、Mコードで処理を定義しました。ダウンロードしたCSVはヘッダー行が途中で分割されていたり、空行が含まれたりするため、List.PositionOfを使って動的にデータ開始位置を特定する処理などを入れています。
Mコード
Mコード(正式名称:Power Query Formula Language)は、Power Queryでデータ変換・整形を行うためのプログラミング言語
使用したMコードは以下になります。利用する場合は「詳細エディター」を開いてコードを入力し実行してください。
※ C:\Users\name\folder\2025-48-teiten-tougai.csv はご自身のファイルパスに書き換えたうえでご利用ください。
前処理用Mコード
let
Source = Csv.Document(
// ★適切なCSVパスに変更
File.Contents("C:\Users\name\folder\2025-48-teiten-tougai.csv"),
[Delimiter=",", Encoding=932, QuoteStyle=QuoteStyle.None]
),
// Column1 → 都道府県(1列目)
Renamed = Table.RenameColumns(Source, {{"Column1", "都道府県"}}),
Rows = Table.ToRows(Renamed),
ColNames = Table.ColumnNames(Renamed),
DiseaseName = "インフルエンザ",
// 「インフルエンザ」を含む行を探す
DiseaseIndex =
List.PositionOf(
List.Transform(Rows, (r) => List.AnyTrue(List.Transform(r, each _ <> null and Text.Contains(Text.From(_), DiseaseName)))),
true
),
// インフルエンザ行以降に限定
RowsAfterDisease = if DiseaseIndex >= 0 then List.Skip(Rows, DiseaseIndex) else Rows,
// インフルエンザブロック内の「01週」ヘッダー行(週行)を探す
HeaderInBlockIndex =
List.PositionOf(
List.Transform(RowsAfterDisease, each List.Contains(_, "01週")),
true
),
HeaderWeekIndex =
if DiseaseIndex >= 0 and HeaderInBlockIndex >= 0
then DiseaseIndex + HeaderInBlockIndex
else List.PositionOf(List.Transform(Rows, each List.Contains(_, "01週")), true),
// 次のブロック(次の「01週」)を探して、そこまでをインフルエンザとみなす
DataStartIndex = HeaderWeekIndex + 2,
NextHeaderOffset =
List.PositionOf(
List.Transform(List.Skip(Rows, DataStartIndex), each List.Contains(_, "01週")),
true
),
DataEndIndex =
if NextHeaderOffset = -1
then List.Count(Rows)
else DataStartIndex + NextHeaderOffset - 1,
DataRowCount = DataEndIndex - DataStartIndex + 1,
// インフルエンザの表本体だけをテーブル化(元の列数を維持)
InfluenzaDataTable =
Table.FromRows(
List.Range(Rows, DataStartIndex, DataRowCount),
ColNames
),
// 週行・指標行(報告/定当)
WeekRow = Rows{HeaderWeekIndex},
TypeRow = Rows{HeaderWeekIndex + 1},
// 週行の空欄をフィルダウン
FillDown =
(lst as list) as list =>
List.Accumulate(
lst,
[prev = null, out = {}],
(s, cur) =>
let
curText = if cur = null then "" else Text.Trim(Text.From(cur)),
nextPrev = if curText = "" then s[prev] else curText,
nextOut = s[out] & { nextPrev }
in
[prev = nextPrev, out = nextOut]
)[out],
WeekVals = FillDown(WeekRow),
TypeVals = List.Transform(TypeRow, each if _ = null then "" else Text.Trim(Text.From(_))),
// 列名:都道府県 / 01週_報告 / 01週_定当 ...
RawNames =
List.Transform(
List.Positions(WeekVals),
(i) =>
if i = 0 then
"都道府県"
else
let
w = WeekVals{i},
t = TypeVals{i},
w2 = if w = null or w = "" then "Col" & Text.From(i) else Text.From(w),
t2 = if t = null or t = "" then "Val" & Text.From(i) else Text.From(t)
in
w2 & "_" & t2
),
// 重複列名を一意化
MakeUnique =
(names as list) as list =>
List.Accumulate(
names,
[seen = {}, out = {}],
(state, current) =>
let
base = if current = null or current = "" then "Col" else Text.From(current),
cnt = List.Count(List.Select(state[seen], each _ = base)),
nm = if cnt = 0 then base else base & "." & Text.From(cnt),
st2 = [seen = state[seen] & {base}, out = state[out] & {nm}]
in
st2
)[out],
FinalNames = MakeUnique(RawNames),
// ヘッダー適用
WithHeaders = Table.FromColumns(Table.ToColumns(InfluenzaDataTable), FinalNames),
// 列のピボット解除
Unpivoted = Table.UnpivotOtherColumns(WithHeaders, {"都道府県"}, "属性", "値"),
// 属性(例: 01週_定当)→ 週 / 指標
SplitAttr = Table.SplitColumn(
Unpivoted,
"属性",
Splitter.SplitTextByDelimiter("_", QuoteStyle.None),
{"週", "指標"}
),
// 週番号(01週→1、総数→null)
AddWeekNum = Table.AddColumn(
SplitAttr,
"週番号",
each try Number.FromText(Text.Replace([週], "週", "")) otherwise null,
Int64.Type
),
// 年(固定:2025)
AddYear = Table.AddColumn(AddWeekNum, "年", each 2025, Int64.Type),
// 型(数値化できない値は null)
ChangedTypes =
Table.TransformColumns(
AddYear,
{
{"都道府県", each Text.From(_), type text},
{"週", each Text.From(_), type text},
{"指標", each Text.From(_), type text},
{"値", each try Number.From(_) otherwise null, type number},
{"週番号", each try Int64.From(_) otherwise null, Int64.Type},
{"年", each try Int64.From(_) otherwise null, Int64.Type}
}
)
in
ChangedTypes

コード変換が完了したら、左上の「閉じて適用」ボタンをクリックします。
感染症データの可視化(インフルエンザ定点報告の実例)
データの前処理が完了したので、ビジュアル化をしていきます。今回は以下の2つについて可視化を行います。
- 報告数の時系列変化(都道府県別)
- 地域別×週別のヒートマップ
報告数の時系列推移を折れ線グラフで可視化
まずは、報告数の時系列変化を見るための「折れ線グラフ」を作成します。以下の手順を実施すると折れ線グラフが表示されます。
- 視覚化のセクションで「折れ線グラフ」をクリック
- 「データ」セクションの 「週番号」 を「ビジュアルのビルド」のセクションのX軸にドラッグ&ドロップ
- 「データ」セクションの 「Σ値」 を「ビジュアルのビルド」のセクションのY軸にドラッグ&ドロップ
- 「データ」セクションの 「指標」 を 「このビジュアルでのフィルタ」 にドラッグ&ドロップし、「定当」のみチェック
- 「データ」セクションの 「都道府県」 を 「このビジュアルでのフィルタ」 にドラッグ&ドロップし、「東京」のみチェック
上記の折れ線グラフは東京におけるインフルエンザ感染数の推移を表示しています。台東区のHPで確認できたグラフ(赤線が2025年)と一致しており、適切にグラフ化できていることが分かります。
都道府県のフィルターを変更することで、都道府県別の推移が確認できます。以下は沖縄のグラフです。
地域別の流行ピークをヒートマップで可視化する
続いては、地域別×週別の報告数を直観的に把握できるヒートマップを作成していきます。PowerBIにはヒートマップは用意されていないため、「マトリックス」をベースに設定を行います。
-
視覚化のセクションで「マトリックス」をクリック
-
「ビジュアルのビルド」を以下のように設定
項目 フィールド 行 都道府県列 週番号値 値 -
「データ」セクションの 「指標」 を 「このビジュアルでのフィルタ」 にドラッグ&ドロップ
-
「データ」セクションの 「週」 を 「このビジュアルでのフィルタ」 にドラッグ&ドロップ
-
「このビジュアルでのフィルタ」の項目について、以下のように設定
フィールド 条件 指標 定当 週 ≠ 総数
(すべて選択 → 「総数」のみチェックを外す)週番号 空白ではない 都道府県 ≠ 都道府県名以外の値
(すべて選択 → 「都道府県名以外の値」はチェックを外す)
ここまでの設定で、以下のように都道府県と報告数のマトリックスが表示されます。
次に「ビジュアルのビルド」セクションの設定で、各セルに色を付けることでヒートマップにします。「値の合計▽」>「条件付き書式」>「背景色」から設定します。
以下の設定を行いました。
- 最小値のカラーに青を選択
- 「中間色を追加する」をチェックし、カラーとして黄色を選択
- 最大値のカラーに赤を選択
以上の設定により、ヒートマップが完成しました。
まとめ
このようにオープンデータ(NESID)とPower BIを活用することで、簡単に各地域の感染状況を可視化できました。医療資源の配分やリスクコミュニケーションに役立つダッシュボードに活用できそうですね。









