numpyのndarrayをitertools.productに渡すのは微妙だからnumpy.nditerを使うほうがいい。それかnumpy.meshgrid。
itertools.product
import numpy
import itertools
x1 = np.arange(4)
x2 = np.arange(3)
for p, q in itertools.product(x1, x2):
print(p, q)
これを実行すると
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
3 0
3 1
3 2
問題:itertoolsのインポートがうるさい。numpyでできないのか?
numpy.nditer
broadcasting in numpy.nditer
import numpy as np
x1 = np.arange(4)
x2 = np.arange(3)
for p, q in np.nditer([x1, x2.reshape(-1, 1)]):
print(p, q)
np.nditerに指定したndarrayにはブロードキャストが効く。
0 0
1 0
2 0
3 0
0 1
1 1
2 1
3 1
0 2
1 2
2 2
3 2
ブロードキャストに慣れていれば使いやすいはず。
numpy.meshgrid
ループがしたいのではなく最初から結果を積んだ配列が欲しい場合。
import numpy as np
x1 = np.linspace(-1, 1, 10)
x2 = np.linspace(-2, 2, 10)
X1, X2 = np.meshgrid(x1, x2)
X = np.c_[X1.ravel(), X2.ravel()] #shape = (100, 2)
# or
X = np.r_[X1.ravel(), X2.ravel()] #shape = (2, 100)
# or
X = np.array(np.meshgrid(x1, x2)).reshape(2, -1).T #shape = (100, 2)
# or
X = np.array(np.meshgrid(x1, x2)).reshape(2, -1) #shape = (2, 100)
どちら向きに積むかわかりやすいのは前半のnp.c_
やnp.r_
で明示的に積んでいる方。
後者はunpackの代わりに強引にnp.arrayを使うことやreshapeの2が引数の2個と対応していないといけない、あげく形によってはTをつける必要あり(reshape(-1, 2)は不可)。短くは書けるのでこれが気にならなければ可。