Day 035 — numpy入門(配列操作・数値計算)

2026-05-14 白 / Phase 1 コーディング numpy入門(配列操作・数値計算)

📚 背景知識(読んでから問題へ)

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つのタスクをすべてこなしてください:

  1. 基本統計を計算: 平均・最大値・最小値・標準偏差を求めて表示
  2. 正規化: スコアを0〜1の範囲に正規化(min-max正規化)してください
  • 公式: (値 - 最小値) / (最大値 - 最小値)
  1. フィルタリング: スコアが平均より高い参加者のスコアだけを取り出す
  2. ランキング: スコアを降順(高い順)に並べ替えて表示
  3. 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 解説

1
基本統計
mean_score = np.mean(scores)   # 全要素を足して個数で割る
max_score  = np.max(scores)    # 最大値
min_score  = np.min(scores)    # 最小値
std_score  = np.std(scores)    # 標準偏差(バラつきの大きさ)

numpyの関数は「配列全体を一発で計算」してくれます。Pythonのループは不要。

2
min-max正規化
normalized = (scores - min_score) / (max_score - min_score)
  • scores - min_score: 各スコアから最小値を引く(最小値が0になる)
  • / (maxscore - minscore): 範囲で割る(最大値が1になる)

numpyでは scores - 0.634 と書くと配列の全要素から0.634が引かれます。これをブロードキャストと言います。

3
ブールインデックスでフィルタリング
above_mean = scores[scores > mean_score]

scores > mean_score[True, False, True, True, ...] のような True/False の配列を返します。これを scores[...] に渡すと、Trueの位置だけ取り出せます。

4
降順ソート
sorted_desc = np.sort(scores)[::-1]

np.sort() はデフォルトで昇順(小→大)なので、[::-1] で逆順にします。[::-1] は「最後から最初まで逆に取り出す」Pythonのスライス記法です。

5
reshape と axis
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=0axis=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の主力ツール

🎯 自己評価

自分の回答

気づき・メモ