Up

平均値の条件差検定のシミュレーション

 

データを母集団からのランダムなサンプリングにより得られたと考えるとき、得られるデータとその統計量はサンプリングごとに変動する。変動の様子を見るシミュレーションプログラムをリスト1に示すように作成してみた。プログラムファイルは、圧縮ファイルsimu2popfile.zipにまとめたので、ダウンロード展開すれば自由に利用できる。ただし、これはWindows用である。CentOS Stream 9などのOS用は、このウェブサイトの後半で説明している。

2つのデータセットx1およびx2がそれぞれ平均および、標準偏差およびの正規分布からの個および個のサンプルであるとする。

このときのデータのサンプリングを次のスクリプトで行った。

 

    x1 = ss.norm.rvs(mu1, sgm1, n1)

    x2 = ss.norm.rvs(mu2, sgm2, n2)

 

このデータに対して、平均値と標準偏差を次のスクリプトで求めた。

 

    m1_hat = np.mean(x1)

    s1_hat = np.std(x1)

    m2_hat = np.mean(x2)

    s2_hat = np.std(x2)

 

また、t検定の値を、次のスクリプトで求めた。

 

    r = ss.ttest_ind(x1, x2)                       #   Student

    rw = ss.ttest_ind(x1, x2, equal_var = False)   #   Welch

 

サンプルされたデータと統計量、検定結果などの情報は、ライブラリPyGameを利用してシミュレーションのウィンドウ画面上に表示した。PyGameのインストールは、コマンド

 

pip install pygame

 

の実行で簡単に行うことができた。

リスト1では、表示ウィンドウを前面に出すためにモジュールwin32guiを用いているが、これはpywin32のインストールによりimportできるようになる。pywin32のインストールは、まず次のコマンドを実行する。

 

pip install pywin32

 

続いて、次のコマンドをPythonのインストールされているフォルダに移って実行する。

 

C:\Pythonのインストールされているフォルダ\python.exe Scripts\pywin32_postinstall.py -install

 

これで、再起動後、次のようにwin32guiimportできる。

 

import win32gui

 

ただし、Anacondaの場合は、上のpipによるインストールで完了である。\python.exe Scripts\pywin32_postinstall.py -installによるインストール作業は不要である。

 

 

リスト1のプログラムを実行すると、まず、2つの母集団の平均と標準偏差、およびそれぞれのサンプルサイズの入力が求められる(図1)。

図1

 

図1の状態で、求められたすべての値を設定すると、シミュレーションが始まるが、その前に図2のウィンドウが表示される。

図2

 

これは、表示ウィンドウにキーボード入力が向けられるようにするためである。

図2のウィンドウの画面は、2回クリックすると消されて、シミュレーションが始まり、計算結果が図3のように表示される。

図3

 

最上段に、標準t検定の結果とWelchのt検定の結果が表示されている。分散が等しいかどうか不明の場合は、Welchのt検定を用いる方がよいと思われる。

次の段に、サンプルx1の母集団パラメータと統計量が表示され、x1の分布が緑の小円で描かれている。

その下の段には、サンプルx2の母集団パラメータと統計量、およびx2の分布が青の小円で描かれている。

最下段に、キーの選択が示されている。Nキーを押すと、次のサンプリングが行われて、結果が表示される。

下図に、Nキーを押して、さらに4回のシミュレーションを行った例を示す。

 

 

 

Eキー押すと、プログラムの実行終了である。

 

 

なお、Pythonによるデータ分析の入門書<岡本安晴「いまさら聞けないPythonでデータ分析」丸善出版>を上梓した。

 

 

