Up

双対尺度法

分割表の分析

 

表1(大山「色彩心理学入門」、1994pp. 220-222 における記述を基に分割表の形にまとめ直したもの)のような分割表を双対尺度法(<岡本安晴「心理学データ分析法と測定」勁草書房、第14章 質的データの可視化:双対尺度法>で説明している)によって分析するPythonスクリプトを作成した。双対尺度法により「怒り」などの行項目と「赤」などの列項目に数値が割り当てられ、この数値を座標値として行項目と列項目の関係をビジュアルに表すことができる(図1)。

 

表1 象徴語と色の適合関係。適合するときを1、適合しないときを0で表す。

 

青紫

緑味青

ピンク

黄橙

黄緑

怒り

1

1

1

0

0

0

0

0

0

0

0

0

0

0

嫉妬

1

1

0

1

0

0

0

0

0

0

0

0

0

0

0

0

1

0

1

1

0

0

0

0

0

0

0

0

永遠

0

0

0

0

0

0

1

1

0

0

1

0

0

0

幸福

0

1

0

0

0

0

0

0

1

1

0

0

0

0

孤独

0

0

1

0

1

0

0

0

0

0

1

0

0

0

平静

0

0

0

0

0

0

0

1

0

0

1

1

0

0

郷愁

0

0

0

0

0

0

0

0

0

1

1

1

1

0

家庭

0

1

0

0

0

0

0

0

1

1

0

0

0

0

1

1

0

0

0

0

0

0

1

0

0

0

0

0

純潔

1

0

0

0

0

0

1

1

0

0

0

0

0

0

0

0

0

0

0

0

0

1

1

0

0

0

0

1

不安

0

0

1

1

1

0

0

0

0

0

0

0

0

0

恐怖

1

0

1

0

1

0

0

0

0

0

0

0

0

0

 

 

図1

 

表1のデータは、図2の形式で入力データファイルとして用意している。

図2

 

スラッシュ / で始まる行の次の行に、行概念(angerからfearまで)の数と列概念(redからyellowまで)の数を書く。

次の行に、列概念のラベルを並べる。

その次の行から、各行に行概念のラベルとそれに続けてクロス表の頻度値を書いていく。表1と図2の対応が確認できる。

 

プログラムはこのウェブサイトの後半にメインスクリプトを載せてあるが、プログラムファイルとサンプルデータファイルをまとめて圧縮ファイルPrgsDS.zipとしても用意した。ファイル名をPrgsDS.zipクリックすればダウンロードできる。

プログラムを実行すると、まず、入力データファイル名の設定が求められる(図3)。

図3

 

入力データファイル名を設定すると、次に計算結果の出力用テキストファイル名の設定が求まられるので、適当なテキストファイル名を設定する(図4)。

図4

 

ファイル名の設定の次に、解の次元数が求められる。双対尺度法の解は、次元数を増やしても次元数が小さいときの解は影響を受けないので、多い目に設定しておけばよい。設定した次元数が大きすぎるときは、プログラムの実行時に調整される。

次元数を設定すると計算が始まり、計算が終了すると解の描画のx軸とy軸の次元の設定が求められる(図5)。

図5

 

x軸とy軸の次元を設定すると、それに対応して解の布置が描画される(図6)。なお、双対尺度法の解は、相関係数を極大にするという条件で求められており、各次元のペアの解は同時に方向を逆転したものも解になる。どちらの方向の解が与えられるかは、プログラムのアルゴリズムに依存している。いずれの解も正しい解である。

図6

 

次元の値が大きすぎるときは最大値に調整される。

右上のX印をクリックすると描画フォームは閉じられる。

次の描画用x軸とy軸の次元の設定が求められる(図7)。

図7

 

希望する次元を設定すれば、それに対応した図6のようなマップが表示される。次元数として0以下の値を設定するとプログラムの実行終了となる(図8)。

 

図8

 

プログラムの実行終了後、出力ファイルを開くと、図2のデータの場合、以下のようになっている。

 

Input data file = Data.txt

 

n_dim = 2

 

Input Data...

 

LabelCol...

 red orange black purple gray violet white grnble pink yorange blue green ygrn yellow

 

LabelRow and F-data

anger       1  1  1  0  0  0  0  0  0  0  0  0  0  0

jealousy    1  1  0  1  0  0  0  0  0  0  0  0  0  0

sin         0  0  1  0  1  1  0  0  0  0  0  0  0  0

eternity    0  0  0  0  0  0  1  1  0  0  1  0  0  0

happy       0  1  0  0  0  0  0  0  1  1  0  0  0  0

lonely      0  0  1  0  1  0  0  0  0  0  1  0  0  0

calm        0  0  0  0  0  0  0  1  0  0  1  1  0  0

nostalgia   0  0  0  0  0  0  0  0  0  1  1  1  1  0

home        0  1  0  0  0  0  0  0  1  1  0  0  0  0

love        1  1  0  0  0  0  0  0  1  0  0  0  0  0

purity      1  0  0  0  0  0  1  1  0  0  0  0  0  0

dream       0  0  0  0  0  0  0  1  1  0  0  0  0  1

