予防接種法に基づく医療機関からの副反応疑い報告状況についてのPDFからCSV変換~前処理

github.com

予防接種法に基づく医療機関からの副反応疑い報告状況について

https://www.mhlw.go.jp/content/10906000/000784435.pdf

github.com

explode は便利

インストール

apt install python3-tk ghostscript
pip install camelot-py[cv]

wget https://www.mhlw.go.jp/content/10906000/000784435.pdf -O data.pdf

CSVに変換

import camelot
import pandas as pd

tables = camelot.read_pdf("data.pdf", pages="2-end", split_text=True)

dfs = [table.df for table in tables]

df = pd.concat(dfs)

df.to_csv("data.csv", encoding="utf_8_sig", index=False, header=False)

前処理

import re
import pandas as pd

!wget https://raw.githubusercontent.com/imabari/covid19-data/master/vaccine/data.csv -O data.csv

df0 = pd.read_csv("data.csv", dtype="object").fillna("")

df0.info()

df0.columns = df0.columns.str.replace("\n", "")

df0["No"] = df0["No"].str.replace("※[1-9]", "").str.strip().astype(int)

df0["年齢"] = df0["年齢"].str.rstrip("歳")
df0["年齢"] = df0["年齢"].mask(df0["年齢"] == "").astype(float).astype("Int64")

df0["性別"] = df0["性別"].replace({"": "不明"})

"""# 整然データ

かのえ/Pattie/柿人 さんのコードを参考にさせていただきました

https://twitter.com/kanoekakihito/status/1397222333505486849

https://github.com/kanoekakihito/tidy_mhlw_data/blob/main/20210523_%E6%96%B0%E5%9E%8B%E3%82%B3%E3%83%AD%E3%83%8A%E3%83%AF%E3%82%AF%E3%83%81%E3%83%B3%E5%89%AF%E5%8F%8D%E5%BF%9CCSV%E6%95%B4%E5%BD%A2.py
"""

df1 = df0.copy()

df1["症状名(PT名)"] = df1["症状名(PT名)"].apply(lambda s: [i.replace("\n", "").strip() for i in re.split("(?<=[))]\n)", s)])
df1["発生日"] = df1["発生日"].str.split()
df1["転帰日"] = df1["転帰日"].str.split()
df1["転帰内容"] = df1["転帰内容"].str.split()

dfs = []

for i, row in df1.iterrows():
    dfs.append(row.apply(pd.Series).T.fillna(method="ffill"))

df2 = pd.concat(dfs).reset_index(drop=True)

df3 = df2["症状名(PT名)"].str.extract("(.+)[((](.+?)[))]").rename(columns={0:"症状名", 1:"PT名"})
df3["PT名"] = df3["PT名"].str.split("|")

df4 = df2.join(df3).explode("PT名")

df4["症状名"] = df4["症状名"].str.strip()
df4["PT名"] = df4["PT名"].str.strip()

df4["No"] = df2["No"].astype(int)
df4["年齢"] = df2["年齢"].astype("Int64")

df4.info()

df4

df4.to_csv("output.csv", index=False, encoding="utf_8_sig")

"""# ダウンロード"""

files.download("output.csv")

"""# 症状別報告件数"""

df4["症状"] = df4["症状名"] + "(" + df4["PT名"] + ")"

df4["症状"].value_counts()

"""# 集計確認"""

df1 = df0.copy()
df1.set_index("No", inplace=True)

"""## アナフィラキシー"""

df1["症状名(PT名)"].str.contains("アナフィラキシー").sum()

"""## 性別"""

# 性別 副反応疑い報告数
df1["性別"].value_counts()

# 性別 重篤報告数
df1.loc[df1["重篤度(報告医評価)"] == "重い", "性別"].value_counts()

# 性別 死亡報告数
df1.loc[df1["転帰内容"].str.contains("死亡"), "性別"].value_counts()

"""## 年齢別"""

labels = [
    "0~9歳",
    "10~19歳",
    "20~29歳",
    "30~39歳",
    "40~49歳",
    "50~59歳",
    "60~69歳",
    "70~79歳",
    "80歳以上",
]

df1["年代"] = pd.cut(
    df1["年齢"],
    [0, 10, 20, 30, 40, 50, 60, 70, 80, 120],
    include_lowest=True,
    right=False,
    labels=labels,
).astype(str)

df1["年代"] = df1["年代"].mask(df1["年齢"].isnull(), "不明")

# 年齢別副反応疑い報告数
df1["年代"].value_counts().reindex(labels + ["不明"]).fillna(0).astype(int)

# 年齢別重篤報告数
df1.loc[df1["重篤度(報告医評価)"] == "重い", "年代"].value_counts().reindex(labels + ["不明"]).fillna(0).astype(int)

# 年齢別死亡報告数
df1.loc[df1["転帰内容"].str.contains("死亡"), "年代"].value_counts().reindex(labels + ["不明"]).fillna(0).astype(int)