情報I試作問題 第4問

新学習指導要領に対応した2025年からの大学入学共通テストの試作問題等が2022-11-09に公開された(2022-12-23一部訂正)。この中の「情報I」の試作問題の第4問は、いわゆるデータサイエンスの問題である。

この元データをT.Matsushima先生が見つけてくださった(令和7年度大学入学共通テスト 情報Ⅰ参照):

社会生活基本調査 / 平成28年社会生活基本調査 / 調査票Aに基づく結果 生活時間に関する結果 生活時間編(地域)

ここからダウンロードできるExcelファイル(ファイル名 a059_4.xlsx)を読めば、表1-A・表1-Bができる。

import pandas as pd

df = pd.read_excel("a059_4.xlsx", skiprows=18, na_values=["...","-"], keep_default_na=False)

df1 = df.iloc[:, [5,6,7,8,9,10,19,20,21,22,24,33]]
df1.columns = ['曜日', '地域区分', '男女', '就業状態', '使用時間', '年齢',
               '睡眠', '用事', '食事', '通学', '学業', '趣味']
# df1.dropna(inplace=True)
dfa = df1.query("曜日 == '2_平日' and 地域区分 != '00_全国' and 男女 == '0_総数' and 就業状態 == '0_総数' and 使用時間 == '21_1時間未満' and 年齢 == '01_15~19歳'")
dfa = dfa[['地域区分', '睡眠', '用事', '食事', '通学', '学業', '趣味']]
dfb = df1.query("曜日 == '2_平日' and 地域区分 != '00_全国' and 男女 == '0_総数' and 就業状態 == '0_総数' and 使用時間 == '23_3~6時間未満' and 年齢 == '01_15~19歳'")
dfb = dfb[['地域区分', '睡眠', '用事', '食事', '通学', '学業', '趣味']]

dfa.to_csv("1a.csv", index=False, encoding="utf_8_sig", lineterminator="\r\n")
dfb.to_csv("1b.csv", index=False, encoding="utf_8_sig", lineterminator="\r\n")

以下では見やすくするためCSVファイル中の .0 は一括削除した。

1a.csv: 表1-A:スマートフォン・パソコンなどの使用時間が1時間未満の人の生活行動時間に関する都道府県別平均値

地域区分,睡眠,用事,食事,通学,学業,趣味
01_北海道,439,74,79,60,465,8
02_青森県,411,74,73,98,480,13
03_岩手県,442,61,87,98,539,8
04_宮城県,425,56,114,41,400,
05_秋田県,447,73,85,42,501,8
06_山形県,,,,,,
07_福島県,,,,,,
08_茨城県,407,61,80,79,552,11
09_栃木県,433,76,113,50,445,57
10_群馬県,411,77,108,79,418,7
11_埼玉県,431,68,82,79,370,14
12_千葉県,499,63,96,64,374,63
13_東京都,454,71,80,99,520,27
14_神奈川県,380,71,89,102,518,3
15_新潟県,,,,,,
16_富山県,429,41,76,100,578,1
17_石川県,423,59,75,64,582,2
18_福井県,362,60,83,48,752,3
19_山梨県,427,65,73,69,527,5
20_長野県,393,81,98,50,487,25
21_岐阜県,421,68,86,70,481,19
22_静岡県,425,79,73,81,543,42
23_愛知県,436,78,92,69,318,95
24_三重県,449,60,91,104,530,2
25_滋賀県,,,,,,
26_京都府,451,95,96,105,375,4
27_大阪府,342,69,96,90,544,14
28_兵庫県,457,58,77,73,463,43
29_奈良県,440,53,97,70,483,17
30_和歌山県,466,60,68,71,481,16
31_鳥取県,,,,,,
32_島根県,433,69,81,58,445,8
33_岡山県,448,77,77,71,447,21
34_広島県,423,87,92,58,469,17
35_山口県,422,83,84,58,561,64
36_徳島県,400,74,85,62,520,23
37_香川県,443,79,72,60,620,21
38_愛媛県,383,126,74,81,524,
39_高知県,,,,,,
40_福岡県,410,84,88,81,594,6
41_佐賀県,418,100,86,52,403,0
42_長崎県,398,57,106,78,483,22
43_熊本県,444,40,85,65,568,
44_大分県,386,41,76,43,419,6
45_宮崎県,407,52,80,105,496,20
46_鹿児島県,407,58,88,56,537,9
47_沖縄県,447,67,90,72,482,13

1b.csv: 表1-B:スマートフォン・パソコンなどの使用時間が3時間以上6時間未満の人の生活行動時間に関する都道府県別平均値

