今回は、配列を結合する方法の1つとして、オブジェクトであるnp.r_
とnp.c_
を用いた方法と使い方を解説します。
np.c_
はnp.r_
の特殊な場合を抜き出したものなので、np.r_
でもnp.c_
と同じことができます。
特に何も指定しない場合は、np.r_
はhstack
、np.c_
はvstack
と同様の使い方をすることができます。
大きな特徴としてはスライス表記で配列を作ることができること、配列でないただの数値も配列として結合できることが挙げられます。どちらも関数ではなく、オブジェクトなので全て[]
の中に配列や値を入れていくことで操作をしていきます。
np.r_
まずは、np.r_
の方からみていきます。関数ではないので、引数とかを指定するのではなく、[ ]
の中に結合したい配列や結合の仕方について指定することができます。
配列同士の結合(特に指定なし)
特に結合の様式を指定しない場合、np.r_
に含まれる配列はaxis=0
の方向に結合することになります。これが最もよく使われるかたちとなっています。
これはnp.hstack
関数と同じ機能を持ちます。np.hstack
関数については以下の記事で詳しく解説していますので参照してみてください。
配列同士を連結する、NumPyのvstackとhstack関数の使い方 /features/numpy-stack.html
実際のコードでみてみましょう。
ここでの使い方はnp.hstack
と全く一緒になります。
スライス表記
np.r_
を使うことで、スライス表記によって1次元配列を作ることができます。
のstart,stop,step
部分に値を入れていくことで連番であったり、等差数列を作ります。start
とstop
は始点と終点になっており、step
は差になっています。これはnp.arange(start, stop, step)
と同じ意味合いを持ちます。
デフォルトの値として、start=1
、step=1
となっており、stop
の値だけ指定すればその値未満までの0から始まる整数の連番が生成されます。また、step
は虚数を指定することができ、その場合はstep=stepj
だった場合、start
からstop
の区間(stopも区間に含まれる)をstep-1
等分する数列を生成します。
すなわち、Pythonのビルトイン関数のrange
を使用したnp.array(range(start, stop, step))
と同じ意味合いを持つ表記になります。また、カンマで区切ることで他の数値単体や、一次元配列を結合することもできます。np.arange
関数とnp.linspace
関数は以下の記事で詳細な説明をしていますので気になる方はみてみてください。
連番や等差数列を生成するnumpy.arange関数の使い方 /features/numpy-arange.html
線形に等間隔な数列を生成するnumpy.linspace関数の使い方 /features/numpy-linspace.html
では、スライス表記を交えてnp.r_
を使ってみます。
数値の文字列(string)による軸や次元の指定
np.r_
ではどの軸方向に結合するのか、次元の最小数はどうするのか、形状(shape)を揃える際、どの軸番号に1
を付け加えればいいのかといったことを
といった数値の文字列で表すことができます(a, b, cはそれぞれ整数)。デフォルトでは'0, 0, -1'
となっています。
-
a
は、どの軸(axis)の方向に沿って配列を結合するのかを指定します。
-
b
は、できあがる配列の次元数の最小値を指定します。
-
c
は、次元数の少ない配列の次元数の拡張を行った際、形状(shape)の表記として、どこに配列の最後の次元が置かれるべきかを指定します。
c
については、例えば (2,3)
の形状(shape)を持つ二次元配列があったとします。この配列を他の(2,2,3)
の形状(shape)を持つ三次元配列と結合したいとします。このとき、二次元配列は三次元に拡張しなければ結合できません。
c=-1
またはc=1
であれば、先頭に1が追加され、(1, 2, 3)
の形状で結合することができます。c=0
であれば、元の配列の形状が先頭に詰められるので、(2,3,1)
となります。
少し複雑ですね。c
が示しているのは拡張前の形状(shape)がどこに配置されるかであることとなっています。ややこしくはなっていますが、マスターできれば次元の違う配列でもうまく結合することが可能となるので使いこなせるようになれば、かなり便利なオブジェクトになるかと思います。
まずは、a
の部分についてみていきます。a
は結合する軸(axis)を指定します。ここでの軸番号は、できあがる配列における軸(axis)番号となっていることに注意してください。
また、a
のデフォルトの値は0
です。
次に、b
の値を変更していきます。b
を変更することで、出力される配列の次元の最小数を指定することができます。b = 2
なら次元数(ndim)>=2となります。b = 3
であれば次元数(ndim)>=3となります。
b
の次元数より少ない配列はb
次元まで拡張されてから結合の操作に入ります(拡張の仕方をc
で指定しますが、デフォルトでは形状(shape)表記の先頭に1を足りない次元分だけ付け足していくことで拡張を行います)。
最後にc
の値を変更していきます。このデフォルトの値は-1
となっており、形状(shape)は先頭に1が続いていくかたちになります。このため、先ほどb
の値を変えたとき、拡張後の配列の形状(shape)は全て(1, 1, 3)
や(1, 1, 1, 3)
のようになっていました。
c
が一番理解しにくいところだと思います。よくわからなかったら、最初からreshape
関数の機能を使って結合したい配列の形状(shape)を変更してから結合するのもできますので、無理に理解する必要はありません。また、コードが読みにくくなるのであまりオススメしません。
行列(matrix)の指定
2次元の行列(matrix)をnp.r_
を使って生成する際は、文字列(string)として、'r'
または'c'
を最初に指定します。2次元行列の場合は、どちらを指定しても結果は同じですが、1次元で横ベクトルを生成したいときはr
を、縦ベクトルを生成したいときはc
を指定する必要があります。
コードをみながら確認していきます。
numpy.c_について
ここまでnp.r_
についてみてきたわけですが、本記事の冒頭に述べたとおり、np.c_
はnp.r_
の特殊な場合について抜き出したものです。
これは、np.c_[] == np.r_['-1, 2, 0']
の関係が成り立ちます。
2次元以上の配列で、最も最低の次元(axisの番号が一番大きい)の方向で配列を結合します。また、次元の拡張を各配列で行っている段階では、c=0
となっているので、形状(shape)表記で元々の要素が先頭にあり、末尾に1を追加する形で拡張されます。
参考