平均の差の検定
条件間でサンプルが独立な場合と、繰り返し条件あるいは関連のあるデータ対として得られた場合とについて、平均値の差の検定のためのプログラム例を用意してみた。
ファイルは圧縮ファイルt_test_files_csv.zipにまとめた。圧縮ファイルt_test_files_csv.zipには、Jupyter Notebook用のファイルも含めた。
2つの畑、AとB,、からそれぞれランダムに10個のメロンを採り、重さを測ったところ、表1の結果を得たとする。
表1 畑AとBのメロンの重さ(g) |
|
畑 |
重さ |
A |
1482 1729 1703 1442 1293 1131 1126 1357 1582 1427 |
B |
1962 2028 1762 1810 1822 1393 1711 1644 2144 |
表1のデータに対して、畑AとBでメロンの重さの平均値に有意差があるかどうかの検定(独立なサンプルのt−検定)を行うためのPythonスクリプトをリスト1のように用意した。
リスト1のスクリプトを実行すると、入力データファイル名の設定が求められる。
File
Name(*.csv) =
入力データファイルは、CSVファイルとして図1のように作成する。
図1
図1のファイルは、表1のデータをExcelに入力してCSV形式のファイルData_Ind.csvとしたものである。CSVファイルの作成は、このウェブサイトで説明している。
データは、図1のように1行目に変量名を書き、その下にデータ値を書いていく。
例として、図1のファイル名Data_Ind.csvを設定する。
File
Name(*.csv) = Data_Ind.csv
ファイル名を設定すると、ファイルが読み込まれて、変量名のリストが表示され、第1変量の設定が求められる。
File Name(*.csv) = Data_Ind.csv
['A' 'B']
Var.1 =
変量名は、「'」で挟んで表されているが、入力するときは「'」を外して設定する。
File Name(*.csv) = Data_Ind.csv
['A' 'B']
Var.1 = A
Var.2 = B
第1変量を設定すると、次に第2変量の設定が求められる。
第2変量を設定すると計算が始まり、ヒストグラムが表示される(図2)。
図2
図2のWindowを閉じると、プログラムは終了して、端末には以下の出力が表示されている。
等分散仮説を前提とする
両側検定
t = -3.84524
p-value = 0.00130
df = 17.000
95% CI = [-590.426, -172.063]
等分散仮説を前提とする
左側検定(下側検定)
t = -3.84524
p-value = 0.00065
df = 17.000
95% CI = [-inf, -208.768]
等分散仮説を前提とする
右側検定(上側検定)
t = -3.84524
p-value = 0.99935
df = 17.000
95% CI = [-553.721, inf]
等分散仮説を前提としない (Welch's t)
両側検定
t' = -3.83262
p-value = 0.00139
df = 16.520
95% CI = [-591.580, -170.909]
等分散仮説を前提としない (Welch's t)
左側検定(下側検定)
t' = -3.83262
p-value = 0.00070
df = 16.520
95% CI = [-inf, -207.910]
等分散仮説を前提としない (Welch's t)
右側検定(上側検定)
t' = -3.83262
p-value = 0.99930
df = 16.520
95% CI = [-554.579, inf]
等分散仮説を前提とする場合(標準のt検定)と、等分散仮説を前提としない場合(ウェルチのt検定)が出力されている。
ウェルチのtのp値は、このウェブサイトでのシミュレーションにおいて、等分散仮説が成り立つ場合、p値が0あるいは1の近傍において若干のずれが認められるが、全体として標準のt検定(スチューデントのt検定)のp値をよく近似していることが示されている。特に理由が無いときは、ウェルチの検定を用いる方が安全であると思われる。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
import pandas as pd
import scipy.stats as ss
fin_nm = input('File Name(*.csv) = ')
data = pd.read_csv(fin_nm)
print(data.keys().values)
A_name = input('Var.1 = ')
B_name = input('Var.2 = ')
A = data[A_name].values
A = A[np.isnan(A)==False]
B = data[B_name].values
B = B[np.isnan(B)==False]
print(f'{A_name}: Mean = {np.mean(A):.3f}, SD = {np.std(A):.3f}')
print(f'{B_name}: Mean = {np.mean(B):.3f}, SD = {np.std(B):.3f}')
for eq in [True, False]:
for alt in['two-sided',
'less', 'greater']:
print(); print()
if
eq == True:
print('等分散仮説を前提とする')
else:
print("等分散仮説を前提としない (Welch's t)")
if
alt == 'two-sided':
print('両側検定')
elif
alt == 'less':
print('左側検定(下側検定)')
else:
print('右側検定(上側検定)')
results
= ss.ttest_ind(A, B, equal_var=eq, alternative=alt)
if
eq == True:
print(f't = {results.statistic:.5f}')
else:
print(f"t' = {results.statistic:.5f}")
print(f'p-value = {results.pvalue:.5f}')
print(f'df
= {results.df:.3f}')
ci =
results.confidence_interval(confidence_level=0.95)
print(f'95% CI = [{ci.low:.3f}, {ci.high:.3f}]')
plt.hist([A, B],label=[f'{A_name}',
f'{B_name}'])
plt.title(f'Mean({A_name}) =
{np.mean(A):.2f}' +
f' Mean({B_name}) =
{np.mean(B):.2f}', fontsize=14)
plt.ylabel('度数', fontsize=16)
plt.legend()
plt.show()
ダイエット前後の体重として表2のデータを得たとする。
表2 ダイエット前後の体重[前、後](Kg) |
[73, 70] [68, 61] [71, 68] [68, 62] [61, 60] [73, 70] [80, 81] [71, 72] [75, 65] [59, 52] [89, 85] [68, 71] [96, 91] [88, 83] [79, 78] [68, 69] [71, 65] [66, 64] [72, 69] [78, 72] |
ダイエット前後で差があったかどうかの検定(繰り返し条件/対応のある条件のt−検定)のため、リスト2のスクリプトを用意した。
リスト2のスクリプトを実行すると、入力ファイルの設定が求められる。
File
Name(*.csv) =
データファイルは、CSV形式のファイルとして用意する。図3は、表2のデータをCSV形式のファイルとしたものである。CSV形式のファイルの作成法は、このウェブサイトで説明している。
図3
入力データは、1行目に変量名を書き、その下にデータを書いていく。例として、図3のファイルData_Rel.csvを入力データファイルとして設定する。
File
Name(*.csv) = Data_Rel.csv
データファイル名を設定すると、ファイルが読み込まれて、変量名のリストが表示され、分析の対象とする変量名の設定が求められる。
File Name(*.csv) = Data_Rel.csv
['前' '後']
Var.1 =
変量名のリストは、変量名が「'」で挟まれて表示されている。変量名を設置するときは、「'」をはずして設定する。
第1変量名を設定すると、第2変量名の設定が求められる。検定は、「第1変量 − 第2変量」について行われる。
File
Name(*.csv) = Data_Rel.csv
['前' '後']
Var.1 = 前
Var.2 = 後
第2変量を設定すると、計算が始まり、差「第1変量 ― 第2変量」のヒストグラムが表示される(図4)。
図4
図4のWindowを閉じると、プログラムの実行の終了となる。端末には、以下の出力が表示されている。
Mean(前) = 73.7
Mean(後) = 70.4
Mean(前) - Mean(後) = 3.300
SD(前 - 後) = 3.226
N = 20
SD/N**0.5 = 0.721
両側検定
t = 4.45826
p-value = 0.00027
df = 19.00
95% CI = [1.751, 4.849]
左側検定(下側検定)
t = 4.45826
p-value = 0.99987
df = 19.00
95% CI = [-inf, 4.580]
右側検定(上側検定)
t = 4.45826
p-value = 0.00013
df = 19.00
95% CI = [2.020, inf]
import pandas as pd
import numpy as np
import scipy.stats as ss
import matplotlib.pyplot as plt
import japanize_matplotlib
fin_nm = input('File Name(*.csv) = ')
f_data = pd.read_csv(fin_nm,
encoding='shift-jis')
print(f_data.keys().values)
A_name = input('Var.1 = ')
B_name = input('Var.2 = ')
a = f_data[A_name].values
b = f_data[B_name].values
print(f'Mean({A_name}) =
{np.mean(a)}')
print(f'Mean({B_name}) =
{np.mean(b)}')
print(f'Mean({A_name}) -
Mean({B_name}) = {np.mean(a) - np.mean(b):.3f}')
print(f'SD({A_name} - {B_name}) =
{np.std(a-b):.3f}')
print(f'N = {len(a)}')
print(f'SD/N**0.5 =
{np.std(a-b)/(len(a)**0.5):.3f}')
for alt in ['two-sided', 'less',
'greater']:
print(); print()
if alt == 'two-sided':
print('両側検定')
elif alt == 'less':
print('左側検定(下側検定)')
else:
print('右側検定(上側検定)')
results = ss.ttest_rel(a, b,
alternative=alt)
print(f't =
{results.statistic:.5f}')
print(f'p-value =
{results.pvalue:.5f}')
print(f'df =
{results.df:.2f}')
print(f'95% CI =
[{results.confidence_interval().low:.3f},' +
f' {results.confidence_interval().high:.3f}]')
plt.hist(a - b)
plt.title(f'Mean({A_name} - {B_name})
= {np.mean(a) - np.mean(b):.2f}',
fontsize=16)
plt.ylabel('度数', fontsize=14)
plt.xticks(fontsize= 12)
plt.xlabel(f'{A_name} - {B_name}',
fontsize=16)
plt.show()