📗

一対比較法における一致性の検定

2021/01/09に公開

Python3を利用して一対比較法シリーズ第二弾です。
前回は一対比較法における一意性の検定を行いました。
https://zenn.dev/_kazuya/articles/0e0c95f82cb931

今回は有効となった被験者間の判定の一致性を調べるため、一致性の検定を行う。

Githubにも上げています↓
https://github.com/Iovesophy/paired_comparison_method.git

一致性の検定とは

n人の判断した一対比較の結果がどの程度に一致しているかを調べて,十分に一致してい るならばn人の判断による含計順位を意味のある順位にするという考え方[1]

前回の記事で一意性が認められた被験者間(有効被験者)の一対比較の判断結果がどの程度一致しているか調べることが可能。確率的に十分に一致しているなら、被験者間の判断の合計順位を意味ある順位とするものである。[2][3]
(例えば、どの服が似合うかを選ぶときに人によって評価は確率的に十分一致しているか否か)

※上図はイメージです。

手法について

一意性の検定を行ったのちに、有効となった被験者の判定結果を集計し、Σ値を求め、一致性係数uを求める。
その後、被験者間の判定が一致しているかどうかを、カイ二乗検定を用いて判断する。

例えば、被験者20人が一対比較法における実験「実験1」を行い、一意性の検定を行った結果、17人の被験者に一意性が有ったと仮定する。

表1

被験者数(人) 一意性有り 一意性無し
実験1 20 17 3
被験者の判定に対する一意性の検討結果

表2

i>j A_j B_j C_j D_j E_j F_j 合計
A_i - 1 0 2 4 5 12
B_i 16 - 2 0 2 0 20
C_i 17 15 - 2 0 0 34
D_i 15 17 15 - 4 0 51
E_i 13 15 17 13 - 2 60
F_i 12 17 17 17 15 - 78
「実験1」の実験結果

この表には、A_i ... F_iA_j ... F_j を比較したとき,A_i ... F_i の方をより大きいと感じたと判定した人数を表している。

表2とk(試料数)とn(人数)から、次の式よりΣ値を求める。[2:1][3:1]

\Sigma = {}_n C_2 \cdot{} {}_k C_2 + \sum_{j>i} \chi_{ij}^2 - n \sum_{j>i} \chi_{ij}

展開

{}_n C_2\cdot{} {}_k C_2 = \frac{nk(n-1)(k-1)}{4}
\Sigma = \frac{nk(n-1)(k-1)}{4} + \sum_{j>i} \chi_{ij}^2 - n \sum_{j>i} \chi_{ij}

ここで、実際に\Sigma値をどう計算するかわかりにくいので、一部計算の具体例を上げておく↓

\sum_{j>i}\chi_{ij} = 1 + 2 \times 5 + 4 \times 2 + 5 = 24
\sum_{j>i}\chi_{ij}^2 = 1^2 + 2^2 \times 5 + 4^2 \times 2 + 5^2 = 78

つまり、Σ値算出に用いる\sum_{j>i}\chi_{ij}は合計の値ではなくてA_i ... F_iA_j ... F_j を比較したとき,A_i ... F_i の方を小さく感じたと判定したそれぞれの得票を使用する。

次に一致性係数uを求める。[2:2][3:2][4]

u=\frac{2\Sigma}{{}_n C_2\cdot{} {}_k C_2}-1

展開

u=\frac{2\Sigma}{\frac{nk(n-1)(k-1)}{4}} - 1

u=\frac{8\Sigma}{nk(n-1)(k-1)} - 1

一致性係数u\Sigmaによる検定表が用意できれば、この時点で一致性を確認することができる。

検定

一致性係数u\Sigmaによる検定表を用意することができれば、そのk(試料数)とn(人数)の範囲内であれば、\Sigmaが表中の値以上で有意となり、n人の判断が一致していると考えられる。
今回は前回同様\chi^2値、自由度f を求めカイ二乗分布表により一致性を検定する。

自由度f

f = {}_k C_2\cdot{}\frac{n(n-1)}{(n-2)^2}

展開

{}_k \mathrm{C}_2 = \frac{k!}{2!(k-2)!} = \frac{n(n-1)}{2}

f=\frac{n(n-1)k(k-1)}{2(n-2)^2}

カイ二乗値\chi^2

\chi_0^2 = \frac{4}{n-2} \left\{\Sigma - \frac{1}{2} \cdot{} {}_n C_2\cdot{} {}_k C_2 \cdot{} \frac{n-3}{n-2} \right\}

展開

{}_n C_2\cdot{} {}_k C_2 = \frac{nk(n-1)(k-1)}{4}

\chi_0^2 = \frac{4}{n-2} \left\{\Sigma - \frac{n(n-1)(n-3)k(k-1)}{8(n-2)} \right\}

\chi^2(カイ二乗分布表)より有意水準\alphaで、n人の判断が一致しているといえる。

\chi_0^2 \geqq \chi^2 (f, \alpha)

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では以下のようになっている。

df \ P_r 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 カイ自乗分布dfまたはv:自由度 より一部抜粋

また、この書籍には自由度fが100以上になった場合の検定方法も記載してある。

以上で一致性の検定ができた。

次回は、刺激間の差を数量的に表すためにサーストン法を用いて尺度化を行い、プロットする予定。(2021/01/15投稿済み)
https://zenn.dev/_kazuya/articles/a1179ed3f6e027

脚注
  1. 「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 ↩︎

  2. 「感性・官能評価システム J-SEMS > 一致性の係数」 https://j-sems.com/一致性の係数/ ↩︎ ↩︎ ↩︎

  3. 武庫川女子大紀要(自然科学) 「PC 画面上で見る三原色の季節感について」 伊佐治せつ子,和泉 志穂 https://core.ac.uk/download/pdf/233608433.pdf ↩︎ ↩︎ ↩︎

  4. 「基礎心理学実験法ハンドブック」 ,日本基礎心理学会 (責任編集:坂上貴之,河原純一郎,木村英司,三浦佳世,行場次郎,石金浩史) ↩︎

  5. 「統計の基礎と実際ー保健・臨床・家政・栄養学のためのー」 水野哲夫 (光生館) ↩︎

GitHubで編集を提案

Discussion