位置とスライスを多次元で
配列のインデックスはリストと同じです。a[0] は先頭、a[-1] は末尾、a[start:stop:step] は stop の手前までのスライスです。違いは、配列は多次元にできることで、次元ごとにインデックスかスライスをカンマで区切って指定します:m[行, 列]。単独の : は「その次元のすべて」を意味するので、m[:, 1] は2列目全体、m[1](または m[1, :])は2行目全体です。負の数は末尾から数え、ステップ -1 は逆順になります。
import numpy as np
a = np.array([10., 11., 12., 13., 14., 15.])
print(a[0], a[-1]) # 10.0 15.0
print(a[1:4]) # [11. 12. 13.]
print(a[-2:]) # [14. 15.]
print(a[::2]) # [10. 12. 14.]
print(a[::-1]) # [15. 14. 13. 12. 11. 10.]
# Two dimensions: one index or slice per dimension
m = np.arange(12).reshape(3, 4)
print(m[1, 2]) # 6
print(m[:, 1]) # [1 5 9] the whole second column
print(m[-1, :]) # [ 8 9 10 11] the last row
print(m[0:2, 1:3]) # [[1 2]
# [5 6]]スライスはコピーではなくビュー
リストのスライスと違い、NumPy の基本的なスライスはデータをコピーしません。同じメモリへのビューなので、そこへ書き込むと元の配列が変わります。巨大な配列でもスライスが一瞬で済む反面、part = a[1:4]; part[0] = 99 で a[1] も変わるという驚きがあります。独立した配列が必要なときは .copy() を呼びます。np.shares_memory(a, b) で確認できます。行・列・ステップ・逆順のスライスでも同じくビューになります。
import numpy as np
a = np.array([10., 11., 12., 13., 14., 15.])
part = a[1:4] # a view, no data copied
part[0] = 99
print(a) # [10. 99. 12. 13. 14. 15.] a changed too
safe = a[1:4].copy() # an independent array
safe[0] = -1
print(a) # [10. 99. 12. 13. 14. 15.] unchanged
print(np.shares_memory(a, a[::2])) # True
print(np.shares_memory(a, safe)) # Falseブールマスクとインデックスのリスト
配列を比較すると、同じ大きさのブール配列が得られます。r > 0 はリターンがプラスの位置で True です。このマスクをインデックスに使う r[r > 0] は、その要素だけを選びます。条件は &(かつ)、|(または)、~(否定)で組み合わせ、各条件はかっこで囲みます。Python の and/or は配列では使えないからです。整数のリストや配列も使え、a[[0, 2, 5]] はまさにその位置をその順に取り出します。マスクやインデックスリストによる選択はデータをコピーし、マスク越しに代入もできます:a[a > 3] = 0。
import numpy as np
r = np.array([0.01, -0.02, 0.03, -0.01, 0.0, 0.02])
print(r > 0) # [ True False True False False True]
print(r[r > 0]) # [0.01 0.03 0.02]
print(r[(r > 0) & (r < 0.025)]) # [0.01 0.02] parentheses are required
print(np.where(r > 0)[0]) # [0 2 5] positions where it holds
# Pick by position, in any order
w = np.array([3.0, 9.0, 1.0, 7.0])
order = np.argsort(-w) # positions from the largest value down
print(order[:2], w[order[:2]]) # [1 3] [9. 7.]
# Assign through a mask
counts = np.array([1, 2, 3, 4, 5, 6])
counts[counts > 3] = 0
print(counts) # [1 2 3 0 0 0]import numpy as np
# Rows are days, columns are assets (AAPL, MSFT, GOOG)
R = np.array([[ 0.02, -0.01, 0.03],
[ 0.01, 0.00, 0.02],
[-0.03, 0.02, -0.01],
[ 0.00, 0.01, 0.04]])
print(R[:, [0, 2]]) # the AAPL and GOOG columns, as a copy
print(R[R[:, 0] > 0]) # the days on which AAPL rose (whole rows)
print(R[R[:, 0] > 0].shape) # (2, 3)
print(R[-2:, 1].mean()) # 0.015 last two days of MSFTa[1:4]、m[:, 1]、a[::2])はビューで、マスクやインデックスリスト(a[a > 0]、a[[0, 2]])はコピーです。引数のスライスを返す関数は、呼び出し側の元のデータへの窓を渡すことになるので、後の書き込みで思わぬ変更が起こり得ます。意図して選びましょう。速度が重要でデータが読み取り専用ならビュー、そうでなければ .copy() です。ラボのテストは両方の挙動を確認します。- 次元ごとに1つのインデックスかスライス:
m[行, 列]、m[:, 1](列)、m[-1](最終行)、a[::-1] - 基本スライスはビュー(書き込みが反映される。切り離すには
.copy())。マスクとインデックスリストはコピー - マスク:
a[a > 0]。&・|・~をかっこ付きで組み合わせる。np.argsortは並べ替え順の位置を返す
次はベクトル化です。Python のループを配列全体の演算に置き換えます。
ラボ:採点される内容
last_rowsで最新の行を取り出す25点positive_valuesでプラスの値だけを残す25点every_kthでk個おきに値を取り出す25点top_k_indicesで大きいほうからk個の位置を求める25点