9. 身近なデータで学ぶ統計の基本

前回はデータの可視化について学びました。今回は、データを数値的に分析する統計の基礎を学んでいきましょう。

9.1 統計とは?クラスの平均点や身長のばらつきを例に考える

統計とは、データの特徴を数値で表現する方法です:

クラスの身長データ例

import numpy as np
import matplotlib.pyplot as plt

# クラスの身長データ例(cm)
heights = [165, 172, 168, 170, 175, 163, 169, 167, 173, 166]

# 基本的な統計量の計算
mean_height = np.mean(heights)     # 平均
max_height = np.max(heights)       # 最大値
min_height = np.min(heights)       # 最小値
range_height = max_height - min_height  # 範囲

print(f"平均身長:{mean_height:.1f}cm")
print(f"最大身長:{max_height}cm")
print(f"最小身長:{min_height}cm")
print(f"身長の範囲:{range_height}cm")

# ヒストグラムで分布を可視化
plt.figure(figsize=(10, 6))
plt.hist(heights, bins=5, edgecolor='black')
plt.title('クラスの身長分布')
plt.xlabel('身長 (cm)')
plt.ylabel('人数')
plt.grid(True)
plt.show()

9.2 平均・中央値・最頻値でデータの「中心」をつかむ

データの中心傾向を表す3つの指標について学びます:

テストの点数データ

import statistics

# テストの点数データ
scores = [85, 92, 78, 85, 90, 85, 88, 95, 73, 85]

# 3つの代表値を計算
mean_score = statistics.mean(scores)      # 平均値
median_score = statistics.median(scores)  # 中央値
mode_score = statistics.mode(scores)      # 最頻値

print(f"平均点:{mean_score:.1f}")
print(f"中央値:{median_score}")
print(f"最頻値:{mode_score}")

# それぞれの特徴
"""
1. 平均値:全データの合計を個数で割った値
   - 外れ値の影響を受けやすい
   - 最も一般的な代表値

2. 中央値:データを順に並べた時の真ん中の値
   - 外れ値の影響を受けにくい
   - データが偏っているときに有効

3. 最頻値:最も頻繁に現れる値
   - データの傾向を直感的に理解しやすい
   - 同じ値が複数ある場合に有効
"""

9.3 四分位数と箱ひげ図でデータの広がりを見てみる(成績分布など)

データの分布の特徴を視覚的に理解します:

テストの点数データ

import numpy as np
import matplotlib.pyplot as plt

# テストの点数データ
test_scores = [65, 70, 75, 78, 80, 82, 85, 88, 90, 92, 95]

# 四分位数の計算
q1 = np.percentile(test_scores, 25)  # 第1四分位数
q2 = np.percentile(test_scores, 50)  # 第2四分位数(中央値)
q3 = np.percentile(test_scores, 75)  # 第3四分位数

# 箱ひげ図の作成
plt.figure(figsize=(10, 6))
plt.boxplot(test_scores, vert=False)  # 横向きの箱ひげ図
plt.title('テスト点数の分布')
plt.xlabel('点数')
plt.grid(True)

# 四分位数の情報を表示
print(f"第1四分位数(下位25%):{q1}")
print(f"中央値(50%):{q2}")
print(f"第3四分位数(上位25%):{q3}")
print(f"四分位範囲:{q3 - q1}")

plt.show()

9.4 分散・標準偏差を使ってデータのばらつきを数値化する

データのばらつきを定量的に評価します:

テストの点数データ

import numpy as np

# 2つのクラスの点数データ
class_a = [82, 85, 88, 84, 87, 83, 86, 85, 84, 86]  # ばらつきが小さい
class_b = [65, 95, 75, 90, 85, 70, 95, 65, 80, 85]  # ばらつきが大きい

def analyze_scores(scores, class_name):
    mean = np.mean(scores)         # 平均
    var = np.var(scores)          # 分散
    std = np.std(scores)          # 標準偏差

    print(f"\n{class_name}の分析:")
    print(f"平均点:{mean:.1f}")
    print(f"分散:{var:.1f}")
    print(f"標準偏差:{std:.1f}")

    return mean, std

# 2つのクラスを分析
mean_a, std_a = analyze_scores(class_a, "クラスA")
mean_b, std_b = analyze_scores(class_b, "クラスB")

