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ヶ月分のデータで傾向を調べる
# - 予測の信頼区間も計算してみる
まとめ
この章で学んだこと:
-
データの中心を表す3つの指標
- 平均値:全体の代表的な値
- 中央値:データを順に並べた時の中央
- 最頻値:最も多く出現する値
-
データのばらつきを表す指標
- 分散:データのばらつきの大きさ
- 標準偏差:ばらつきを元のデータと同じ単位で表現
- 四分位数:データを4等分する値
-
データの関係性を調べる方法
- 散布図:2つの変数の関係を視覚化
- 相関係数:関係の強さを-1から1の数値で表現
- 回帰直線:データの傾向を直線で表現
-
実践的な活用法
- 成績データの分析
- 身長・体重などの身体測定データの特徴把握
- 学習時間と成績の関係分析
- 将来の予測
次の章では、Pythonの便利な活用方法について学び、より実践的なプログラミングスキルを身につけていきます!