3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

東京テクニカルカレッジAdvent Calendar 2022

Day 16

ITパスポート試験の過去問の "正解選択肢だけ" を分析するためのデータ処理

Last updated at Posted at 2022-12-15

この記事の内容

ネタです。
ITパスポートの4択ア、イ、ウ、エのパターンを分析するために、データを構造化してみます。
過去問対策には全くならないので、あまり間に受けないようご注意ください。

処理の流れ

  1. PDFファイルの取得
  2. PDFからテキストの読み取り
  3. データの整理
  4. 簡単な分析例

環境

  • macOS Monterey 12.6
  • Python 3.8.5
    • beautiful-soup
    • pandas
    • pdfminer
    • matplotlib
      • データ整理までなら不要
    • statsmodels
      • 同上

PDFファイルの取得

ITパスポート試験の過去問ページでPDFが公開されているので、BeaufulSoupでダウンロードURLを一括で拾ってローカルにダウンロードします。

# 使うモジュール
import requests
from urllib.request import urlopen
from urllib.parse import urljoin
import time
import os
from bs4 import BeautifulSoup
# URL一覧の取得
base_url = "https://www3.jitec.ipa.go.jp/JitesCbt/html/openinfo/questions.html"
res = urlopen(base_url)
soup = BeautifulSoup(res.read())
tar_table = soup.find_all("table")[1]
titles = tar_table.find_all("td", attrs={"class":"table_10_1"})
titles = [t.text.strip() for t in titles]
answers = tar_table.find_all("td", attrs={"class":"table_10_4"})
urls = [a.find("a").get("href") for a in answers]
urls = [urljoin(base_url,u) for u in urls]
title_url_dict = dict(zip(titles,urls))
title_url_dict

こんな感じの辞書ができます。

{'ITパスポート試験 令和4年度分': 'https://www3.jitec.ipa.go.jp/JitesCbt/html/openinfo/pdf/questions/2022r04_ip_ans.pdf',
 'ITパスポート試験 令和3年度分': 'https://www3.jitec.ipa.go.jp/JitesCbt/html/openinfo/pdf/questions/2021r03_ip_ans.pdf',
(中略)
'ITパスポート試験 平成21年度 春期分': 'https://www3.jitec.ipa.go.jp/JitesCbt/html/openinfo/pdf/questions/2009h21h_ip_ans.pdf'}

あとは順番にダウンロードすれば良いです。サーバーに負荷をかけないように、待機時間を入れるのを忘れずに。

# PDFのダウンロード
dirname = "pdf"
os.makedirs(dirname,exist_ok=True)
for title, url in title_url_dict.items():
    print(f"downloading {title}")
    pdf = urlopen(url)
    with open(os.path.join(dirname,title+".pdf"), "wb") as f:
        f.write(pdf.read())
    time.sleep(3)
    
print("done.")

done. が表示されたら終了です。

downloading ITパスポート試験 令和4年度分
downloading ITパスポート試験 令和3年度分
(中略)
downloading ITパスポート試験 平成21年度 春期分
done.

PDFからテキストの読み取り

ダウンロードしたPDFファイルから、pdfminerを使って文字を読み取ります。
pdfminer は表組みになっているものは縦方向に順番に文字を読み取るようなので、ITパスポートの様式にぴったりですね。ラッキー。
結果のリストは各試験ごとに辞書型で格納します。

# モジュールの読み込み
from pdfminer.high_level import extract_text
import re
# PDFからテキストを読み取る
# 正規表現で「ア」から「エ」までの文字を抜き取る
table_data = {}
pat = re.compile(r"[ア-エ]")
for title in titles:
    path = os.path.join(dirname, title+".pdf")
    text = extract_text(path)
    seq = pat.findall(text)
    ver = title.split(" ", 1)[1]
    table_data[ver] = seq

データの整理

あとはpandasデータフレームに入れてあげるだけです。
1点注意が必要なのが、平成21年の秋試験は、多答問題があるため回答数が揃っていません。
今回は泣く泣く除外するとします。

# モジュールのインポート
import pandas as pd
# 各試験での回答数を表示
for k,v in table_data.items():
    print(k, len(v))
令和4年度分 100
令和3年度分 100
(中略)
平成22年度 春期分 100
平成21年度 秋期分 102
平成21年度 春期分 100