# ヒストグラムで比較
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.hist(class_a, bins=5, edgecolor='black')
plt.title('クラスAの点数分布')
plt.xlabel('点数')
plt.ylabel('人数')

plt.subplot(1, 2, 2)
plt.hist(class_b, bins=5, edgecolor='black')
plt.title('クラスBの点数分布')
plt.xlabel('点数')
plt.ylabel('人数')

plt.tight_layout()
plt.show()

9.5 散布図で 2 つのデータの関係を調べよう(勉強時間とテスト点数)

2つの変数の関係を視覚化します:

テストの点数データ

import matplotlib.pyplot as plt

# 勉強時間(時間)とテスト点数のデータ
study_hours = [2, 3, 1.5, 4, 2.5, 3.5, 3, 4.5, 2, 5]
test_scores = [65, 75, 60, 85, 70, 80, 75, 90, 65, 95]

# 散布図の作成
plt.figure(figsize=(10, 6))
plt.scatter(study_hours, test_scores)
plt.title('勉強時間とテスト点数の関係')
plt.xlabel('勉強時間(時間)')
plt.ylabel('テスト点数')
plt.grid(True)

# 平均点で線を引く
avg_score = np.mean(test_scores)
plt.axhline(y=avg_score, color='r', linestyle='--',
           label=f'平均点:{avg_score:.1f}')
plt.legend()

plt.show()

9.6 相関係数で「強い関係」か「弱い関係」か判断する

2つの変数の関係の強さを数値化します:

テストの点数データ

import numpy as np
from scipy import stats

# データ例
x = [2, 3, 1.5, 4, 2.5, 3.5, 3, 4.5, 2, 5]  # 勉強時間
y = [65, 75, 60, 85, 70, 80, 75, 90, 65, 95] # テスト点数

# 相関係数の計算
correlation = np.corrcoef(x, y)[0, 1]
print(f"相関係数:{correlation:.3f}")

# 相関係数の解釈
def interpret_correlation(corr):
    if abs(corr) < 0.2:
        return "ほとんど関係がない"
    elif abs(corr) < 0.4:
        return "弱い関係がある"
    elif abs(corr) < 0.7:
        return "中程度の関係がある"
    else:
        return "強い関係がある"

print(f"解釈:{interpret_correlation(correlation)}")

# 散布図と回帰直線
plt.figure(figsize=(10, 6))
plt.scatter(x, y)

# 回帰直線
slope, intercept = np.polyfit(x, y, 1)
line_x = np.array([min(x), max(x)])
line_y = slope * line_x + intercept
plt.plot(line_x, line_y, 'r--',
         label=f'相関係数: {correlation:.3f}')

plt.title('勉強時間とテスト点数の関係')
plt.xlabel('勉強時間(時間)')
plt.ylabel('テスト点数')
plt.legend()
plt.grid(True)
plt.show()

9.7 回帰直線で「未来」を予測してみる(勉強時間から点数を予測)

データから将来の値を予測する方法を学びます:

テストの点数データ

from sklearn.linear_model import LinearRegression
import numpy as np

# データの準備
study_hours = np.array([2, 3, 1.5, 4, 2.5, 3.5, 3, 4.5, 2, 5]).reshape(-1, 1)
test_scores = np.array([65, 75, 60, 85, 70, 80, 75, 90, 65, 95])

# 回帰モデルの作成と学習
model = LinearRegression()
model.fit(study_hours, test_scores)

# モデルの係数を確認
print(f"傾き:{model.coef_[0]:.2f}")
print(f"切片:{model.intercept_:.2f}")

# 新しい勉強時間での点数予測
new_hours = np.array([[6]])  # 6時間勉強した場合
predicted_score = model.predict(new_hours)
print(f"\n6時間勉強した場合の予測点数:{predicted_score[0]:.1f}点")

# 予測の可視化
plt.figure(figsize=(10, 6))
plt.scatter(study_hours, test_scores, label='実データ')

# 回帰直線
x_range = np.linspace(0, 7, 100).reshape(-1, 1)
y_pred = model.predict(x_range)
plt.plot(x_range, y_pred, 'r--', label='予測ライン')

plt.title('勉強時間と点数の関係(予測付き)')
plt.xlabel('勉強時間(時間)')
plt.ylabel('テスト点数')
plt.legend()
plt.grid(True)
plt.show()

課題 1. クラス全員の身長データから平均・中央値・標準偏差を計算して特徴をまとめる

