教育データ分析入門2 第2回

  • 2.1 縦断データ
  • 2.2 成長曲線モデル
  • 2.3 集団の変化
  • 練習問題

2.1 縦断データ¶

  • 同じテストを同じ人が数年にわたり受験したデータなどを縦断的データと呼びます。
  • 以下の表はAくん、Bくん、Cくんが3年間同じ英語のテストを受けた結果です。

|-| 1年生 | 2年生 | 3年生 -----|-----|-----|----- |Aくん | 52 | 57 | 90 |Bくん | 44 | 70 | 75 |Cくん | 67 | 80 | 95

  • 以下のようなことはこの表から分かります。
    • 3回のテストを通じてCくんが常に最も高い点数をとっている。
    • 最も成績が伸びているのはAくん(3年生の点数から1年生の点数を引いた値が最も大きい)
  • ですが、「伸び率」のようなものを考えようとした場合、表では難しそうです。
  • これをグラフで表すと以下のようになります。
In [1]:
import matplotlib.pyplot as plt
%matplotlib inline
In [2]:
A = [52,57,90]
B = [44,70,75]
C = [67,80,95]
X = ["First year","Second year","Third year"]

plt.plot(X,A,linewidth=0,marker="o",label="A")
plt.plot(X,B,linewidth=0,marker="x",label="B")
plt.plot(X,C,linewidth=0,marker="^",label="C")
plt.legend(loc="upper left")
Out[2]:
<matplotlib.legend.Legend at 0x7fdbbf71ff28>
No description has been provided for this image
  • もう少し分かりやすくするためにそれぞれのデータを 線で結んでみます。
In [3]:
Y = [1,2,3]
plt.xticks([1,2,3])
plt.plot(Y,A,marker="o",label="A")
plt.plot(Y,B,marker="x",label="B")
plt.plot(Y,C,marker="^",label="C")
plt.legend(loc="upper left")
Out[3]:
<matplotlib.legend.Legend at 0x7fdbbf79c208>
No description has been provided for this image
  • グラフで見ると表に比べて変化を捉えることが容易になります。
  • 3人の受験者すべてが年を追うごとに点数が上昇していることが分かります。
  • 個別に見ると、
    • Aくん(青の線)は1年生の時と2年生の時で点数に違いがないが、3年生の時で点数が大きく上がっている。
    • Bくん(オレンジの線)は1年生の時から2年生の時にかけて大きく上がっているが3年生の時の点数は2年生の時の点数とそれほど変わっていない。
    • Cくん(緑の線)は1年生から2年生、2年生から3年生にかけてほぼ同じ伸び率で得点が上昇している。

2.2 成長曲線モデル¶

  • このような変化を発達軌跡と呼びます。
  • この発達軌跡に関してある仮定をするのが成長曲線モデルです。
    • この英語のテストはAくん、Bくん、Cくんの英語の能力を測定している。
    • しかし、テストの点数には誤差が含まれていて、真の点数ではない。例えば、テスト当日の体調が悪かったとか。多肢選択式の問題で適当に選んだ選択肢が正解だったとか。
    • そして、真の発達軌跡は直線で表現できると仮定します。
  • 直線なので以下のように傾き(a)と切片(b)の2つを用いて表現できます。 $$ 真の得点 = a \times 受験年度 + b $$
  • 以下のように実際に観測されたデータから回帰分析を用いて個人の発達軌跡の直線を求めることができます。
In [4]:
import numpy as np
from scipy import polyfit
X = [1,2,3]
Coef = []
Inter = []

a,b = polyfit(X,A,1)

Coef.append(a)
Inter.append(b)

x = np.arange(1,3,0.01)
y = a*x + b

plt.plot(X,A,linewidth=0,marker="o",label="A")
plt.plot(x,y,color="blue")

a,b = polyfit(X,B,1)

Coef.append(a)
Inter.append(b)

y = a*x + b

plt.plot(X,B,linewidth=0,marker="x",label="B")
plt.plot(x,y,color="orange")

a,b = polyfit(X,C,1)

Coef.append(a)
Inter.append(b)

y = a*x + b

plt.xticks([1,2,3])
plt.plot(X,C,linewidth=0,marker="^",label="C")
plt.plot(x,y,color="green")
plt.legend(loc="upper left")
Out[4]:
<matplotlib.legend.Legend at 0x7fdbbf8d0f28>
No description has been provided for this image
  • このように発達軌跡に直線を仮定することで、点数だけではなく「伸び」の違いを比較することができます。
  • また、傾きと切片の相関係数を見ることで、「初期値」と「伸び」の関係を見ることができます。
In [5]:
# 「伸び」の違い
Coef
Out[5]:
[18.999999999999986, 15.5, 13.999999999999993]
In [6]:
# 切片と傾きの相関係数
np.corrcoef(Coef,Inter)
Out[6]:
array([[ 1.        , -0.81944417],
       [-0.81944417,  1.        ]])
  • このデータにおける切片と傾きの相関係数は負であり、ある程度の強さの関係がみられるので、「1年生の時の点数が低いほど伸びる」と言うことができます。
  • あるいは、カリキュラムと言う観点から見ると、「1年生の時点で高い点数をとっている学習者にはカリキュラムの効果が弱い」とも言えます。
  • 100点満点のテストなので単純に90点以上の点数をとることが難しいのかもしれません。

2.3 集団の変化¶

2つの異なる教授法で英語を教えたグループがあり、3年間にわたり同じテストを受けた結果のデータを読み込みます。

