一対比較法における一致性の検定
Python3を利用して一対比較法シリーズ第二弾です。
前回は一対比較法における一意性の検定を行いました。
今回は有効となった被験者間の判定の一致性を調べるため、一致性の検定を行う。
Githubにも上げています↓
一致性の検定とは
n人の判断した一対比較の結果がどの程度に一致しているかを調べて,十分に一致してい るならばn人の判断による含計順位を意味のある順位にするという考え方[1]
前回の記事で一意性が認められた被験者間(有効被験者)の一対比較の判断結果がどの程度一致しているか調べることが可能。確率的に十分に一致しているなら、被験者間の判断の合計順位を意味ある順位とするものである。[2][3]
(例えば、どの服が似合うかを選ぶときに人によって評価は確率的に十分一致しているか否か)
※上図はイメージです。
手法について
一意性の検定を行ったのちに、有効となった被験者の判定結果を集計し、Σ値を求め、一致性係数
その後、被験者間の判定が一致しているかどうかを、カイ二乗検定を用いて判断する。
例えば、被験者20人が一対比較法における実験「実験1」を行い、一意性の検定を行った結果、17人の被験者に一意性が有ったと仮定する。
表1
被験者数(人) | 一意性有り | 一意性無し | |
---|---|---|---|
実験1 | 20 | 17 | 3 |
被験者の判定に対する一意性の検討結果 |
表2
i>j | 合計 | ||||||
---|---|---|---|---|---|---|---|
- | 1 | 0 | 2 | 4 | 5 | 12 | |
16 | - | 2 | 0 | 2 | 0 | 20 | |
17 | 15 | - | 2 | 0 | 0 | 34 | |
15 | 17 | 15 | - | 4 | 0 | 51 | |
13 | 15 | 17 | 13 | - | 2 | 60 | |
12 | 17 | 17 | 17 | 15 | - | 78 | |
「実験1」の実験結果 |
この表には、
表2と
展開
ここで、実際に
つまり、Σ値算出に用いる
展開
一致性係数
検定
一致性係数
今回は前回同様
自由度
展開
カイ二乗値
展開
Python3を用いて一致性の検定を行う
環境
- Python 3.9.1 (default, Dec 24 2020, 16:23:16)
- macOS Big Sur ver11.1(このOSで動作を確認)
流れ
- まず一意性の検定をあらかじめ終えておく
- 有効被験者の判定結果を集計
- Σ値を求める
- 一致性係数
を求めるu - カイ二乗値
を求める\chi_0^2 - 被験者間の判定が一致しているかどうかを、カイ二乗検定を用いて判断
各種ライブラリのインポート
import pandas as pd
import csv
import subprocess
import re
import numpy as np
import datetime
import sys
welcomeメッセージ表示
def welcome_mes(): # 起動時のメッセージ
print("Welcome to 一対比較法得票集計システムver2:2021,1,3")
print("paired comparison method consistency vote data aggregate software, PCCS")
print("made by kazuya yuda.")
CSVをインポート
ここでは、すでに一意性の検定を終えて、一意性が有った被験者の実験結果ファイル名が確認済みであることが前提。
def import_csv(): # 試料読み込み
material=['','','']
loop_ans = 0
count = 0
n = 1
while loop_ans < 2:
# ファイル名確認
return_code = subprocess.check_output(['ls','./analyze_data'])
code = return_code.split(b"\n")
for i in range(len(code)):
stdout_txt = str(code[i]).replace("b","").replace('\'',"")
if re.search("csv",stdout_txt):
print(stdout_txt)
print("拡張子を含めて、解析したいmainデータファイル名を入力してください")
filename = input()
if filename == "csv":
print("csvファイルを指定してください。")
sys.exit()
elif re.search("csv",filename):
pass
else:
print("csvファイルを指定してください。")
sys.exit()
print(filename,end=" ")
print("を読み込みました.")
if count == 0 and filename != "":
material[0] = np.loadtxt('./analyze_data/'+filename, delimiter=',')
count += 1
elif filename != "":
material[0] += np.loadtxt('./analyze_data/'+filename, delimiter=',')
else:
pass
print("読み込みを続けますか?y,n:",end=" ")
ans = input()
if ans == "n":
loop_ans = 2
else:
n += 1
if n <= 2:
print("人数が足りません。")
sys.exit()
info=[]
return_code = subprocess.check_output(['ls','./../selector'])
code = return_code.split(b"\n")
for i in range(len(code)):
stdout_txt = str(code[i]).replace("b","").replace('\'',"")
if re.search("csv",stdout_txt) and stdout_txt != "sample_info.csv":
print(stdout_txt)
print("拡張子を含めて、現在解析中の関連mainデータファイル名を入力してください")
filename = './../selector/' + input()
if filename == "csv":
print("csvファイルを指定してください。")
sys.exit()
elif re.search("csv",filename):
pass
else:
print("csvファイルを指定してください。")
sys.exit()
print(filename,end=" ")
print("を読み込みました.")
# info file のインポート
filename2 = filename.replace("main","info")
csv_file = open(filename2, "r", encoding="utf_8", errors="", newline="" )
f = csv.reader(csv_file, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True)
header = next(f)
for row in f: # データ読み込み
info.append(row[1:])
material[1] = info
material[2] = n
return material
試料数kを取得
def get_k(info):
k = int(str(info[2]).replace("[","").replace("]","").replace("\'",""))
return k
ここでは、行列のポジションを指定して、Σ値を算出するための下準備を行う。
上図の処理を行う。
def get_array_position():
material_import = import_csv()
k = get_k(material_import[1])
n = int(material_import[2])
material = material_import[0]
count = 0
sum_all = 0
sum_2 = 0
for a in range(k-1):
count += 1
for b in range(k-count):
#print(a+1,a+b+2)
sum_all += int(material[a+1,a+b+2])
sum_2 += int(material[a+1,a+b+2])**2
#print(material)
#print(sum_all,sum_2)
result=['','','','']
result[0] = sum_all
result[1] = sum_2
result[2] = k
result[3] = n
return result
以下のサブルーチンで計算を行う。
- Σ値を求める
- 一致性係数
を求めるu - 自由度
を求めるf - カイ二乗値
を求める\chi_0^2
def sigma_calculation(sum_all,sum_2,k,n):
v_1 = n*k*(n-1)*(k-1)
v_2 = float(v_1/4)
sigma_val = v_2 + sum_2 - (n*sum_all)
return sigma_val
def consistency_u(sigma_val,k,n):
v_1 = n*k*(n-1)*(k-1)
u = float((8*sigma_val/v_1)-1)
return u
def f_calculation(k,n):
v_1 = n * (n-1) * k * (k-1)
v_2 = 2*(n-2)** 2
f = float(v_1/v_2)
return f
def chi_2_0_caluculation(sigma_val,k,n):
v_1 = float(4/(n-2))
v_2 = n*(n-1)*(n-3)*k*(k-1)
v_3 = 8*(n-2)
chi_2_0 = v_1 * (sigma_val - float(v_2/v_3))
return chi_2_0
最後にmainで各種サブルーチンを呼び出す。
def main():
material = get_array_position()
sum_all = material[0]
sum_2 = material[1]
k = material[2]
n = material[3]
sigma_val=sigma_calculation(sum_all,sum_2,k,n)
print("Σ値:",end=" ")
print(sigma_val)
print("一致性係数u:",end=" ")
print(consistency_u(sigma_val,k,n))
print("自由度f:",end=" ")
print(f_calculation(k,n))
print("カイ二乗値:",end="")
print(chi_2_0_caluculation(sigma_val,k,n))
if __name__ == "__main__":
main()
実行結果
ちなみに、上図は筆者が適当に生成したデータだが、読み込ませた3つのcsvファイルは同じファイルで、
当然カイ二乗分布表からデータが十分一致していることがわかる。
「統計の基礎と実際ー保健・臨床・家政・栄養学のためのー」 の付表[5]によると、自由度fが90では以下のようになっている。
|
0.500 | 0.250 | 0.100 | 0.050 | 0.025 | 0.010 | 0.005 |
---|---|---|---|---|---|---|---|
90 | 89.3342 | 98.6499 | 107.565 | 113.145 | 118.136 | 124.116 | 128.299 |
引用:「統計の基礎と実際ー保健・臨床・家政・栄養学のためのー」 水野哲夫 付表6 カイ自乗分布 |
また、この書籍には自由度fが100以上になった場合の検定方法も記載してある。
以上で一致性の検定ができた。
次回は、刺激間の差を数量的に表すためにサーストン法を用いて尺度化を行い、プロットする予定。(2021/01/15投稿済み)
-
「AHPにおける一対比較法に関する一考察 官能検査における一対比較法の利用」 飯田洋市 https://soar-ir.repo.nii.ac.jp/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=16026&item_no=1&attribute_id=65&file_no=1&page_id=13&block_id=45 ↩︎
-
「感性・官能評価システム J-SEMS > 一致性の係数」 https://j-sems.com/一致性の係数/ ↩︎ ↩︎ ↩︎
-
武庫川女子大紀要(自然科学) 「PC 画面上で見る三原色の季節感について」 伊佐治せつ子,和泉 志穂 https://core.ac.uk/download/pdf/233608433.pdf ↩︎ ↩︎ ↩︎
-
「基礎心理学実験法ハンドブック」 ,日本基礎心理学会 (責任編集:坂上貴之,河原純一郎,木村英司,三浦佳世,行場次郎,石金浩史) ↩︎
-
「統計の基礎と実際ー保健・臨床・家政・栄養学のためのー」 水野哲夫 (光生館) ↩︎
Discussion