テストの点数データ

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

def analyze_height_data():
    # 身長データ(cm)
    heights = [158, 160, 165, 168, 170, 172, 175, 163, 167, 169,
              164, 166, 171, 173, 168, 167, 165, 170, 172, 169]

    # 基本統計量の計算
    mean = np.mean(heights)
    median = np.median(heights)
    std = np.std(heights)
    mode = stats.mode(heights)[0][0]

    # 結果の表示
    print("身長データの分析結果:")
    print(f"平均値:{mean:.1f}cm")
    print(f"中央値:{median:.1f}cm")
    print(f"最頻値:{mode}cm")
    print(f"標準偏差:{std:.1f}cm")

    # ヒストグラムと正規分布の重ね描き
    plt.figure(figsize=(10, 6))
    plt.hist(heights, bins=10, density=True, alpha=0.7,
             label='実データ')

    # 正規分布曲線
    x = np.linspace(min(heights), max(heights), 100)
    y = stats.norm.pdf(x, mean, std)
    plt.plot(x, y, 'r-', label='正規分布')

    plt.title('クラスの身長分布')
    plt.xlabel('身長 (cm)')
    plt.ylabel('頻度')
    plt.legend()
    plt.grid(True)
    plt.show()

# 分析の実行
analyze_height_data()

課題 2. 勉強時間とテスト点数のデータで散布図を描き、相関係数や回帰直線を求めて関係を考える

テストの点数データ

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

def analyze_study_data():
    # 1週間の勉強時間(時間)とテスト点数のデータ
    study_hours = np.array([1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5,
                           2.0, 2.5, 3.0, 3.5, 4.0, 3.0, 3.5]).reshape(-1, 1)
    test_scores = np.array([65, 70, 75, 80, 85, 90, 95,
                           68, 72, 78, 82, 88, 77, 83])

    # 相関係数の計算
    correlation = np.corrcoef(study_hours.flatten(), test_scores)[0, 1]
    print(f"相関係数:{correlation:.3f}")

    # 回帰分析
    model = LinearRegression()
    model.fit(study_hours, test_scores)

    # 回帰直線の係数
    slope = model.coef_[0]
    intercept = model.intercept_
    print(f"\n回帰直線: y = {slope:.1f}x + {intercept:.1f}")
    print(f"傾き:{slope:.1f}(1時間勉強時間が増えると点数が{slope:.1f}点上がる)")

    # 予測例
    study_time = 5.0
    predicted_score = model.predict([[study_time]])[0]
    print(f"\n{study_time}時間勉強した場合の予測点数:{predicted_score:.1f}点")

    # グラフの作成
    plt.figure(figsize=(10, 6))

    # 散布図
    plt.scatter(study_hours, test_scores, color='blue',
               label='実データ', alpha=0.7)

    # 回帰直線
    x_range = np.linspace(1, 5, 100).reshape(-1, 1)
    y_pred = model.predict(x_range)
    plt.plot(x_range, y_pred, 'r--',
            label=f'回帰直線 (相関係数: {correlation:.3f})')

    # グラフの装飾
    plt.title('勉強時間とテスト点数の関係')
    plt.xlabel('勉強時間(時間)')
    plt.ylabel('テスト点数')
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.legend()
    plt.show()

# 分析の実行
analyze_study_data()

# チャレンジ:
# - 複数教科のデータで同じ分析を行う
# - 1ヶ月分のデータで傾向を調べる
# - 予測の信頼区間も計算してみる

まとめ

この章で学んだこと:

  1. データの中心を表す3つの指標

    • 平均値:全体の代表的な値
    • 中央値:データを順に並べた時の中央
    • 最頻値:最も多く出現する値
  2. データのばらつきを表す指標

    • 分散:データのばらつきの大きさ
    • 標準偏差:ばらつきを元のデータと同じ単位で表現
    • 四分位数:データを4等分する値
  3. データの関係性を調べる方法

    • 散布図:2つの変数の関係を視覚化
    • 相関係数:関係の強さを-1から1の数値で表現
    • 回帰直線:データの傾向を直線で表現
  4. 実践的な活用法

    • 成績データの分析
    • 身長・体重などの身体測定データの特徴把握
    • 学習時間と成績の関係分析
    • 将来の予測

次の章では、Pythonの便利な活用方法について学び、より実践的なプログラミングスキルを身につけていきます!