In [7]:
import pandas as pd
In [8]:
group_A = pd.read_csv("../DATA02/GroupA.csv",index_col=0)
group_A.head()
Out[8]:
first_year second_year third_year
S001 86 101 155
S002 98 133 133
S003 71 101 133
S004 60 88 117
S005 24 55 65
In [9]:
group_B = pd.read_csv("../DATA02/GroupB.csv",index_col=0)
group_B.head()
Out[9]:
first_year second_year third_year
T001 75 98 123
T002 86 111 140
T003 50 81 101
T004 55 69 111
T005 70 29 34
In [10]:
group_A.describe()
Out[10]:
first_year second_year third_year
count 30.000000 30.000000 30.000000
mean 61.066667 82.100000 110.633333
std 18.247217 24.489759 25.910301
min 24.000000 44.000000 65.000000
25% 50.000000 61.750000 94.500000
50% 57.000000 76.500000 111.500000
75% 71.750000 100.500000 123.750000
max 98.000000 133.000000 171.000000
In [11]:
group_B.describe()
Out[11]:
first_year second_year third_year
count 30.000000 30.000000 30.000000
mean 68.366667 69.000000 90.533333
std 17.289589 22.777787 26.887676
min 33.000000 29.000000 34.000000
25% 53.500000 55.000000 71.000000
50% 67.500000 68.000000 90.000000
75% 84.250000 84.250000 106.000000
max 96.000000 111.000000 140.000000
  • この2つのクラスの平均点を見ると1年目はGroup Bの方が高いですが、2年目以降はGroup Aの方が高くなっていることが分かります。
  • 平均点からはGroup Aの方が良い結果が得られていると解釈することができます。
  • では、このデータを成長曲線モデルを用いてグラフで表してみましょう。
In [12]:
import numpy as np
from scipy import polyfit
In [13]:
# データフレームをリストに変換
group_A_values = group_A.values
In [14]:
# 実際の点数を線で結ぶ
Y = [1,2,3]
plt.xticks([1,2,3])

for i in group_A_values:
    plt.plot(Y,i,c="grey",marker="+")
No description has been provided for this image
In [15]:
# 成長曲線モデル
X = [1,2,3]

x = np.arange(1,3,0.01)

plt.xticks([1,2,3])

for i in group_A_values:
    a,b = polyfit(X,i,1)
    y = a*x + b
    plt.plot(x,y,color="grey")
No description has been provided for this image
In [16]:
# データフレームをリストに変換
group_B_values = group_B.values
In [17]:
# 実際の点数を線で結ぶ
Y = [1,2,3]
plt.xticks([1,2,3])

for i in group_B_values:
    plt.plot(Y,i,c="grey",marker="+")
No description has been provided for this image
In [18]:
X = [1,2,3]
x = np.arange(1,3,0.01)
plt.xticks([1,2,3])
for i in group_B_values:
    a,b = polyfit(X,i,1)
    y = a*x + b
    plt.plot(x,y,color="grey")
No description has been provided for this image
  • Group Aはほぼ全員が右肩上がりの直線になっていますが、Group Bは1年目から3年目にかけて点数が下がっている人もいることが分かります。
  • このように成長曲線モデルでは、平均点のみでは分からない全体の変化に関する情報を得ることができます。
  • 続いて、それぞれのグループの個人の傾きと切片をリストに保存し、比較してみましょう。
In [19]:
# Group Aの傾きと切片の保存
Coef_A = []
Inter_A = []
for i in group_A_values:
    a,b = polyfit(X,i,1)
    y = a*x + b
    Coef_A.append(a)
    Inter_A.append(b)
In [20]:
# Group Aの傾きの平均値
np.mean(Coef_A)
Out[20]:
24.783333333333324
In [21]:
# Group Aの傾きの標準偏差
np.std(Coef_A)
Out[21]:
6.4493970433074
In [22]:
# Group Aの傾きと切片の相関係数
np.corrcoef(Coef_A,Inter_A)
Out[22]:
array([[ 1.        , -0.05863524],
       [-0.05863524,  1.        ]])
In [23]:
# Group Bの傾きと切片の保存
Coef_B = []
Inter_B = []
for i in group_B_values:
    a,b = polyfit(X,i,1)
    y = a*x + b
    Coef_B.append(a)
    Inter_B.append(b)
In [24]:
# Group Bの傾きの平均値
np.mean(Coef_B)
Out[24]:
11.083333333333325
In [25]:
# Group Bの傾きの標準偏差
np.std(Coef_B)
Out[25]:
13.329843293235758
In [26]:
# Group Bの傾きと切片の相関係数
np.corrcoef(Coef_B,Inter_B)
Out[26]:
array([[ 1.        , -0.73057181],
       [-0.73057181,  1.        ]])
  • ここまで算出した統計量を解釈すると
    • Group Aの方がGroup Bに比べて傾きの平均値が大きい。すなわち、Group Aの方が全体として伸び率が大きいと言えます。
    • 傾きの標準偏差はGroup Bの方が大きいのでGroup Bの方が伸びのばらつきが大きいと言えます。すなわち、伸びている人とそうでない人の差がある、あるいは伸び率にばらつきがあると言えます。
    • 傾きと切片の相関係数を見ると、Group Aは-0.05で、1年目の点数と伸び率はほとんど関係ないことがわかります。反対にGroup Bは負の相関なので1年目の点数が低い人ほど伸びていると言えます。

練習問題¶

"../DATA01/IEDA2_04_lc.csv"には2つの異なる学校の生徒が同じテストを3年間継続して受験したテストの結果が保存されています。学校は"School"というコラムで示されています(AあるいはB)。成長曲線モデルを用いてこれらのデータをグラフで表し、それぞれの学校の傾きの平均値、傾きと切片の相関係数を求めなさい。