Magicode logo
Magicode
2 min read

文京区の保育施設における新型コロナ感染報告数(データ取得から可視化まで)

https://picsum.photos/seed/fc785d00c1474b41a7f1efecc6f77613/600/800
What this notebook does:
  • Retrieve coronavirus cases in daycares reported in the Bunkyo-ku (A ward in Tokyo, Japan) official website (https://www.city.bunkyo.lg.jp)
  • Parse into a dataframe
  • Visualize
  • Save as a CSV file
python
from datetime import datetime

currenttime = datetime.now()
print("As of:", currenttime)  # may be in UTF
As of: 2021-08-04 07:50:06.940375
python
from urllib.request import urlopen
from bs4 import BeautifulSoup as BS

src = urlopen("https://www.city.bunkyo.lg.jp/kyoiku/kosodate/okosan/nicchu/ninka/coronaoshirase.html").read()
soup = BS(src)

ts = soup.find_all("table")
def parse_table(t):
    ths = t.find_all("th")
    tds = [th.find_next("td") for th in ths]
    data = {th.text.strip():td.text.strip() for th,td in zip(ths,tds)}
    return data

x = [parse_table(t) for t in ts]
x[:5]
[{'いつ': '令和3年7月29日(木曜日)', 'どこで': '私立認可保育園', 'だれが': '園児', '内容': '令和3年7月29日(木曜日)、文京区内の私立認可保育園に在籍する園児1名が、新型コロナウイルス感染症に罹患していることが判明しました。感染拡大防止のため、7月30日(金曜日)及び7月31日(土曜日)は臨時休園することとし、全園児の保護者に対して園から連絡を行いました。'}, {'いつ': '令和3年7月29日(木曜日)', 'どこで': '私立認可保育園', 'だれが': '職員', '内容': '令和3年7月29日(木曜日)、文京区内の私立認可保育園に勤務する職員(50代以上)1名が、新型コロナウイルス感染症に罹患していることが判明しました。感染拡大防止のため、7月30日(金曜日)及び7月31日(土曜日)は臨時休園することとし、全園児の保護者に対して園から連絡を行いました。'}, {'いつ': '令和3年7月28日(水曜日)', 'どこで': '私立認可保育園', 'だれが': '職員', '内容': '令和3年7月28日(水曜日)、文京区内の私立認可保育園に勤務する職員(20代以下)1名が、新型コロナウイルス感染症に罹患していることが判明しました。感染拡大防止のため、7月29日(木曜日)から7月31日(土曜日)まで臨時休園することとし、全園児の保護者に対して園から連絡を行いました。'}, {'いつ': '令和3年7月28日(水曜日)', 'どこで': '私立認可保育園', 'だれが': '職員', '内容': '令和3年7月28日(水曜日)、文京区内の私立認可保育園に勤務する職員(20代以下)1名が、新型コロナウイルス感染症に罹患していることが判明しました。感染拡大防止のため、7月29日(木曜日)は臨時休園することとし、全園児の保護者に対して園から連絡を行いました。'}, {'いつ': '令和3年7月29日(木曜日)', 'どこで': '私立認可保育園', 'だれが': '職員及び園児', '内容': '令和3年7月29日(木曜日)、新たに職員(30代)1名及び園児1名が、新型コロナウイルス感染症に罹患していることが判明したため、休園期間を7月31日(土曜日)まで延長することとし、全園児の保護者に対して園から連絡を行いました。'}]
python
# check the consistency in the variable names
expected = ['いつ', 'どこで', 'だれが', '内容']
for a in x:
    keys = list(a.keys())
    assert len(keys) == len(expected), a
    assert sorted(keys) == sorted(expected), a
python
import re
import pandas as pd

def clean_item(item):
    date = item["いつ"]
    r = re.search(r"令和(\d+)年(\d+)月(\d+)日", date) # ignore the second date, if any
    assert r is not None, item
    date = "%04d-%02d-%02d" % (int(r.group(1)) + 2018, int(r.group(2)), int(r.group(3)))  
    place   = item["どこで"]
    patient = item["だれが"]
    patient_worker = (patient.find("職員") >= 0)
    patient_child  = (patient.find("園児") >= 0)
    detail  = item["内容"]
    return {"date":date, "place":place, "patient":patient,
            "patient_worker":patient_worker, "patient_child":patient_child, "detail":detail}
y = pd.DataFrame(clean_item(a) for a in x)
y.date = pd.to_datetime(y.date, format="%Y-%m-%d")

y
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
python
import matplotlib.pyplot as plt

fig, ax = plt.subplots(2, 1, figsize=(12, 6), sharex=True, sharey=True)


# approx 14 days bins
bins = int((y.date.max() - y.date.min()).days / 14)
y.date[y.patient_worker].hist(ax=ax[0], bins=bins, edgecolor="grey")
ax[0].set_title("Workers")
y.date[y.patient_child].hist(ax=ax[1], bins=bins, edgecolor="grey")
ax[1].set_title("Children")
fig.tight_layout()
None
png
python
y.to_csv("coronavirus-cases-in-bunkyoku-daycares_{}.csv".format(currenttime.strftime("%Y%m%d")), index=False)
python

Discussion

コメントにはログインが必要です。