統計分析のPython実現ガイド

【概要】pandas、SciPy、Matplotlib、statsmodelsを用いた基礎的な統計分析(探索的データ解析と古典的仮説検定)のPython実装ガイドである。記述統計量、ヒストグラム、箱ひげ図、クロス集計表、相関分析、検定(t検定、一元配置分散分析、正規性検定、等分散性検定、カイ二乗独立性検定、Mann-Whitney U検定)、分散分析後の多重比較を扱う。各手法のPythonコードと実行結果を示す。

【本資料の前提】

【目次】

  1. 統計手法
  2. 記述統計量
  3. 用語リスト
  4. 統計処理の比較
  5. Pythonプログラム例
  6. 前準備
  7. 演習

統計手法

本資料で扱う手法を内容ごとに列挙する。

  1. 記述統計量
  2. ヒストグラム
  3. 箱ひげ図
  4. クロス集計表
  5. 相関分析(Pearson、Spearman)
  6. 検定(t検定、一元配置分散分析、正規性検定、等分散性検定、カイ二乗独立性検定、Mann-Whitney U検定)
  7. 分散分析後の多重比較(Tukey HSD)

記述統計量

記述統計量は、データセットの特徴を数値で要約する指標である。データ全体の特性を把握し、分析手法の選択に用いる。

基本的な統計量を以下に示す。

用語リスト

統計処理の比較

同じ統計処理を異なるツールで実行する際のコマンドを比較する。各ツールで既定の挙動が異なる場合がある(特にt検定)。

処理内容SPSSRPython (pandas/scipy/statsmodels)
記述統計量DESCRIPTIVESFREQUENCIESsummarysdskewnesskurtosisdf.describe()stats.skew()stats.kurtosis()
頻度表FREQUENCIEStablevalue_counts()
クロス集計表CROSSTABStablepd.crosstab()
集約AGGREGATEaggregategroupby().agg()
相関CORRELATIONScorcor.testdf.corr()stats.pearsonr()stats.spearmanr()
通常のt検定T-TESTt.test(..., var.equal=TRUE)stats.ttest_ind()(既定)
Welchのt検定T-TESTt.test(既定)stats.ttest_ind(equal_var=False)
等分散性検定EXAMINEleveneTeststats.levene()
一元配置分散分析ONEWAYaovoneway.teststats.f_oneway()
多重比較(Tukey)POSTHOCTukeyHSDpairwise_tukeyhsd()
カイ二乗独立性検定CROSSTABS /STATISTICSchisq.teststats.chi2_contingency()
Mann-Whitney U検定NPAR TESTSwilcox.teststats.mannwhitneyu()

Pythonのttest_ind()は既定が通常のt検定(equal_var=True)であり、Welch検定にはequal_var=Falseを指定する。Rのt.testは既定でWelch検定を行う。

Pythonプログラム例

記述統計・可視化では以下の成績データを用いる。クロス集計以降の検定では、手法の説明のため例ごとに別データを用いる。

科目受講者得点
国語A90
国語B80
算数A95
算数B90
理科A80

データフレームの作成

pandasのデータフレームは表形式データの基本構造である。ここでは成績データを辞書から作成し、データフレームへ変換する。

import pandas as pd

data = {
    '科目': ['国語', '国語', '算数', '算数', '理科'],
    '受講者': ['A', 'B', 'A', 'B', 'A'],
    '得点': [90, 80, 95, 90, 80]
}
df = pd.DataFrame(data)
df = df.astype({'科目': 'category', '受講者': 'category', '得点': 'int32'})

print("基本データ:")
print(df)
基本データフレームの出力結果
3列(科目・受講者・得点)5行のデータフレームが表示される。

個別の統計量計算

個々の統計量を個別に算出する。特定の統計量のみ必要な場合や、計算過程を確認したい場合に用いる。

import pandas as pd
from scipy import stats

data = {
    '科目': ['国語', '国語', '算数', '算数', '理科'],
    '受講者': ['A', 'B', 'A', 'B', 'A'],
    '得点': [90, 80, 95, 90, 80]
}
df = pd.DataFrame(data)
df = df.astype({'科目': 'category', '受講者': 'category', '得点': 'int32'})
scores = df['得点']

