tileとrepeat
numpyで配列を繰り返したいとき、今までrepeatしか知らなかったけれど、tileというmethodもあることに気がついた。
まずはrepeatから
基本的な使い方は以下。
import numpy as np
np.repeat(a, repeats, axis = None)
\(a\)は配列、\(repeats\)は整数か整数配列、\(axis\)も整数で、どちらの軸に繰り返すかを指定する。\(axis\)は指定しなくても良い。
いくつか例を見てみる。
np.repeat(3, 4)
#array([3, 3, 3, 3])
この場合、\(3\)が\(4\)回繰り返される。
x = np.array([[1, 2], [3, 4]])
np.repeat(x, 2)
#array([1, 1, 2, 2, 3, 3, 4, 4])
このように、\(axis\)を指定しないとFlattened(平坦化)された\(1\)次元配列が生成される。ここで\(axis\)を指定すると以下のようになる。
np.repeat(x, 3, axis = 1)
#array([[1, 1, 1, 2, 2, 2],
# [3, 3, 3, 4, 4, 4]])
\(repeats\)には整数の配列を指定することもできる。
np.repeat(x, [1, 2], axis = 0)
#array([[1, 2],
# [3, 4],
# [3, 4]])
最後は少しわかりにくい。\([1, 2]\)を\(1\)回、\([3, 4]\)を\(2\)回繰り返している。ここで\(axis = 1\)とすると以下のようになる。
np.repeat(x, [1, 2], axis = 1)
#array([[1, 2, 2],
# [3, 4, 4]])
ここでは軸が行方向になるので、\(1\)を\(1\)回、\(2\)を\(2\)回、\(3\)を\(1\)回、\(4\)を\(2\)回繰り返している。
repeatは便利だが
このように(少し複雑だが)numpyのrepeat methodは便利である。しかし、例えば
np.arange(10)
#array([1, 2, 3, 4, 5, 6, 7, 8, 9])
に対してrepeatを適用すると、下のようになる。
np.repeat(np.arange(10), 3)
#array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7,
# 7, 7, 8, 8, 8, 9, 9, 9])
これが必要な場合もあるだろうが、多くの人が想像するのは以下のような配列ではないであろう。
#array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
# 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
そんなときに便利なのが、以下のtileである。
tile
基本的な使い方は以下。
np.tile(A, reps)
\(A\)は整数配列で、\(reps\)は整数あるいは整数配列である。もしも\(reps\)の長さが\(d\)であれば、結果の配列は\(max(d, A.ndim)\)になる。ただし。\(A.ndim\)は\(A\)の次元である。また、\(A.ndim < d\)のときは、\(A\)は新しい軸を付加することで\(d\)次元に昇格する。したがって、形状\((3, )\)の配列は、\(2\)次元の場合は\((1, 3)\)に、\(3\)次元の場合は形状\((1, 1, 3)\)にプロモートされる。この動作が望ましくない場合は関数を呼び出す前に、\(A\)を手動で\(d\)次元にに昇格させておくと良い。また、\(A.ndim > d\)のときは、\(reps\)は\(A.ndim\)に\(1\)をプリペンドして昇格させる。したがって、\((2, 3, 4, 5)\)の形状の\(A\)に対して、\(reps = (2, 2)\)は\((1, 1, 2, 2)\)として扱われることになる。
よくわからないと思うので、いくつか具体例を見てみる。
a = np.array([0, 1, 2])
np.tile(a, 2)
#array([0, 1, 2, 0, 1, 2])
これは正に最初に望んでいたものである。
np.tile(a, (2, 2))
#array([[0, 1, 2, 0, 1, 2],
# [0, 1, 2, 0, 1, 2]])
また、
np.tile(a, (2, 2))
#array([[0, 1, 2, 0, 1, 2]])
と
np.tile(a, (2, 1, 2))
#array([[[0, 1, 2, 0, 1, 2]],
# [[0, 1, 2, 0, 1, 2]]])
の違いがわかるであろうか。注意深く眺めてみると良い。リンク先に習っていくつか例をあげておく。
b = np.array([[1, 2], [3, 4]])
np.tile(b, 2)
#array([[1, 2, 1, 2],
# [3, 4, 3, 4]])
np.tile(b, (2, 1))
#array([[1, 2],
# [3, 4],
# [1, 2],
# [3, 4]])
c = np.array([1, 2, 3, 4])
np.tile(c, (4, 1))
#array([[1, 2, 3, 4],
# [1, 2, 3, 4],
# [1, 2, 3, 4],
# [1, 2, 3, 4]])
コメント