anxiety     0  0  1  1  1  0  0  0  0  0  0  0  0  0

fear        1  0  1  0  1  0  0  0  0  0  0  0  0  0

 

               sq-cor-ratio        coorelation              Prop.      Cum-Prop.

1:             0.79550             0.89191                 22.77%         22.77%

2:             0.69651             0.83457                 19.94%         42.71%

3:             0.58080             0.76210                 16.63%         59.34%

4:             0.44823             0.66950                 12.83%         72.17%

5:             0.31479             0.56106                  9.01%         81.18%

6:             0.20005             0.44727                  5.73%         86.91%

7:             0.18970             0.43554                  5.43%         92.34%

8:             0.14835             0.38516                  4.25%         96.59%

9:             0.06270             0.25041                  1.80%         98.38%

10:            0.04255             0.20628                  1.22%         99.60%

11:            0.01388             0.11781                  0.40%        100.00%

 

 

Row categories

anger             0.64729  -0.61905

jealousy          0.58478  -0.93674

sin               1.79765   0.82609

eternity         -0.98094   1.27341

happy            -0.54496  -1.52207

lonely            0.78469   0.95314

calm             -1.13363   1.35036

nostalgia        -1.14923   0.78936

home             -0.54496  -1.52207

love             -0.08410  -1.36867

purity           -0.57312   0.54473

dream            -1.08906  -0.52765

anxiety           1.47619   0.27158

fear              1.19250   0.22445

 

 

Column categories

red               0.39631  -0.51650

orange            0.01301  -1.43033

black             1.32263   0.39690

purple            1.15537  -0.39850

gray              1.47186   0.68156

violet            2.01552   0.98983

white            -0.87121   1.08926

grnble           -1.05862   0.79108

pink             -0.63434  -1.47993

yorange          -0.83685  -0.90057

blue             -0.69490   1.30793

green            -1.27977   1.28192

ygrn             -1.28851   0.94582

yellow           -1.22104  -0.63224

 

 

Row categories (weighted)

anger             0.57732  -0.51664

jealousy          0.52156  -0.78178

sin               1.60334   0.68943

eternity         -0.87491   1.06276

happy            -0.48606  -1.27028

lonely            0.69986   0.79547

calm             -1.01110   1.12698

nostalgia        -1.02501   0.65878

home             -0.48606  -1.27028

love             -0.07501  -1.14225

purity           -0.51117   0.45461

dream            -0.97133  -0.44037

anxiety           1.31662   0.22665

fear              1.06360   0.18732

 

 

Column categorie (weighted)s

red               0.35347  -0.43106

orange            0.01161  -1.19372

black             1.17966   0.33124

purple            1.03048  -0.33258

gray              1.31276   0.56881

violet            1.79765   0.82609

white            -0.77703   0.90907

grnble           -0.94419   0.66021

pink             -0.56577  -1.23511

yorange          -0.74639  -0.75159

blue             -0.61978   1.09157

green            -1.14143   1.06986

ygrn             -1.14923   0.78936

yellow           -1.08906  -0.52765

 

 

これらの出力の解釈は、岡本安晴「心理学データ分析と測定」の「第14章 質的データの可視化:双対尺度法」を参照されたい。

 

プログラムのPythonスクリプトのメイン部は以下のようになっている。変数名は岡本安晴「心理学データ分析と測定」の「第14章 質的データの可視化:双対尺度法」における説明に合わせてある。

 

import numpy as np

import matplotlib as plt

from mySVD import my_svd

from PlotDS import plot_ds

 

#       Input Data File Name

 

fn_in = input("Input data file = ")

 

f_in = open(fn_in, "r")

 

data_f = f_in.readlines()

f_in.close()

 

 

#       Output File Name

 

fn_out = input("Output data file = ")

f_out = open(fn_out, "w")

f_out.write("Input data file = " + fn_in + "\n\n")

 

n_dim = int(input('\nNumber of dimensions = '))

f_out.write('n_dim = {}\n'.format(n_dim))

 

pos = 0

while True:

    if (len(data_f[pos]) > 0):

        if data_f[pos][0] == '/':

            break

    pos += 1

 

pos += 1

s = data_f[pos].split()

n_row = int(s[0])

n_col = int(s[1])

print('\nn_row =', n_row, '   n_col =', n_col)

 

pos += 1

s = data_f[pos].split()

LabelCol = []

for v in s:

    LabelCol.append(v)

 

pos += 1

LabelRow = []

F = []

for i in range(n_row):

    F.append([])

    s = data_f[pos].split()

    LabelRow.append(s[0])

    for j in range(n_col):

        F[i].append(int(s[j + 1]))

    pos += 1

 

f_out.write('\nInput Data...\n')

f_out.write('\nLabelCol...\n')

for i in range(n_col):

    f_out.write(' {}'.format(LabelCol[i]))

f_out.write('\n\nLabelRow and F-data\n')

for i in range(n_row):

    f_out.write('{0:<10s}'.format(LabelRow[i]))

    for j in range(n_col):

        f_out.write('{0:3d}'.format(F[i][j]))

    f_out.write('\n')

 