print("基本統計量:")
print(f"平均値: {scores.mean():.1f}")
print(f"標準偏差(ddof=1): {scores.std(ddof=1):.1f}")
print(f"中央値: {scores.median():.1f}")
print(f"最大値: {scores.max()}")
print(f"最小値: {scores.min()}")
print(f"第1四分位数: {scores.quantile(0.25):.1f}")
print(f"第3四分位数: {scores.quantile(0.75):.1f}")
print(f"歪度: {stats.skew(scores):.3f}")
print(f"尖度(超過尖度): {stats.kurtosis(scores):.3f}")
個別統計量の計算結果
平均、標準偏差、中央値、四分位数、歪度、尖度の各値が表示される。

総合的な統計分析

describe()は主要な記述統計量を一括算出する。stdは不偏(ddof=1)で出力される。

import pandas as pd

data = {
    '科目': ['国語', '国語', '算数', '算数', '理科'],
    '受講者': ['A', 'B', 'A', 'B', 'A'],
    '得点': [90, 80, 95, 90, 80]
}
df = pd.DataFrame(data)
df = df.astype({'科目': 'category', '受講者': 'category', '得点': 'int32'})

print("総合的な統計量:")
print(df['得点'].describe())

print("\n科目別の統計量:")
print(df.groupby('科目', observed=True)['得点'].describe())
describeメソッドによる統計量の出力結果
全体および科目別の count、mean、std、min、四分位数、max が表示される。

データの可視化(箱ひげ図とヒストグラム)

import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'Meiryo'
plt.rcParams['axes.unicode_minus'] = False

data = {
    '科目': ['国語', '国語', '算数', '算数', '理科'],
    '受講者': ['A', 'B', 'A', 'B', 'A'],
    '得点': [90, 80, 95, 90, 80]
}
df = pd.DataFrame(data)
df = df.astype({'科目': 'category', '受講者': 'category', '得点': 'int32'})

plt.figure(figsize=(10, 6))
df.boxplot(column='得点', by='科目')
plt.suptitle('')
plt.title('科目別得点分布', pad=15)
plt.ylabel('得点')
plt.grid(True)
plt.savefig('score_distribution.png', bbox_inches='tight')
plt.show()
plt.close()

plt.figure(figsize=(10, 6))
plt.hist(df['得点'], bins=range(0, 101, 10), edgecolor='black')
plt.title('得点分布のヒストグラム')
plt.xlabel('得点')
plt.ylabel('頻度')
plt.grid(True)
plt.savefig('score_histogram.png', bbox_inches='tight')
plt.show()
plt.close()
科目別得点分布の箱ひげ図
科目ごとの中央値・四分位範囲を示す箱ひげ図。
得点分布のヒストグラム
10点刻みの区間ごとの頻度を示すヒストグラム。

クロス集計表とカイ二乗独立性検定

クロス集計表は2つのカテゴリ変数の組み合わせごとの頻度を表で示す。カイ二乗検定で2変数が独立かを検定し、Cramér's Vで関連の強さ(効果量)を評価する。

import numpy as np
import pandas as pd
from scipy import stats

data = {
    'グループ1': ['a', 'b', 'c', 'a', 'b'],
    'グループ2': ['d', 'd', 'e', 'e', 'e']
}
df = pd.DataFrame(data)

cross_table = pd.crosstab(df['グループ1'], df['グループ2'])
print(cross_table)

cross_with_margins = pd.crosstab(df['グループ1'], df['グループ2'], margins=True)
print("\n合計付きクロス集計表(合計の名称はAll):")
print(cross_with_margins)

chi2, p, dof, expected = stats.chi2_contingency(cross_table)
print(f"\nカイ二乗統計量: {chi2:.3f}, p値: {p:.3f}, 自由度: {dof}")

n = cross_table.to_numpy().sum()
r, k = cross_table.shape
cramers_v = np.sqrt(chi2 / (n * (min(r, k) - 1)))
print(f"Cramér's V: {cramers_v:.3f}")

このデータは標本数が少なく期待度数も小さいため、検定結果は説明目的の参考値である。

クロス集計表とカイ二乗検定の出力結果
クロス集計表、合計付き表、カイ二乗統計量・p値・自由度・Cramér's Vが表示される。

相関分析

連続変数間の関係の強さを相関係数で評価する。Pearsonは線形関係、Spearmanは順位に基づく単調関係を測る。

import pandas as pd
from scipy import stats

df = pd.DataFrame({
    'x': [1, 2, 3, 4, 5, 6, 7, 8],
    'y': [2, 1, 4, 3, 6, 5, 8, 7]
})