辞書をpd.DataFrameに放り込むと簡単にデータフレームにしてくれます。

# データフレーム型に変換
table_data = {k:v for k,v in table_data.items() if len(v) == 100}
df = pd.DataFrame(table_data)
df.head()
令和4年度分 令和3年度分 令和2年度 10月分 令和元年度 秋期分 平成31年度 春期分 平成30年度 秋期分 平成30年度 春期分 平成29年度 秋期分 平成29年度 春期分 平成28年度 秋期分 平成28年度 春期分 平成27年度 秋期分 平成27年度 春期分 平成26年度 秋期分 平成26年度 春期分 平成25年度 秋期分 平成25年度 春期分 平成24年度 秋期分 平成24年度 春期分 平成23年度 秋期分 平成23年度 特別分 平成22年度 秋期分 平成22年度 春期分 平成21年度 春期分
0
1
2
3
4

数値として分析したい人のために、ア→0、イ→1 みたいな変換をしたデータも作っておきましょう。

# 変数の変換
df_num = df.replace({
    "":0,
    "":1,
    "":2,
    "":3
})
df_num.head()
令和4年度分 令和3年度分 令和2年度 10月分 令和元年度 秋期分 平成31年度 春期分 平成30年度 秋期分 平成30年度 春期分 平成29年度 秋期分 平成29年度 春期分 平成28年度 秋期分 平成28年度 春期分 平成27年度 秋期分 平成27年度 春期分 平成26年度 秋期分 平成26年度 春期分 平成25年度 秋期分 平成25年度 春期分 平成24年度 秋期分 平成24年度 春期分 平成23年度 秋期分 平成23年度 特別分 平成22年度 秋期分 平成22年度 春期分 平成21年度 春期分
0 3 2 2 3 3 0 3 2 0 3 0 0 2 2 0 3 0 3 1 0 0 3 0 2
1 1 3 1 0 2 2 2 3 1 0 0 0 0 2 3 0 2 1 0 1 1 0 1 2
2 2 2 1 2 0 2 1 0 0 2 3 3 3 0 3 3 1 0 1 3 1 1 3 1
3 0 0 2 3 1 2 0 1 1 3 2 0 2 1 1 2 0 1 0 3 1 0 2 0
4 1 2 1 3 0 2 1 0 1 1 2 0 0 2 3 2 3 1 2 1 2 2 1 1

簡単な分析例

後はよしなに、好き勝手分析してみてください。

例えば毎年の正答選択肢の数を集計するならこんな感じ。

# データを縦持ちにする
df_long = df.unstack()
df_long.name = "value"
df_long = df_long.reset_index()
# グループ集計
df_long.groupby("level_0")["value"].value_counts().unstack().loc[df.columns]
value
令和4年度分 32 27 16 25
令和3年度分 29 20 25 26
令和2年度 10月分 27 25 23 25
令和元年度 秋期分 21 20 23 36
平成31年度 春期分 26 22 26 26
平成30年度 秋期分 19 25 28 28
平成30年度 春期分 30 21 27 22
平成29年度 秋期分 18 29 31 22
平成29年度 春期分 14 25 22 39
平成28年度 秋期分 27 27 20 26
平成28年度 春期分 25 21 32 22
平成27年度 秋期分 30 23 29 18
平成27年度 春期分 19 23 31 27
平成26年度 秋期分 21 25 34 20
平成26年度 春期分 22 24 26 28
平成25年度 秋期分 20 26 26 28
平成25年度 春期分 23 28 23 26
平成24年度 秋期分 18 28 31 23
平成24年度 春期分 25 24 30 21
平成23年度 秋期分 17 29 37 17
平成23年度 特別分 23 30 26 21
平成22年度 秋期分 22 34 20 24
平成22年度 春期分 18 29 30 23
平成21年度 春期分 23 30 31 16

自己相関関数を書いてみたりもできます。

# モジュールのインポート
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import acf
plt.rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic']
%matplotlib inline

# 全ての列に自己相関関数を適用して折れ線グラフで表示
fig = plt.figure(figsize=(10,12))
ax = fig.add_subplot()
df_num.apply(lambda x:acf(x), axis=0).plot(ax=ax)
plt.show()

acf.png

おわり

ITパスポートを受けようとする人はこんな事をやっていないで、過去問をひたすら解いたら良いんじゃないでしょうか。

参考にしたもの

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?