📚 背景知識(読んでから問題へ)
numpyとは何か?
Pythonで数値計算をするとき、普通のリスト([1, 2, 3])は「電卓を1つずつ押す」イメージです。
numpyの配列(ndarray)は「1000個のボタンを一気に押せる計算機」のイメージです。
たとえば、全員の給料に10%ボーナスを足す処理:
# 普通のPythonリスト(遅い)
salaries = [300, 400, 500]
result = [s * 1.1 for s in salaries] # 1つずつループ
# numpy(速い・シンプル)
import numpy as np
salaries = np.array([300, 400, 500])
result = salaries * 1.1 # 全部まとめて計算!
numpyの核心:ブロードキャスト
「ブロードキャスト」とは、異なる形の配列を自動的に合わせて計算する機能です。
テレビ放送が1つの電波を全テレビに届けるイメージ → 1つの数値を全要素に適用する。
arr = np.array([1, 2, 3, 4, 5])
arr + 10 # → [11, 12, 13, 14, 15] ← 10が全要素にブロードキャスト
arr * 2 # → [2, 4, 6, 8, 10]
多次元配列(行列)の考え方
numpyは「表形式のデータ」を扱うのが得意です。
1次元: [1, 2, 3] ← 数直線(1列のデータ)
2次元: [[1, 2, 3], ← 表(行と列)
[4, 5, 6]]
3次元: 表が積み重なったもの ← 画像データなど
| 属性 | 意味 | 例 |
|---|---|---|
ndim | 何次元か | 2次元なら 2 |
shape | 行×列の形 | (3, 4) = 3行4列 |
dtype | データの型 | float64, int32 など |
size | 要素の総数 | shape の積 |
インデックスとスライシング
arr = np.array([10, 20, 30, 40, 50])
arr[0] # → 10 (最初の要素)
arr[-1] # → 50 (最後の要素)
arr[1:4] # → [20, 30, 40] (1番目〜3番目)
arr[::2] # → [10, 30, 50] (1個おき)
2次元の場合は [行, 列] の形でアクセス:
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
matrix[1, 2] # → 6 (2行目、3列目)
matrix[:, 1] # → [2, 5, 8] (全行の2列目)
matrix[0, :] # → [1, 2, 3] (1行目の全列)
📝 問題
以下の4つの問いに答えなさい。
問1: 配列の属性を理解する
次のコードを見て、各出力値を予測しなさい(実行せずに考える)。
▶ 出力を見る
import numpy as np
data = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
print(data.ndim)
print(data.shape)
print(data.size)
print(data.dtype)Q: ndim, shape, size, dtype はそれぞれ何を出力するか?
問2: ブロードキャストの結果を予測する
次のコードの出力を答えなさい。
▶ 出力を見る
import numpy as np
scores = np.array([60, 75, 88, 45, 92])
# 全員の点数に5点のボーナスを加算
result_a = scores + 5
# 70点未満の人を抽出(ブール型インデックス)
result_b = scores[scores < 70]
print(result_a)
print(result_b)問3: 形状変換(reshape)
1次元配列を行列に変換しなさい。
import numpy as np
arr = np.arange(12) # [0, 1, 2, ..., 11]
# この配列を 3行4列 の2次元配列に変換せよ
# ヒント: reshape を使う
arr を reshape した後の shape は何になるか?また最後の行(3行目)の要素は何か?
問4: numpy の便利な集計関数
下記のコードの空欄を埋めて、出力を完成させなさい。
▶ 出力を見る
import numpy as np
exam_scores = np.array([72, 85, 91, 63, 78, 88, 55, 94, 67, 80])
# 以下の値を求めよ
total = ___________ # 合計
average = ___________ # 平均
minimum = ___________ # 最小値
maximum = ___________ # 最大値
std_dev = ___________ # 標準偏差
print(f"合計: {total}")
print(f"平均: {average:.1f}")
print(f"最小: {minimum}, 最大: {maximum}")
print(f"標準偏差: {std_dev:.2f}")🔍 ヒント(段階的開示)
ヒント1(方向性)
- 問1: numpyの配列には「次元数」「形」「要素数」「型」という属性がある
- 問2:
scores < 70は True/False の配列を作り、それでフィルタリングできる - 問3:
np.arange(n)は0からn-1まで連番を作る。reshape(行, 列)で形を変える - 問4: numpy には
.sum(),.mean(),.min(),.max(),.std()という集計関数がある
ヒント2(アプローチ)
- 問1:
dataは2行3列の浮動小数点配列。ndim=次元数,shape=(行,列),size=行×列の総数 - 問2: ブール型インデックス
arr[arr < 70]は条件を満たす要素だけを取り出す - 問3:
np.arange(12)→ 12個の要素 → 3×4=12 なので reshape(3, 4) が可能 - 問4:
np.sum(arr)またはarr.sum()の2通りの書き方がある(どちらでも正解)
ヒント3(コード骨格)
# 問1の答えを確認
import numpy as np
data = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
print(data.ndim) # 2(2次元)
print(data.shape) # (2, 3)(2行3列)
print(data.size) # 6(2×3=6個)
print(data.dtype) # float64
# 問3のヒント
arr = np.arange(12)
matrix = arr.reshape(3, 4) # ← ここを埋める
print(matrix[-1]) # 最後の行
# 問4のヒント
exam_scores = np.array([72, 85, 91, 63, 78, 88, 55, 94, 67, 80])
total = exam_scores.sum()
average = exam_scores.mean()
# ...
✅ 模範解答
import numpy as np
# ===============================
# 問1: 配列の属性
# ===============================
data = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
print("=== 問1 ===")
print(data.ndim) # 2
print(data.shape) # (2, 3)
print(data.size) # 6
print(data.dtype) # float64
# ===============================
# 問2: ブロードキャスト&ブールインデックス
# ===============================
print("\n=== 問2 ===")
scores = np.array([60, 75, 88, 45, 92])
result_a = scores + 5
result_b = scores[scores < 70]
print(result_a) # [65 80 93 50 97]
print(result_b) # [60 45]
# ===============================
# 問3: reshape
# ===============================
print("\n=== 問3 ===")
arr = np.arange(12)
matrix = arr.reshape(3, 4)
print(matrix.shape) # (3, 4)
print(matrix)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print("3行目:", matrix[-1]) # [ 8 9 10 11]
# ===============================
# 問4: 集計関数
# ===============================
print("\n=== 問4 ===")
exam_scores = np.array([72, 85, 91, 63, 78, 88, 55, 94, 67, 80])
total = exam_scores.sum()
average = exam_scores.mean()
minimum = exam_scores.min()
maximum = exam_scores.max()
std_dev = exam_scores.std()
print(f"合計: {total}") # 合計: 773
print(f"平均: {average:.1f}") # 平均: 77.3
print(f"最小: {minimum}, 最大: {maximum}") # 最小: 55, 最大: 94
print(f"標準偏差: {std_dev:.2f}") # 標準偏差: 12.26
🪜 Step-by-Step 解説
np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) は「2行3列の表」。
| 属性 | 値 | 理由 |
|---|---|---|
ndim | 2 | 「行と列」の2軸がある |
shape | (2, 3) | 2行、3列 |
size | 6 | 2 × 3 = 6要素 |
dtype | float64 | 小数点あり → 浮動小数点型 |
ブロードキャスト (scores + 5):
[60, 75, 88, 45, 92] + 5
= [65, 80, 93, 50, 97] ← 全要素に+5
ブールインデックス (scores[scores < 70]):
scores < 70 → [True, False, False, True, False]
scores[[True, False, False, True, False]] → [60, 45]
条件式が True の位置にある要素だけが選ばれる仕組み。
np.arange(12) = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
これを reshape(3, 4) すると:
行0: [ 0, 1, 2, 3]
行1: [ 4, 5, 6, 7]
行2: [ 8, 9, 10, 11] ← matrix[-1] はこれ
ポイント: reshape 前後で要素数が変わってはいけない(12 = 3×4 ✓)。
データ: [72, 85, 91, 63, 78, 88, 55, 94, 67, 80]
合計: 72+85+91+63+78+88+55+94+67+80 = 773
平均: 773 ÷ 10 = 77.3
最小: 55
最大: 94
標準偏差: 約12.26(ばらつきの大きさ)
📐 数学・統計の補足(文系向け)
ndim / shape / size の違いを「建物」で例えると
ndim= 何階建てか(1階建て=1次元、2階建て=2次元)shape= 各フロアの間取り(3部屋×4列のオフィス)size= 部屋の総数(3×4=12部屋)
dtype の意味
numpyはデータ型を自動判定する:
- 整数だけ →
int64(整数型) - 小数点あり →
float64(浮動小数点型) - 文字列 →
(文字列型)
Kaggleではほとんど float64 か int64 を使う。
🏆 Kaggleでの実践的な使い方
ブールインデックスは特徴量選択・フィルタリングの基本
import numpy as np
import pandas as pd
# 例: Titanicデータで年齢が30歳以上の乗客のみ抽出
df = pd.read_csv('titanic.csv')
ages = df['Age'].values # numpy配列に変換
# 30歳以上をフィルタリング
over_30 = ages[ages >= 30]
print(f"30歳以上の人数: {len(over_30)}")
reshapeは画像・時系列データで必須
# 画像データ (28×28ピクセル) をニューラルネットに入力する際
image = np.random.rand(28, 28) # 2次元: 28×28
flat = image.reshape(1, 784) # 1次元に変換: 1×784
# または
flat = image.reshape(-1) # -1は「残りは自動計算」
集計関数は EDA(探索的データ分析)の基礎
コンペ開始時に必ずやる作業:
data = df.select_dtypes(include='number').values
print(f"平均: {data.mean(axis=0)}") # 列ごとの平均
print(f"最大: {data.max(axis=0)}") # 列ごとの最大
print(f"欠損: {np.isnan(data).sum(axis=0)}") # 列ごとの欠損数
⚠️ よくある誤解・ミス
| 誤解・ミス | なぜ起こるか | 正しい理解 |
|---|---|---|
shape を (6) と答える | 1次元と混同 | (2, 3) のようにタプルで表す |
reshape(3, 4) と reshape(4, 3) を混同 | 行と列の順序を忘れる | 第1引数=行数、第2引数=列数 |
arr + 5 でエラーが出ると思う | Pythonリストでは +5 が意味をなさない | numpyはブロードキャストで一括処理できる |
arr.mean() と np.mean(arr) が違うと思う | 見た目が違う | 結果は同じ。どちらでも正解 |
dtype=int なのに .mean() が小数を返す | 整数配列の平均が小数になると思わない | numpyは自動的に float64 に変換して返す |
🚀 次のステップ
- 発展:
axisパラメータを使った行・列方向の集計(arr.sum(axis=0)vsarr.sum(axis=1)) - 次回予告: pandas入門(DataFrame・Series) — numpyを「名前付き列」で使えるようにするライブラリ