fc = []

for j in range(n_col):

    sum = 0

    for i in range(n_row):

        sum += F[i][j]

    fc.append(sum)

 

ft = 0

for j in range(n_col):

    ft += fc[j]

 

fr = []

for i in range(n_row):

    sum = 0

    for j in range(n_col):

        sum += F[i][j]

    fr.append(sum)

 

Dc_invsqrt = np.zeros((n_col, n_col))

for j in range(n_col):

    Dc_invsqrt[j, j] = 1.0 / (fc[j] ** 0.5)

 

Dr_invsqrt = np.zeros((n_row, n_row))

for i in range(n_row):

    Dr_invsqrt[i, i] = 1.0 / (fr[i] ** 0.5)

 

Fmat = np.matrix(F)

 

G = Dr_invsqrt * Fmat * Dc_invsqrt

 

rnk, Lambda, v, u = my_svd(G)

 

if (rnk - 1) < n_dim:

    n_dim = rnk - 1

    f_out.write('\nrank of G = {0}\n'.format(rnk))

    f_out.write('n_dim was set to be {0}\n'.format(n_dim))

 

if rnk <= 1:

    print('\nRank of G is less than 2')

else:

    cor = []

    corr_sqr = []

    cum_corr_sqr = []

    sum = 0.0

    for i in range(1, rnk, 1):

        cor.append(Lambda[i])

        corr_sqr.append(Lambda[i]**2)

        sum += Lambda[i] ** 2

        cum_corr_sqr.append(sum)

 

    f_out.write('\n{0:<15}{1:<20}{2:<15}{3:>15}{4:>15}\n'.\

                format(' ', 'sq-cor-ratio', \

                       'coorelation', 'Prop.', 'Cum-Prop.'))

    for i in range(rnk - 1):

        f_out.write('{0:<15}{1:<20.5f}{2:<15.5f}{3:>15}{4:>15}\n'.\

                    format(('{0}:'.format(i + 1)),\

                           corr_sqr[i], cor[i],\

                           ('{0:.2f}%'.format(100.0 * corr_sqr[i] / cum_corr_sqr[rnk - 2])),\

                           ('{0:.2f}%'.format(100.0 * cum_corr_sqr[i] / cum_corr_sqr[rnk - 2]))))

 

    for t in range(n_dim):

        for j in range(n_col):

            u[t + 1][j] *= ft ** 0.5

        for i in range(n_row):

            v[t + 1][i] *= ft ** 0.5

 

    x = []

    y = []

    x_coord = []

    y_coord = []

    for t in range(n_dim):

        x.append([])

        x_coord.append([])

        for j in range(n_col):

            x[t].append(Dc_invsqrt[j, j] * u[t + 1][j])

            x_coord[t].append(Lambda[t + 1] * Dc_invsqrt[j, j] * u[t + 1][j])

        y.append([])

        y_coord.append([])

        for i in range(n_row):

            y[t].append(Dr_invsqrt[i, i] * v[t + 1][i])

            y_coord[t].append(Lambda[t + 1] * Dr_invsqrt[i, i] * v[t + 1][i])

 

    f_out.write('\n\nRow categories\n')

    for i in range(n_row):

        f_out.write('{0:<15}'.format(LabelRow[i]))

        for t in range(n_dim):

            f_out.write('{0:>10.5f}'.format(y[t][i]))

        f_out.write('\n')

 

    f_out.write('\n\nColumn categories\n')

    for j in range(n_col):

        f_out.write('{0:<15}'.format(LabelCol[j]))

        for t in range(n_dim):

            f_out.write('{0:>10.5f}'.format(x[t][j]))

        f_out.write('\n')

 

    f_out.write('\n\nRow categories (weighted)\n')

    for i in range(n_row):

        f_out.write('{0:<15}'.format(LabelRow[i]))

        for t in range(n_dim):

            f_out.write('{0:>10.5f}'.format(y_coord[t][i]))

        f_out.write('\n')

       

    f_out.write('\n\nColumn categorie (weighted)s\n')

    for j in range(n_col):

        f_out.write('{0:<15}'.format(LabelCol[j]))

        for t in range(n_dim):

            f_out.write('{0:>10.5f}'.format(x_coord[t][j]))

        f_out.write('\n')

 

    v_scale = 0.0

    for t in range(n_dim):

        for i in range(n_row):

            if v_scale < abs(y_coord[t][i]):

                v_scale = abs(y_coord[t][i])

        for j in range(n_col):

            if v_scale < abs(x_coord[t][j]):

                v_scale = abs(x_coord[t][j])

 

    v_scale *= 1.3

    if v_scale < 1.3:

        v_scale = 1.3                             

 

    while True:

        dim_x = int(input('\ndim-x = '))

        if dim_x < 1:

            break

        dim_y = int(input('dim-y = '))

        if dim_y < 1:

            break

        plot_ds( v_scale, dim_x, dim_y, n_dim, x_coord, LabelCol, \

                 n_col, y_coord, LabelRow, n_row, "Bi-Plot")

 

f_out.close()

print('\n', fn_out, 'was saved.')

 

 

 

Up