リスト1 2つの正規分布からのサンプリング(simu_2pop.py

 

import pygame as pg

import scipy.stats as ss

import numpy as np

from win32gui import SetWindowPos, SetFocus

import win32con

 

mu1 = float(input('mu_1 = '))

mu2 = float(input('mu_2 = '))

sgm1 = float(input('sgm_1 = '))

sgm2 = float(input('sgm_2 = '))

n1 = int(input('n_1 = '))

n2 = int(input('n_2 = '))

wt = int(3000 / (n1 + n2)) + 1

 

pg.init()

pg.display.set_caption('Two Independent Sampling')

screen = pg.display.set_mode(size=(800, 600))

SetWindowPos(pg.display.get_wm_info()['window'], -1, 0, 0, 0, 0,

             win32con.SWP_ASYNCWINDOWPOS | win32con.SWP_NOMOVE |

             win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)

 

screen.fill((255,255,255))

pg.display.flip()

my_font = pg.font.SysFont(None, 32)

my_font_L = pg.font.SysFont(None, 40)

img_str_L = my_font_L.render('Next -> key N,    End -> key E', True,

                             (0,0,0), (255,255,255))

rect_str_L = img_str_L.get_rect()

 

my_font_L1 = pg.font.SysFont(None, 60)

img_str_mouse = my_font_L1.render('Click here, twice', True,

                             (0,0,0), (255,255,255))

rect_str_mouse = img_str_mouse.get_rect()

screen.blit(img_str_mouse, (400 - rect_str_mouse.width//2,

                            300 - rect_str_mouse.height//2))

pg.display.flip()

ck1 = True

while ck1:

    for e in pg.event.get():

        if e.type == pg.MOUSEBUTTONDOWN:

            ck1 = False

 

ck = True

while ck:

    x1 = ss.norm.rvs(mu1, sgm1, n1)

    x2 = ss.norm.rvs(mu2, sgm2, n2)

 

    min_x = np.min(x1) if np.min(x1) < np.min(x2) else np.min(x2)

    max_x = np.max(x1) if np.max(x1) > np.max(x2) else np.max(x2)

 

    def scale_x(v):

        return int(30 + 740 * (v - min_x) / (max_x - min_x))

 

    screen.fill((255,255,255))

 

    for i in range(n1):

        pg.draw.circle(screen, (0,200,0), (scale_x(x1[i]), 250), 10, 3)

        pg.display.flip()

        pg.time.wait(wt)

 

    m1_hat = np.mean(x1)

    s1_hat = np.std(x1)

    str1 = f'mu1 = {mu1}, sgm1 = {sgm1},' + \

            f'  m1_hat = {m1_hat:.2f}, s1_hat = {s1_hat:.2f}'

    img_str1 = my_font.render(str1, True, (0,0,0), (255,255,255))

    screen.blit(img_str1, (50, 150))

   

       

    for i in range(n2):

        pg.draw.circle(screen, (0,0,200), (scale_x(x2[i]), 400), 10, 3)

        pg.display.flip()

        pg.time.wait(wt)

 

 

    m2_hat = np.mean(x2)

    s2_hat = np.std(x2)

    str2 = f'mu2 = {mu2}, sgm2 = {sgm2},' + \

            f'  m2_hat = {m2_hat:.2f}, s2_hat = {s2_hat:.2f}'

    img_str2 = my_font.render(str2, True, (0,0,0), (255,255,255))

    screen.blit(img_str2, (50, 330))

 

    r = ss.ttest_ind(x1, x2)                       #   Student

    rw = ss.ttest_ind(x1, x2, equal_var = False)   #   Welch

    strg = f't = {r.statistic:.3f}, p = {r.pvalue:.5f}, df = {r.df:.0f}'

    strgw =  f"t' = {rw.statistic:.3f}, p' = {rw.pvalue:.5f}, df' = {rw.df:.3f}"

    img_strg = my_font.render(strg, True, (0,0,0), (255,255,255))

    screen.blit(img_strg, (400 - (img_strg.get_rect().width//2), 10))

    img_strgw = my_font.render(strgw, True, (0,0,0), (255,255,255))

    screen.blit(img_strgw, (400 - (img_strgw.get_rect().width//2), 40))

 

    screen.blit(img_str_L, (400 - (rect_str_L.width//2),

                                   600 - (rect_str_L.height*2)) )

    pg.display.flip()

 

    pg.event.set_grab(True)

    ck1 = True

    while ck1:

        for e in pg.event.get():

            if e.type == pg.KEYDOWN:

                if e.key == pg.K_n:

                    ck1 = False

                elif e.key == pg.K_e:

                    ck = False

                    ck1 = False

 

pg.quit()

 

 

 

LinuxUbuntuCentOS Stream 9など)の場合

 

 

2つのデータセットx1およびx2がそれぞれ平均および、標準偏差およびの正規分布からの個および個のサンプルであるとする。

このときのデータのサンプリングを次のスクリプトで行った。

 

    x1 = ss.norm.rvs(mu1, sgm1, n1)

    x2 = ss.norm.rvs(mu2, sgm2, n2)

 

このデータに対して、平均値と標準偏差を次のスクリプトで求めた。

 

    m1_hat = np.mean(x1)

    s1_hat = np.std(x1)

    m2_hat = np.mean(x2)

    s2_hat = np.std(x2)

 

また、t検定の値を、次のスクリプトで求めた。

 

    r = ss.ttest_ind(x1, x2)                       #   Student

    rw = ss.ttest_ind(x1, x2, equal_var = False)   #   Welch

 

サンプルされたデータと統計量、検定結果などの情報は、ライブラリPyGameを利用してシミュレーションのウィンドウ画面上に表示した。PyGameのインストールは、コマンド

 

pip install pygame

 

の実行で簡単に行うことができた。

 

シミュレーションはリストのスクリプトで行ったが、スクリプトファイルは圧縮ファイルsimu2pop_cos.zipにまとめた。

リスト2のプログラムを実行すると、まず、2つの母集団の平均と標準偏差、およびそれぞれのサンプルサイズの入力が求められる。

 

mu_1 = 70

mu_2 = 80

sgm_1 = 10

sgm_2 = 12

n_1 = 50

n_2 = 55

 

これらの値の設定後、シミュレーションが始まる。シミュレーションの結果は、下図のように表示される。

 

最上段に、標準t検定の結果とWelchのt検定の結果が表示されている。分散が等しいかどうか不明の場合は、Welchのt検定を用いる方がよいと思われる。

次の段に、サンプルx1の母集団パラメータと統計量が表示され、x1の分布が緑の小円で描かれている。

その下の段には、サンプルx2の母集団パラメータと統計量、およびx2の分布が青の小円で描かれている。

最下段に、キーの選択が示されている。Nキーを押すと、次のサンプリングが行われて、結果が表示される。

Eキー押すと、プログラムの実行終了である。

 

リスト2のスクリプトは、CentOS Stream 9Python 3.12.3/Anacondaで実行したが、Ubuntu 24/WSL/Windows 10Python 3.12.3/Anacondaでも実行できた。

 

 

なお、Pythonによるデータ分析の入門書<岡本安晴「いまさら聞けないPythonでデータ分析」丸善出版>を上梓した。

 

 

 

リスト2 LinuxUbuntuCentOS Stream 9など)用サンプルスクリプト

 

import pygame as pg

import scipy.stats as ss

import numpy as np

 

mu1 = float(input('mu_1 = '))

mu2 = float(input('mu_2 = '))

sgm1 = float(input('sgm_1 = '))

sgm2 = float(input('sgm_2 = '))

n1 = int(input('n_1 = '))

n2 = int(input('n_2 = '))

wt = int(3000 / (n1 + n2)) + 1

 

pg.init()

pg.display.set_caption('Two Independent Sampling')

screen = pg.display.set_mode(size=(800, 600))

 

screen.fill((255,255,255))

pg.display.flip()

my_font = pg.font.SysFont(None, 32)

my_font_L = pg.font.SysFont(None, 40)

img_str_L = my_font_L.render('Next -> key N,    End -> key E', True,

                             (0,0,0), (255,255,255))

rect_str_L = img_str_L.get_rect()

 

ck = True

while ck:

    x1 = ss.norm.rvs(mu1, sgm1, n1)

    x2 = ss.norm.rvs(mu2, sgm2, n2)

 

    min_x = np.min(x1) if np.min(x1) < np.min(x2) else np.min(x2)

    max_x = np.max(x1) if np.max(x1) > np.max(x2) else np.max(x2)

 

    def scale_x(v):

        return int(30 + 740 * (v - min_x) / (max_x - min_x))

 

    screen.fill((255,255,255))

 

    for i in range(n1):

        pg.draw.circle(screen, (0,200,0), (scale_x(x1[i]), 250), 10, 3)

        pg.display.flip()

        pg.time.wait(wt)

 

    m1_hat = np.mean(x1)

    s1_hat = np.std(x1)

    str1 = f'mu1 = {mu1}, sgm1 = {sgm1},' + \

            f'  m1_hat = {m1_hat:.2f}, s1_hat = {s1_hat:.2f}'

    img_str1 = my_font.render(str1, True, (0,0,0), (255,255,255))

    screen.blit(img_str1, (50, 150))

   

       

    for i in range(n2):

        pg.draw.circle(screen, (0,0,200), (scale_x(x2[i]), 400), 10, 3)

        pg.display.flip()

        pg.time.wait(wt)

 

 

    m2_hat = np.mean(x2)

    s2_hat = np.std(x2)

    str2 = f'mu2 = {mu2}, sgm2 = {sgm2},' + \

            f'  m2_hat = {m2_hat:.2f}, s2_hat = {s2_hat:.2f}'

    img_str2 = my_font.render(str2, True, (0,0,0), (255,255,255))

    screen.blit(img_str2, (50, 330))

 

    r = ss.ttest_ind(x1, x2)                       #   Student

    rw = ss.ttest_ind(x1, x2, equal_var = False)   #   Welch

    strg = f't = {r.statistic:.3f}, p = {r.pvalue:.5f}, df = {r.df:.0f}'

    strgw =  f"t' = {rw.statistic:.3f}, p' = {rw.pvalue:.5f}, df' = {rw.df:.3f}"

    img_strg = my_font.render(strg, True, (0,0,0), (255,255,255))

    screen.blit(img_strg, (400 - (img_strg.get_rect().width//2), 10))

    img_strgw = my_font.render(strgw, True, (0,0,0), (255,255,255))

    screen.blit(img_strgw, (400 - (img_strgw.get_rect().width//2), 40))

 

    screen.blit(img_str_L, (400 - (rect_str_L.width//2),

                                   600 - (rect_str_L.height*2)) )

    pg.display.flip()

 

    pg.event.set_grab(True)

    ck1 = True

    while ck1:

        for e in pg.event.get():

            if e.type == pg.KEYDOWN:

                if e.key == pg.K_n:

                    ck1 = False

                elif e.key == pg.K_e:

                    ck = False

                    ck1 = False

 

pg.quit()

 

 

 

Home