前回のRによるデータクリーニング実践――政府統計からのグラフ作成を例として を参考にしたのでクリーニング方法も今回は変更
せっかくなのでe-Statにあるデータ全部(1957年は課程ごとのため除外)をスクレイピングしてグラフ作成しました。
Excelデータ
年度ごとの違い
年度 | 分校 | 学校 | 共学 | 英語 | 合計 | 転置 |
---|---|---|---|---|---|---|
1976~2019 | 〇 | 〇 | × | × | 計 | 〇 |
1966~1975 | × | 〇 | 〇 | × | 計 | 〇 |
1964~1965 | × | 〇 | 〇 | 〇 | 計 | 〇 |
1963 | × | 〇 | 〇 | 〇 | 計 | × |
1962 | × | 〇 | 〇 | 〇 | 総数 | × |
1959~1961 | × | × | 〇 | × | 総数 | × |
1958 | × | × | 〇 | × | 総数 | 〇 |
1957 | - | - | - | - | - | - |
- 分校:分校の列があり、なし
- 学校:男のみの学校・女のみの学校と「の学校が」つく・つかない
- 共学:「共学」はあり、「男女ともにいる」はなし
- 英語:英語のタイトルがあり、なし
- 合計:計か総数
- 転置:必要、なし
共学の違い
年度 | 共学 |
---|---|
1976-2019 | 男女ともにいる学校 |
1963-1975 | 男女共学の学校 |
1962 | 男女共学学校 |
1959-1961 | 共学 |
1958 | 男女共学 |
プログラム
!pip install japanize_matplotlib
EXCELファイルのURLと年を抽出
import requests from bs4 import BeautifulSoup from urllib.parse import urljoin headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" } data = [] for page in [1, 2]: r = requests.get( f"https://www.e-stat.go.jp/stat-search/files?page={page}&query=%E7%94%B7%E5%A5%B3%E5%88%A5%E5%AD%A6%E6%A0%A1%E6%95%B0%20-%E5%BE%8C%E6%9C%9F%E8%AA%B2%E7%A8%8B&sort=year_month%20desc&layout=dataset&toukei=00400001&metadata=1&data=1", headers=headers, ) r.raise_for_status() soup = BeautifulSoup(r.content, "html5lib") for div in soup.select("div.stat-resource_list-main"): li = div.select("li.stat-resource_list-detail-item") year = int(li[2].contents[2].rstrip("年")) if year > 1957: url = urljoin( "https://www.e-stat.go.jp/", li[4].find("a", attrs={"data-file_type": "EXCEL"}).get("href"), ) data.append({"year": year, "url": url}) else: break
EXCELファイルのデータ抽出、CSVに保存
import pandas as pd from tqdm import tqdm_notebook import time dfs = [] for i in tqdm_notebook(data): df1 = pd.read_excel(i["url"]) df1.replace(["-", "―", "-"], 0, inplace=True) # クリーニング df2 = df1.loc[df1.notnull().sum(axis=1) > 2, df1.notnull().sum() > 2] year = i["year"] # 1962年~1965年は英語があるので除去 if 1961 < year < 1966: df2.replace("[a-zA-Z-]", "", regex=True, inplace=True) # 空白文字を除去 df2.replace(r"\s", "", regex=True, inplace=True) # 1959年~1963年は転置なし if 1958 < year < 1964: # 転置なし df3 = df2.fillna(method="ffill") else: # 転置あり df3 = df2.T.fillna(method="ffill") filename = f"{year}.csv" # CSVに保存 df3.to_csv(filename, header=False, index=False) time.sleep(3) ## 年度ごとに取り込み方法変更 if year > 1975: df4 = pd.read_csv(filename, header=0, index_col=[0, 1]) s = df4.loc[("計", "計"), ["男のみの学校", "女のみの学校"]] elif year > 1962: df4 = pd.read_csv(filename, header=0, index_col=0) s = df4.loc["計", ["男のみの学校", "女のみの学校"]] elif year == 1962: df4 = pd.read_csv(filename, header=0, index_col=0) s = df4.loc["総数", ["男のみの学校", "女のみの学校"]] elif year > 1957: df4 = pd.read_csv(filename, header=0, index_col=0) s = df4.loc["総数", ["男のみ", "女のみ"]] s.index = ["男のみの学校", "女のみの学校"] else: break s.name = year dfs.append(s) df = pd.concat(dfs, axis=1).T df
グラフ
import matplotlib.pyplot as plt import japanize_matplotlib import numpy as np df.plot( marker="o", ms=5, grid=True, figsize=(10, 8), xticks=np.arange(1955, 2020+1, 5), title="日本における男子のみ・女子のみの高校(通信制除く)の数" )