print("Pearson相関行列:")
print(df.corr(method='pearson'))

r_p, p_p = stats.pearsonr(df['x'], df['y'])
r_s, p_s = stats.spearmanr(df['x'], df['y'])
print(f"\nPearson r: {r_p:.3f} (p={p_p:.3f})")
print(f"Spearman r: {r_s:.3f} (p={p_s:.3f})")
相関分析の出力結果
相関行列、Pearson・Spearman相関係数とそのp値が表示される。

等分散性の検定(Levene検定)とt検定

t検定の前に、Levene検定で2群の分散が等しいかを確認する。ここでは分散が等しくない場合にも適用できるWelchのt検定を実装する。

import numpy as np
from scipy import stats

np.random.seed(42)
group1 = np.random.normal(0, 1, 100)
group2 = np.random.normal(0.5, 1, 100)

lev_stat, lev_p = stats.levene(group1, group2)
print(f"Levene検定: 統計量={lev_stat:.3f}, p値={lev_p:.3f}")

res = stats.ttest_ind(group1, group2, equal_var=False)
print(f"t値: {res.statistic:.3f}")
print(f"p値: {res.pvalue:.3f}")
print(f"自由度: {res.df:.1f}")
等分散性検定とt検定の実行結果
Levene検定の統計量・p値、t値・p値・自由度が表示される。

Mann-Whitney U検定(ノンパラメトリック)

正規性が仮定できない場合、t検定の代わりに独立2群のMann-Whitney U検定を用いる(Wilcoxon順位和検定と等価)。

from scipy import stats

group1 = [12, 15, 14, 10, 13, 11]
group2 = [18, 20, 17, 19, 16, 22]

res = stats.mannwhitneyu(group1, group2, alternative='two-sided')
print(f"U統計量: {res.statistic:.3f}")
print(f"p値: {res.pvalue:.3f}")
Mann-Whitney U検定の実行結果
U統計量とp値が表示される。

一元配置分散分析と多重比較(Tukey HSD)

3群以上の平均値の差は一元配置分散分析で検定する。t検定は2群間の比較に限られるため、3群以上にはこの手法を用いる。有意だった場合、どの群間に差があるかをTukey HSD(多重比較)で調べる。

import numpy as np
from scipy import stats
from statsmodels.stats.multicomp import pairwise_tukeyhsd

group_a = [3.42, 3.84, 3.96, 3.76]
group_b = [3.17, 3.63, 3.47, 3.44, 3.39]
group_c = [3.64, 3.72, 3.91]

f_stat, p_value = stats.f_oneway(group_a, group_b, group_c)
print(f"F値: {f_stat:.3f}")
print(f"p値: {p_value:.3f}")

values = np.array(group_a + group_b + group_c)
labels = (['A'] * len(group_a)) + (['B'] * len(group_b)) + (['C'] * len(group_c))
tukey = pairwise_tukeyhsd(endog=values, groups=labels, alpha=0.05)
print(tukey)

各群が3〜5個と小標本のため、結果は説明目的の参考値である。

分散分析とTukey HSDの実行結果
F値・p値に続き、群の各ペアの平均差・p値・有意判定の表が表示される。

正規性の検定(Shapiro-Wilk検定)

t検定や分散分析などのパラメトリック検定は正規性を仮定するため、事前にShapiro-Wilk検定で確認する。

import numpy as np
from scipy import stats

np.random.seed(42)
data = np.random.normal(0, 1, 100)

res = stats.shapiro(data)
print(f"検定統計量(W): {res.statistic:.3f}")
print(f"p値: {res.pvalue:.3f}")
正規性検定の実行結果
Shapiro-Wilkの統計量Wとp値が表示される。

前準備

Python 3.12のインストール(Windows) [クリックして展開]

以下のいずれかの方法でPython 3.12をインストールする。インストール済みの場合、この手順は不要である。

方法1:wingetによるインストール

管理者権限のコマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトは、Windowsキーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択して起動する。

winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""
powershell -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; $m=[Environment]::GetEnvironmentVariable('Path','Machine'); if($m -notlike \"*$s*\") { [Environment]::SetEnvironmentVariable('Path', \"$p;$s;$m\", 'Machine') }"

--scope machineを指定すると全ユーザー向けにインストールされ、管理者権限を要する。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。

方法2:インストーラーによるインストール

  1. Python公式サイト(https://www.python.org/downloads/)にアクセスし、Windows用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面下部の「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する(チェックを入れないと、コマンドプロンプトからpythonコマンドを実行できない)。
  4. 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。

インストールの確認

コマンドプロンプトで以下を実行する。

python --version

バージョン番号(例:Python 3.12.x)が表示されれば成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。

AIエディタWindsurfのインストール(Windows) [クリックして展開]

Pythonプログラムの編集・実行にはAIエディタを用いる。ここではWindsurfをインストールする。インストール済みの場合、この手順は不要である。

管理者権限のコマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトは、Windowsキーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択して起動する。

winget install --scope machine --id Codeium.Windsurf -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --custom "/SP- /SUPPRESSMSGBOXES /NORESTART /CLOSEAPPLICATIONS /DIR=""C:\Program Files\Windsurf"" /MERGETASKS=!runcode,addtopath,associatewithfiles,!desktopicon"
powershell -Command "$env:Path=[System.Environment]::GetEnvironmentVariable('Path','Machine')+';'+[System.Environment]::GetEnvironmentVariable('Path','User'); windsurf --install-extension MS-CEINTL.vscode-language-pack-ja --force; windsurf --install-extension ms-python.python --force; windsurf --install-extension Codeium.windsurfPyright --force"

--scope machineを指定すると全ユーザー向けにインストールされ、管理者権限を要する。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。

Windsurf公式ページ:https://windsurf.com/

必要なPythonライブラリのインストール

  1. 管理者権限のコマンドプロンプトを起動する。Windowsキーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。
  2. 以下のコマンドで必要なライブラリをインストールする。
    pip install -U pandas numpy matplotlib scipy statsmodels

Matplotlibの日本語表示設定(Windows)

グラフ内の日本語が文字化けしないよう、描画前に一度だけ以下を設定する。Windows標準の「Meiryo」を用いる(無い場合は「Yu Gothic」または「MS Gothic」を指定する)。

import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'Meiryo'      # 'Yu Gothic' / 'MS Gothic' でも可
plt.rcParams['axes.unicode_minus'] = False  # マイナス記号の文字化け防止

演習

各演習は、対応するプログラム例のコードを実行し、結果を確認したうえで取り組む。コードは「Pythonプログラム例」の該当節を参照する。

演習1.記述統計量の算出

手順

  1. 「個別の統計量計算」のコードを実行する。
  2. 「得点」列の平均値、標準偏差、中央値、第1四分位数、第3四分位数、歪度、尖度を出力する。
  3. 標準偏差のddof0に変えて再実行し、ddof=1の場合と値を比較する。

ヒント

考察ポイント

演習2.箱ひげ図とヒストグラムの作成

手順

  1. 「データの可視化(箱ひげ図とヒストグラム)」のコードを実行する。
  2. 科目別の箱ひげ図と、得点全体のヒストグラムを出力する。
  3. ヒストグラムのbinsrange(0, 101, 5)に変えて再実行する。

ヒント

考察ポイント

演習3.クロス集計表とカイ二乗独立性検定

手順

  1. 「クロス集計表とカイ二乗独立性検定」のコードを実行する。
  2. クロス集計表、合計付きの表、カイ二乗統計量、p値、自由度、Cramér's Vを出力する。

ヒント

考察ポイント

演習4.相関分析

手順

  1. 「相関分析」のコードを実行する。
  2. Pearson相関行列、Pearson相関係数とp値、Spearman相関係数とp値を出力する。

ヒント

考察ポイント

演習5.等分散性検定とt検定

手順

  1. 「等分散性の検定(Levene検定)とt検定」のコードを実行する。
  2. Levene検定の統計量とp値、Welchのt検定のt値、p値、自由度を出力する。

ヒント

考察ポイント

演習6.分散分析と多重比較

手順

  1. 「一元配置分散分析と多重比較(Tukey HSD)」のコードを実行する。
  2. 分散分析のF値とp値、Tukey HSDの結果の表を出力する。

ヒント

考察ポイント

演習7.正規性の検定

手順

  1. 「正規性の検定(Shapiro-Wilk検定)」のコードを実行する。
  2. 正規分布から生成したデータに対し、統計量Wとp値を出力する。
  3. サンプル数を100から20に変えて再実行し、結果を比較する。

ヒント

考察ポイント