📚 背景知識(読んでから問題へ)
numpyは「数値計算に特化したPythonライブラリ」で、Kaggleでは必須ツールです。
普通のPythonリスト [1, 2, 3] と numpy配列 np.array([1, 2, 3]) の最大の違いは速さと便利さです。
- 速さ: numpyは内部でC言語で動いているので、Pythonのループより100倍以上速いことがある
- 便利さ: 配列全体に一度に計算を適用できる(ベクトル演算)
# Pythonリストの場合:ループが必要
scores = [80, 65, 90, 72, 88]
doubled = [x * 2 for x in scores] # 全要素を2倍にするのに1行必要
# numpyの場合:配列全体に一度に適用
import numpy as np
scores = np.array([80, 65, 90, 72, 88])
doubled = scores * 2 # 全要素が一度に2倍になる!
よく使うnumpy操作:
| 操作 | コード | 説明 |
|---|---|---|
| 配列作成 | np.array([1,2,3]) | リストから配列を作る |
| 形状確認 | arr.shape | 行数・列数を確認 |
| 平均 | np.mean(arr) | 全要素の平均 |
| 合計 | np.sum(arr) | 全要素の合計 |
| 最大/最小 | np.max(arr), np.min(arr) | 最大値・最小値 |
| 条件抽出 | arr[arr > 60] | 条件に合う要素だけ取り出す |
| 連番生成 | np.arange(0, 10, 2) | 0から10未満を2刻みで生成 |
| ゼロ配列 | np.zeros((3, 4)) | 3行4列のゼロ埋め配列 |
📝 問題
以下のシナリオに従って、numpyを使って計算してください。
シナリオ: Kaggleコンペの試験スコア分析
あなたは機械学習コンペのスコアデータを持っています。参加者10人のスコアが与えられています。
import numpy as np
scores = np.array([0.721, 0.689, 0.743, 0.812, 0.634,
0.756, 0.701, 0.829, 0.667, 0.778])
以下の5つのタスクをすべてこなしてください:
- 基本統計を計算: 平均・最大値・最小値・標準偏差を求めて表示
- 正規化: スコアを0〜1の範囲に正規化(min-max正規化)してください
- 公式:
(値 - 最小値) / (最大値 - 最小値)
- フィルタリング: スコアが平均より高い参加者のスコアだけを取り出す
- ランキング: スコアを降順(高い順)に並べ替えて表示
- 2次元配列: 上位5人のスコアと下位5人のスコアを2行5列の2次元配列に変換し、各行の平均を計算
期待される出力イメージ:
▶ 出力を見る
=== 基本統計 ===
平均: 0.7330
最大: 0.8290
最小: 0.6340
標準偏差: 0.0586
=== 正規化後スコア ===
[0.449 0.284 0.565 0.917 0.000 0.634 0.344 1.000 0.171 0.738]
=== 平均より高いスコア ===
[0.743 0.812 0.756 0.829 0.778]
=== 降順ランキング ===
[0.829 0.812 0.778 0.756 0.743 0.721 0.701 0.689 0.667 0.634]
=== 2次元配列の各行平均 ===
上位5人平均: 0.7836
下位5人平均: 0.6824🔍 ヒント(段階的開示)
ヒント1(方向性)
各タスクはnumpyの関数1〜2つで解けます。まずタスクごとに使う関数を考えてみましょう。numpyの関数は np.関数名(配列) か 配列.関数名() の形で呼びます。
ヒント2(アプローチ)
- 基本統計:
np.mean(),np.max(),np.min(),np.std() - 正規化: 引き算と割り算を組み合わせるだけ(numpyは配列全体に一度に演算できる)
- フィルタリング:
scores[scores > 条件]の形(ブールインデックス) - 並べ替え:
np.sort()はデフォルト昇順なので逆順にする工夫が必要([::-1]) - 2次元配列:
arr.reshape(行数, 列数)で形を変えられる
ヒント3(コード骨格)
import numpy as np
scores = np.array([0.721, 0.689, 0.743, 0.812, 0.634,
0.756, 0.701, 0.829, 0.667, 0.778])
# 1. 基本統計
mean_score = np.mean(scores)
# ... max, min, std も同様に
# 2. 正規化
normalized = (scores - np.min(scores)) / (np.max(scores) - np.min(scores))
# 3. フィルタリング(ブールインデックス)
above_mean = scores[scores > mean_score]
# 4. 降順ソート
sorted_scores = np.sort(scores)[::-1]
# 5. 2次元配列
sorted_asc = np.sort(scores) # 昇順でソート
top5 = sorted_asc[-5:] # 上位5つ(末尾5つ)
bottom5 = sorted_asc[:5] # 下位5つ(先頭5つ)
matrix = np.array([top5, bottom5]) # 2行に積み上げ
row_means = np.mean(matrix, axis=1) # axis=1 は横方向(行ごと)の平均
✅ 模範解答
import numpy as np
scores = np.array([0.721, 0.689, 0.743, 0.812, 0.634,
0.756, 0.701, 0.829, 0.667, 0.778])
# 1. 基本統計を計算
mean_score = np.mean(scores)
max_score = np.max(scores)
min_score = np.min(scores)
std_score = np.std(scores)
print("=== 基本統計 ===")
print(f"平均: {mean_score:.4f}")
print(f"最大: {max_score:.4f}")
print(f"最小: {min_score:.4f}")
print(f"標準偏差: {std_score:.4f}")
# 2. min-max正規化
normalized = (scores - min_score) / (max_score - min_score)
print("\n=== 正規化後スコア ===")
print(np.round(normalized, 3))
# 3. 平均より高いスコアをフィルタリング
above_mean = scores[scores > mean_score]
print("\n=== 平均より高いスコア ===")
print(above_mean)
# 4. 降順ランキング
sorted_desc = np.sort(scores)[::-1]
print("\n=== 降順ランキング ===")
print(sorted_desc)
# 5. 2次元配列と行平均
sorted_asc = np.sort(scores) # 昇順ソート
top5 = sorted_asc[-5:] # 上位5人(高スコア)
bottom5 = sorted_asc[:5] # 下位5人(低スコア)
matrix = np.array([top5, bottom5]) # shape: (2, 5)
row_means = np.mean(matrix, axis=1) # 各行(上位/下位)の平均
print("\n=== 2次元配列の各行平均 ===")
print(f"上位5人平均: {row_means[0]:.4f}")
print(f"下位5人平均: {row_means[1]:.4f}")
🪜 Step-by-Step 解説
mean_score = np.mean(scores) # 全要素を足して個数で割る
max_score = np.max(scores) # 最大値
min_score = np.min(scores) # 最小値
std_score = np.std(scores) # 標準偏差(バラつきの大きさ)
numpyの関数は「配列全体を一発で計算」してくれます。Pythonのループは不要。
normalized = (scores - min_score) / (max_score - min_score)
scores - min_score: 各スコアから最小値を引く(最小値が0になる)/ (maxscore - minscore): 範囲で割る(最大値が1になる)
numpyでは scores - 0.634 と書くと配列の全要素から0.634が引かれます。これをブロードキャストと言います。
above_mean = scores[scores > mean_score]
scores > mean_score は [True, False, True, True, ...] のような True/False の配列を返します。これを scores[...] に渡すと、Trueの位置だけ取り出せます。
sorted_desc = np.sort(scores)[::-1]
np.sort() はデフォルトで昇順(小→大)なので、[::-1] で逆順にします。[::-1] は「最後から最初まで逆に取り出す」Pythonのスライス記法です。
matrix = np.array([top5, bottom5]) # shape: (2, 5) = 2行5列
row_means = np.mean(matrix, axis=1) # axis=1 = 横方向(列をまたいで)の平均
axis=0 は縦方向(行をまたいで)、axis=1 は横方向(列をまたいで)の演算です。2次元配列でよく混乱するポイントなので覚えておきましょう。
📐 数学・統計の補足(文系向け)
min-max正規化とは?
異なるスケールのデータを0〜1に揃える変換です。例えば身長(cm)と体重(kg)を一緒に扱うとき、数字の大きい身長ばかりが影響を持ちすぎないよう揃えます。
標準偏差のおさらい
「スコアのバラつきがどれくらいか」を表す数字。標準偏差0.0586 = スコアが平均からだいたい±0.06ぐらいの範囲に収まっているということ。
🏆 Kaggleでの実践的な使い方
- スコア正規化: 異なる特徴量(例: 年齢と年収)を同じスケールに揃えるために前処理で必須
- ブールインデックス: 特定条件のデータを素早く抽出(外れ値の除外など)
- axis引数: 集計方向の指定はGroupByやモデル出力の集計で頻出
- np.sort / np.argsort: 予測確率の上位N件を取り出す操作でよく使う
# 実際のKaggleでよく見るパターン
predictions = np.array([0.3, 0.8, 0.6, 0.9, 0.2])
top_indices = np.argsort(predictions)[::-1][:3] # 上位3件のインデックス
print(top_indices) # [3, 1, 2]
⚠️ よくある誤解・ミス
| 誤解・ミス | なぜ起こるか | 正しい理解 |
|---|---|---|
np.sort() が降順と思う | 普通「ソート = 大きい順」に思いがち | デフォルトは昇順。[::-1] か np.sort()[::-1] で降順 |
axis=0 と axis=1 を混乱 | 直感的にわかりにくい | axis=0は縦(行方向)、axis=1は横(列方向)。行数・列数の「0番目・1番目」と対応 |
scores * 2 でエラーになると思う | Pythonリストでは *2 は要素複製 | numpyはブロードキャストで全要素に適用される |
| 正規化とは標準化(z-score)のこと | 「正規化」という言葉が曖昧 | min-max正規化(0〜1)と標準化(平均0・分散1)は別物 |
🚀 次のステップ
- 発展:
np.where()を使って条件分岐した配列を作る /np.concatenate()で配列を結合する - 次回予告: pandas入門(DataFrame・Series)— 表形式データを扱うKaggleの主力ツール