📚 背景知識(読んでから問題へ)
numpyの「次元」を身近な例えで理解する
numpyの配列(ndarray)は「箱の入れ子構造」で考えると分かりやすいです。
- 0次元(スカラー): 数値1個。例:
42 - 1次元(ベクトル): 数字が一列に並んだもの。例:
[1, 2, 3, 4, 5](テストの点数リスト) - 2次元(行列): 表(スプレッドシートのイメージ)。例: 5人×3科目の成績表
- 3次元: 表が複数枚重なったもの。例: 月別×5人×3科目の成績(12枚の表が重なっている)
なぜ「形状(shape)」が重要か
numpyで最も大事な概念が shape(形状) です。データが何行×何列(×何層)で構成されているかを表します。
array.shape → (行数, 列数) → 例: (100, 5) は100行5列
Kaggleのデータ処理では、配列の形状が一致していないと計算エラーが発生します。shape を常に意識することが、バグを防ぐ第一歩です。
ブロードキャストとは何か
numpyには「ブロードキャスト」という自動拡張機能があります。
例え: 「5人全員のテストの点数に10点加算する」とき、わざわざ [10, 10, 10, 10, 10] を用意しなくても scores + 10 と書くだけで全員に加算されます。これがブロードキャストです。
scores = np.array([70, 80, 60, 90, 75])
scores + 10 # → array([80, 90, 70, 100, 85])
📝 問題
以下の numpyに関する4つの概念説明を読み、それぞれが 正しい(○) か 誤り(×) かを答えなさい。誤りの場合は正しい説明を述べなさい。
【概念A】
np.array([1, 2, 3]) と np.array([[1, 2, 3]]) は、格納されている数値は同じなので、.shape も同じ (3,) になる。
【概念B】
np.zeros((3, 4)) は、すべての要素が 0 の「3行4列」の2次元配列を作成する。
【概念C】
numpyの配列は、Python のリストと違い、1つの配列の中に整数と文字列を混在させることができない。これを「均一なデータ型(dtype)を持つ」という。
【概念D】
np.arange(1, 10, 2) は、[1, 3, 5, 7, 9, 10] という配列を返す。
🔍 ヒント(段階的開示)
ヒント1(方向性)
各概念について、実際にPythonで動かして確認するのが一番確実です。特にshapeは .shape で確認できます。
ヒント2(アプローチ)
- 【概念A】:
[1, 2, 3]は1次元、[[1, 2, 3]]は2次元(外側の[]がもう1層ある) - 【概念B】:
np.zerosの引数はタプルで(行, 列)の順 - 【概念C】: numpyのdtype(データ型)の特性を思い出してください
- 【概念D】:
np.arange(start, stop, step)のstopは含まれるか含まれないかに注意
ヒント3(コード骨格)
import numpy as np
# 概念A の確認
a1 = np.array([1, 2, 3])
a2 = np.array([[1, 2, 3]])
print(a1.shape) # ?
print(a2.shape) # ?
# 概念D の確認
print(np.arange(1, 10, 2)) # ?
✅ 模範解答
【概念A】× 誤り
np.array([1, 2, 3]).shape は (3,) だが、np.array([[1, 2, 3]]).shape は (1, 3) になる。外側にもう1つ [] があることで「1行3列の2次元配列」になる。
【概念B】○ 正しい
np.zeros((3, 4)) は 3行4列の全ゼロ配列を作成する。
【概念C】○ 正しい
numpyの配列は1つのdtype(データ型)しか持てない。整数と文字列を混在させると、Pythonが自動的に全要素を文字列型(
【概念D】× 誤り
np.arange(1, 10, 2) は [1, 3, 5, 7, 9] を返す(10は含まれない)。np.arange の stop は 含まれない(Pythonの range() と同じルール)。
import numpy as np
# 確認コード
print(np.array([1, 2, 3]).shape) # (3,)
print(np.array([[1, 2, 3]]).shape) # (1, 3)
print(np.zeros((3, 4)))
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
mixed = np.array([1, 2, "hello"])
print(mixed.dtype) #
🪜 Step-by-Step 解説
import numpy as np
a1 = np.array([1, 2, 3])
a2 = np.array([[1, 2, 3]])
print(a1.ndim, a1.shape) # 1次元, (3,)
print(a2.ndim, a2.shape) # 2次元, (1, 3)
[1, 2, 3] → 1次元(単なる数字の列)
[[1, 2, 3]] → 2次元(1行3列の表)
なぜこれが重要か: Kaggleのデータは2次元(表形式)が基本です。モデルに渡すとき (N,) と (N, 1) の違いでエラーになることがよくあります。
zeros_matrix = np.zeros((3, 4)) # 3行4列の全ゼロ
ones_matrix = np.ones((2, 5)) # 2行5列の全1
eye_matrix = np.eye(3) # 3×3の単位行列(対角が1)
print(zeros_matrix.shape) # (3, 4)
使い道: 初期値の配列を用意したり、マスク処理(特定箇所だけ0/1にする)に使います。
# Pythonリストは混在OK
py_list = [1, 2, "hello"] # エラーにならない
# numpyは全部同じ型に変換される
np_arr = np.array([1, 2, "hello"])
print(np_arr) # ['1' '2' 'hello'] ← 数値が文字列になった!
print(np_arr.dtype) #
注意: 数値データに欠損値(NaN)を入れると自動的に float64 に変換されます。
# np.arange: ステップ幅を指定(stopは含まない)
print(np.arange(1, 10, 2)) # [1 3 5 7 9]
print(np.arange(0, 1, 0.25)) # [0. 0.25 0.5 0.75]
# np.linspace: 個数を指定(stopを含む)
print(np.linspace(0, 1, 5)) # [0. 0.25 0.5 0.75 1. ]
使い分け: グラフの軸を作るときは linspace(「0から1まで100点均等に」)、ループの代替は arange(「0から9まで2刻みで」)が多い。
📐 数学・統計の補足(文系向け)
「行列」を怖がらなくていい
「行列」と聞くと難しそうですが、Kaggleで使う場面のほとんどは「表(スプレッドシート)」のことです。
- 行 = サンプル(1人のデータ)
- 列 = 特徴量(年齢・性別・価格など)
(1000, 15) の行列 = 1000人分のデータ、各人に15個の情報がある表。
これだけ理解していれば、numpyの行列操作の意味が直感的に分かります。
shapeとdtypeは「配列の身分証明書」
numpyで何かうまくいかないとき、まず確認すること:
print(array.shape) # 形状確認
print(array.dtype) # 型確認
print(array.ndim) # 次元確認
これを習慣にするだけで、デバッグ時間が大幅に短縮されます。
🏆 Kaggleでの実践的な使い方
1. 特徴量の形状チェック(前処理の基本)
import numpy as np
import pandas as pd
df = pd.read_csv("train.csv")
X = df.drop("target", axis=1).values # numpyに変換
print(X.shape) # (891, 10) → 891サンプル、10特徴量
print(X.dtype) # データ型確認
2. モデルへの入力形状の注意
scikit-learnのモデルは (nsamples, nfeatures) を期待します。1次元配列を渡すとエラーになります:
# NG: 1次元
model.fit(np.array([1, 2, 3]), y) # エラー
# OK: 2次元に変換
model.fit(np.array([[1], [2], [3]]), y)
# または
model.fit(X.reshape(-1, 1), y)
3. ブロードキャストでの特徴量正規化
X = np.array([[170, 60], [165, 55], [180, 70]]) # 身長・体重データ
mean = X.mean(axis=0) # 列ごとの平均: [171.67, 61.67]
std = X.std(axis=0) # 列ごとの標準偏差
X_normalized = (X - mean) / std # ブロードキャストで全行に適用
⚠️ よくある誤解・ミス
| 誤解・ミス | なぜ起こるか | 正しい理解 |
|---|---|---|
[1,2,3] と [[1,2,3]] が同じと思う | 見た目が似ているから | shapeが (3,) vs (1,3) で別物。モデルに渡すとエラーの原因になる |
np.arange(1, 10) で10が含まれると思う | 「1から10まで」という日本語の感覚から | stopは含まれない。Pythonのrange()と同じルール |
| 整数配列にNaNを入れようとする | 欠損値を扱う際に起こる | NaNはfloat型なので、float64の配列にしか入れられない |
array.shape を忘れてデバッグする | エラーメッセージが分かりにくい | 処理の各ステップでshapeをprintする習慣をつける |
🚀 次のステップ
- 発展: numpyのスライシング(
X[0:5, 2:4]のように2次元配列の一部を取り出す方法)とfancy indexing(X[[0, 2, 4]]のようにインデックスの配列で取り出す方法) - 次回予告: pandas入門(DataFrame・Series)— numpyの次はKaggleで最も使う表形式データ操作ツールへ