地域区分,睡眠,用事,食事,通学,学業,趣味
01_北海道,436,74,88,63,411,64
02_青森県,461,57,83,55,269,44
03_岩手県,442,70,76,54,366,63
04_宮城県,426,64,86,89,285,44
05_秋田県,430,68,76,96,340,41
06_山形県,426,69,67,64,509,54
07_福島県,422,51,77,55,379,53
08_茨城県,443,80,81,82,423,63
09_栃木県,386,120,79,77,504,33
10_群馬県,427,76,60,65,442,69
11_埼玉県,431,69,99,98,400,24
12_千葉県,411,69,98,104,391,60
13_東京都,428,98,101,87,406,59
14_神奈川県,415,94,81,113,390,53
15_新潟県,434,79,80,63,363,107
16_富山県,476,70,68,63,401,29
17_石川県,417,59,91,84,475,82
18_福井県,452,73,77,68,378,70
19_山梨県,466,69,100,60,263,84
20_長野県,446,63,76,75,424,88
21_岐阜県,426,64,82,59,442,32
22_静岡県,415,79,79,68,410,82
23_愛知県,409,76,89,83,371,68
24_三重県,465,83,87,57,334,67
25_滋賀県,433,89,98,116,341,73
26_京都府,462,31,68,83,365,18
27_大阪府,448,57,86,80,369,70
28_兵庫県,448,67,68,83,378,36
29_奈良県,468,62,82,102,347,48
30_和歌山県,442,51,66,60,315,76
31_鳥取県,425,73,78,112,255,96
32_島根県,422,68,81,61,407,108
33_岡山県,451,58,78,70,374,69
34_広島県,452,69,72,68,414,57
35_山口県,441,54,89,68,350,68
36_徳島県,412,56,83,86,486,22
37_香川県,456,44,67,79,462,61
38_愛媛県,463,84,72,48,404,125
39_高知県,452,87,86,64,393,81
40_福岡県,418,63,84,77,445,56
41_佐賀県,453,67,75,67,360,49
42_長崎県,423,56,82,42,432,80
43_熊本県,442,29,68,47,481,49
44_大分県,415,42,69,57,436,62
45_宮崎県,421,64,86,71,316,56
46_鹿児島県,407,82,79,69,424,50
47_沖縄県,450,52,103,50,417,49

いったんCSVファイルができてしまえば、これを読むほうが早い:

import pandas as pd

dfa = pd.read_csv("https://okumuralab.org/~okumura/python/data/1a.csv")
dfb = pd.read_csv("https://okumuralab.org/~okumura/python/data/1b.csv")

p.26に「ただし,表1-A,表1-Bにおいて一か所でも項目のデータに欠損値がある場合は,それらの都道府県を除外したものを全体として考える」とあるので、欠損値が一つでもある行を削除したものも作っておく:

dfA = dfa.dropna()
dfB = dfb.dropna()

欠損値を削除しない dfadfb も残しておくのは、あとで回帰分析をする際に、dfa のほうを使わないと結果が合わないためである。問題作成者が混乱しているのかもしれない。

p.26で「なお,以下において,データの範囲については,外れ値も含めて考えるものとする」という指示があるのは、一部で(例えば2σ以上離れた)外れ値は機械的に削除するといった指導がされていることに対応するためなのだろうか。

p.27「図1 睡眠の時間の分布」の箱ひげ図:

import matplotlib.pyplot as plt

plt.boxplot([dfB['睡眠'], dfA['睡眠']], vert=False, labels=['表1-B', '表1-A'])

Seabornを使う場合:

import seaborn as sns

sns.boxplot(pd.DataFrame({"表1-A": dfA["睡眠"], "表1-B": dfB["睡眠"]}), orient="h")

p.27「図2 学業の時間の分布」の箱ひげ図:

plt.boxplot([dfB['学業'], dfA['学業']], vert=False, labels=['表1-B', '表1-A'])

p.29「図3 生活行動時間の差」の箱ひげ図:

plt.boxplot([(dfa['睡眠'] - dfb['睡眠']).dropna(),
             (dfa['学業'] - dfb['学業']).dropna()],
            labels=['睡眠', '学業'])

図4 表1-Aの学業の時間と睡眠の時間の散布図:

plt.plot(dfa['学業'], dfa['睡眠'], 'o')

回帰直線:

import pingouin as pg

pg.linear_regression(dfa[['学業']], dfa['睡眠'], remove_na=True)
       names        coef         se          T  ...       r2    adj_r2    CI[2.5%]   CI[97.5%]
0  Intercept  491.165521  27.408073  17.920469  ...  0.13757  0.115456  435.727460  546.603581
1         学業   -0.136434   0.054700  -2.494202  ...  0.13757  0.115456   -0.247076   -0.025792

回帰式 y = -0.14x + 491.17 が確認できる。傾き -0.136 は、95% 信頼区間 [-0.247, -0.026] が 0 をまたがないので、5% 水準で有意である。

残差は次のようにして求められる:

lm = pg.linear_regression(dfa[['学業']], dfa['睡眠'], remove_na=True, as_dataframe=False)
r = lm['residuals']  

図6 睡眠の時間(推定値)と残差の変換値との関係:

import numpy as np

plt.plot(lm['pred'], (r - r.mean()) / r.std(), "o")

散布図と回帰直線(95%信頼区間付き)を描くには seaborn のほうが便利である:

import seaborn as sns

sns.regplot(dfa, x="学業", y="睡眠")

ただし、一番右の点(福井県、752分)を含めなければ、傾きは有意でなくなる:

dfx = dfa.query("地域区分 != '18_福井県'")
pg.linear_regression(dfx[['学業']], dfx['睡眠'], remove_na=True)
       names        coef        se          T  ...        r2   adj_r2    CI[2.5%]   CI[97.5%]
0  Intercept  472.905958  31.48758  15.018809  ...  0.058038  0.03325  409.162686  536.649230
1         学業   -0.097699   0.06385  -1.530144  ...  0.058038  0.03325   -0.226956    0.031558

散布図と回帰直線をさきほどの図に重ね書きする。青が全体、オレンジが福井県を除いたものである:

sns.regplot(dfx, x="学業", y="睡眠")
学業と睡眠の時間

このことから、右端の福井県こそが外れ値というべきであろう(問5の後半の議論とは裏腹に)。

福井県を除けば傾きが有意でなくなることに加え、都道府県ごとの平均値の傾向は必ずしも個人の傾向を表すものではないこと(生態学的誤謬、ecological fallacy)を考慮して、この種のデータは慎重に扱う必要がある。

また、学業の時間と睡眠の時間との関連を調べる際に、なぜスマホ・パソコンの利用時間が1時間未満という条件を付ける必要があったのかもよくわからない。