NumPy配列の繰り返しはtile()だけじゃない!代替メソッドで効率アップ
numpy.tile()
の基本的な使い方
基本的な構文は以下の通りです。
numpy.tile(A, reps)
reps
: 各次元でA
を何回繰り返すかを指定します。- スカラー(整数)の場合:
A
の全ての次元でその回数繰り返します。 - タプルまたは配列の場合:
A
の各次元に対応する繰り返しの回数を指定します。len(reps)
はA.ndim
と同じである必要はありません。reps
の長さがA.ndim
より小さい場合、A
の最初の次元から順に繰り返しが適用されます。reps
の長さがA.ndim
より大きい場合、A
に新しい次元が追加され、それらの次元で繰り返しが行われます。
- スカラー(整数)の場合:
A
: 繰り返しを行いたい元の配列(array_like)です。
具体例
いくつか例を見てみましょう。
例1: 1次元配列の繰り返し
import numpy as np
a = np.array([0, 1, 2])
b = np.tile(a, 3)
print(b)
# 出力: [0 1 2 0 1 2 0 1 2]
この例では、1次元配列 [0, 1, 2]
を3回繰り返しています。
例2: 2次元配列の繰り返し(スカラー指定)
import numpy as np
a = np.array([[0, 1], [2, 3]])
b = np.tile(a, 2)
print(b)
# 出力:
# [[0 1 0 1]
# [2 3 2 3]]
2次元配列 [[0, 1], [2, 3]]
を、行方向にも列方向にも2回繰り返しています。つまり、a
を縦横に並べています。
例3: 2次元配列の繰り返し(タプル指定)
import numpy as np
a = np.array([[0, 1], [2, 3]])
b = np.tile(a, (2, 3))
print(b)
# 出力:
# [[0 1 0 1 0 1]
# [2 3 2 3 2 3]
# [0 1 0 1 0 1]
# [2 3 2 3 2 3]]
この例では、タプル (2, 3)
を reps
に指定しています。これは、「行方向(軸0)に2回繰り返し、列方向(軸1)に3回繰り返す」という意味になります。
例4: reps
の長さが A.ndim
より長い場合
import numpy as np
a = np.array([0, 1])
b = np.tile(a, (3, 2))
print(b)
# 出力:
# [[0 1 0 1]
# [0 1 0 1]
# [0 1 0 1]]
元の配列 a
は1次元ですが、reps
は2次元のタプル (3, 2)
です。この場合、a
はまず2次元配列として扱われ(新たな軸が追加され)、それから reps
の指定に従って繰り返されます。結果として a
は3行2列の形に繰り返されています。
numpy.tile()
の用途
numpy.tile()
は、以下のような状況で非常に役立ちます。
- 機械学習におけるデータ準備
特徴量エンジニアリングなどで、特定の値を複数回コピーして新しい特徴量を作成する場合など。 - パターン生成
特定の数値パターンや配列のブロックを繰り返し生成する際に便利です。 - ブロードキャストを模倣する(あるいは、ブロードキャストが適用できない場合): 特定の配列を別の配列に適用するために、サイズを合わせる必要がある場合によく使われます。
numpy.tile()
と混同されやすい関数に numpy.repeat()
があります。
numpy.repeat(A, repeats)
:A
の個々の要素またはスライスを繰り返します。numpy.tile(A, reps)
:A
全体をブロックとして扱い、そのブロックを繰り返して並べます。
import numpy as np
a = np.array([0, 1])
# tile の場合
tile_result = np.tile(a, 3)
print(f"tile_result: {tile_result}")
# 出力: tile_result: [0 1 0 1 0 1]
# repeat の場合
repeat_result = np.repeat(a, 3)
print(f"repeat_result: {repeat_result}")
# 出力: repeat_result: [0 0 0 1 1 1]
この違いを理解することが重要です。
reps の次元と期待する出力形状の不一致
これが最もよくある混乱の原因です。reps
引数は、元の配列 A
の各次元をどれだけ繰り返すかを指定しますが、その解釈が直感的ではない場合があります。
エラー/混乱の例
-
reps のタプルが A.ndim と一致しない場合の挙動の誤解
reps
をタプルで指定した場合、そのタプルの長さがA.ndim
と一致しないと、numpy.tile()
は元の配列A
に新しい次元を追加したり、既存の次元の解釈を変えたりします。import numpy as np a = np.array([1, 2, 3]) # 1次元配列 (ndim=1) # `reps` が A.ndim (1) より長い場合 # 期待: 行方向に2回、列方向に3回繰り返される2D配列 # 実際: `a` が2D配列として扱われ、行方向に2回、列方向に3回繰り返される # 結果として (2, 3*len(a)) の形状になるのではなく、(2, 3) の形状になる。 # いや、これは説明が難しいので、出力を見るのが一番。 # reps の長さが a.ndim よりも長い場合、a の形状が左側に1が追加されて拡張され、 # その拡張された形状に合わせて reps が適用される。 # つまり、a は (1, 3) と見なされ、(2, 3) の reps が適用される。 b = np.tile(a, (2, 3)) print(b) # 出力: # [[1 2 3 1 2 3 1 2 3] <- 1行目が a を3回繰り返している # [1 2 3 1 2 3 1 2 3]] <- 2行目も a を3回繰り返している # これは (2, 3*3) = (2, 9) の形状になっている。 # reps の長さが A.ndim (1) より短い場合 (例えば、1次元配列にスカラー指定と結果が同じ) # この場合、reps の最初の要素だけが元の配列の最初の次元に適用され、 # 残りの次元は繰り返されない(1回繰り返される)。 # 実際は、reps の要素が尽きるまで、元の配列の次元と対応付けて繰り返される。 # 足りない場合は1と見なされる。 # # 例: 2次元配列に対してrepsが1次元の場合 arr = np.array([[1,2], [3,4]]) # (2, 2) tiled_arr = np.tile(arr, 2) # repsが単一の整数なので、(2,2)の全ての次元に2が適用 # tiled_arr: # [[1 2 1 2] # [3 4 3 4] # [1 2 1 2] # [3 4 3 4]] tiled_arr_partial = np.tile(arr, (2,)) # repsがタプルだが長さが1なので、軸0のみに2が適用 print(tiled_arr_partial) # 出力: # [[1 2] # [3 4] # [1 2] # [3 4]]
-
単一の整数で reps を指定した場合の多次元配列の挙動の誤解
reps
を単一の整数で指定すると、それはA
の全ての次元に適用されます。つまり、A
を構成する各次元が指定された回数だけ繰り返されます。これにより、元の配列が「タイル状」に縦横に並べられた形になります。import numpy as np a = np.array([[1, 2], [3, 4]]) # 期待: 行を2回繰り返すだけ # 実際: 行も列も2回繰り返される b = np.tile(a, 2) print(b) # 出力: # [[1 2 1 2] # [3 4 3 4] # [1 2 1 2] # [3 4 3 4]]
トラブルシューティング
- reps と A.ndim の関係を明確にする
reps
を単一の整数にする場合、A
の全ての次元でその回数繰り返されることを理解する。reps
をタプルにする場合、そのタプルの要素数がA.ndim
と同じになるように調整するのが最も安全で直感的です。例えば、2次元配列(M, N)
を行方向にr_row
回、列方向にr_col
回繰り返したい場合は、np.tile(A, (r_row, r_col))
とします。reps
の長さがA.ndim
より短い場合、reps
に足りない分は1
と見なされます。reps
の長さがA.ndim
より長い場合、A
の形状の左側に1
が追加されて、reps
の長さと一致するように拡張されます。この挙動は複雑なので、慣れないうちは避けるか、十分にテストすることが推奨されます。
- 出力の形状を常に確認する
print(b.shape)
を使って、生成された配列の形状が意図したものになっているかを確認しましょう。
reps が負の数であることによるエラー
reps
には負の数を指定することはできません。
エラーの例
import numpy as np
a = np.array([1, 2])
# ValueError: 'reps' cannot contain negative values.
b = np.tile(a, -1)
トラブルシューティング
reps
には常に正の整数または正の整数を含むタプルを指定してください。繰り返しの回数は0以上である必要があります。
不適切な入力型
numpy.tile()
の最初の引数 A
は配列ライク(array_like)なオブジェクトである必要があります。リストやタプルなども受け入れられますが、数値以外のオブジェクトを渡すとエラーになる場合があります。
エラーの例
import numpy as np
# TypeError: loop of ufunc does not support argument 0 of type NoneType which has no callable abs method
# これはNoneTypeをNumPyが数値として扱おうとして失敗している
# b = np.tile(None, 2)
# TypeError: only integer scalar arrays can be converted to a scalar index
# これはrepsに不適切な型を渡した場合
# b = np.tile([1,2], "abc")
トラブルシューティング
reps
には、単一の整数、または整数のタプルを指定してください。A
には、NumPy 配列に変換可能な数値のリスト、タプル、または既存の NumPy 配列を渡してください。
メモリ不足エラー (MemoryError)
numpy.tile()
は元の配列を繰り返して新しい配列を生成するため、非常に大きな繰り返し回数を指定したり、もともと大きな配列を繰り返したりすると、メモリを大量に消費し、MemoryError
が発生する可能性があります。
エラーの例
import numpy as np
# 非常に大きな配列を生成
large_array = np.zeros((1000, 1000))
# 非常に大きな回数繰り返す (PCのメモリによってはこれでもエラーになる)
# MemoryError: Unable to allocate ...
# tiled_large_array = np.tile(large_array, (1000, 1000))
トラブルシューティング
- チャンキング/バッチ処理
データを小さな塊(チャンク)に分割して処理し、メモリの使用量を抑える方法を検討してください。 - ジェネレータやイテレータを使用する
全てのデータを一度にメモリにロードするのではなく、必要に応じてデータを生成するアプローチを検討してください。 - よりメモリ効率の良いデータ型を使用する
必要であれば、np.float32
やnp.int8
のように、より小さなデータ型を使用することを検討してください。 - 繰り返しの回数を再検討する
本当にそれほど大きな配列が必要ですか?別のアルゴリズムや、必要な部分だけを計算するような方法がないか検討してください。
numpy.repeat() との混同
前述の通り、numpy.tile()
と numpy.repeat()
は挙動が異なります。意図せずにどちらか一方を使ってしまうと、期待とは異なる結果が得られます。
混乱の例
- 配列全体を繰り返してパターンを作りたいのに
repeat
を使ってしまう。 - 要素ごとに繰り返したいのに
tile
を使ってしまう。
import numpy as np
arr = np.array([1, 2])
# 要素ごとに繰り返したい場合 (正解は repeat)
# 期待: [1 1 1 2 2 2]
tile_result = np.tile(arr, 3)
print(f"tile_result (誤った使い方): {tile_result}") # [1 2 1 2 1 2]
repeat_result = np.repeat(arr, 3)
print(f"repeat_result (正しい使い方): {repeat_result}") # [1 1 1 2 2 2]
トラブルシューティング
- 両関数のドキュメントを再確認し、違いを理解しておくことが重要です。
- 目的を明確にする
- 配列全体をブロックとして繰り返し並べたい場合は
np.tile()
。 - 配列の各要素(またはスライス)を個別に繰り返したい場合は
np.repeat()
。
- 配列全体をブロックとして繰り返し並べたい場合は
numpy.tile()
は、既存の配列を繰り返し(タイル状に並べて)新しい配列を生成するのに非常に役立ちます。
1次元配列の繰り返し
最も基本的な使い方です。1次元配列を単に連結して繰り返します。
import numpy as np
# 例1: 1次元配列を3回繰り返す
print("--- 例1: 1次元配列を3回繰り返す ---")
arr_1d = np.array([1, 2, 3])
tiled_arr_1d = np.tile(arr_1d, 3)
print(f"元の配列: {arr_1d}")
print(f"繰り返した配列: {tiled_arr_1d}")
# 出力:
# 元の配列: [1 2 3]
# 繰り返した配列: [1 2 3 1 2 3 1 2 3]
# 例2: 1次元配列を2回繰り返す(単一の整数)
print("\n--- 例2: 1次元配列を2回繰り返す ---")
arr_single = np.array([10])
tiled_arr_single = np.tile(arr_single, 2)
print(f"元の配列: {arr_single}")
print(f"繰り返した配列: {tiled_arr_single}")
# 出力:
# 元の配列: [10]
# 繰り返した配列: [10 10]
2次元配列の繰り返し(スカラー reps)
reps
に単一の整数を指定すると、元の配列のすべての次元でその回数だけ繰り返されます。これにより、元の配列が「タイル」として縦横に並べられます。
import numpy as np
# 例3: 2次元配列を2回繰り返す
print("\n--- 例3: 2次元配列を2回繰り返す (スカラー reps) ---")
arr_2d = np.array([[1, 2],
[3, 4]])
tiled_arr_2d_scalar = np.tile(arr_2d, 2)
print(f"元の配列:\n{arr_2d}")
print(f"繰り返した配列:\n{tiled_arr_2d_scalar}")
# 出力:
# 元の配列:
# [[1 2]
# [3 4]]
# 繰り返した配列:
# [[1 2 1 2]
# [3 4 3 4]
# [1 2 1 2]
# [3 4 3 4]]
2次元配列の繰り返し(タプル reps)
reps
にタプルを指定すると、各次元に対して異なる繰り返し回数を指定できます。タプルの要素は、対応する次元(軸0, 軸1, ...)の繰り返し回数を示します。
import numpy as np
# 例4: 2次元配列を行方向に2回、列方向に3回繰り返す
print("\n--- 例4: 2次元配列を行方向に2回、列方向に3回繰り返す ---")
arr_2d_specific = np.array([[1, 0],
[0, 1]]) # 単位行列のような形
tiled_arr_2d_tuple = np.tile(arr_2d_specific, (2, 3)) # (行方向繰り返し, 列方向繰り返し)
print(f"元の配列:\n{arr_2d_specific}")
print(f"繰り返した配列:\n{tiled_arr_2d_tuple}")
# 出力:
# 元の配列:
# [[1 0]
# [0 1]]
# 繰り返した配列:
# [[1 0 1 0 1 0]
# [0 1 0 1 0 1]
# [1 0 1 0 1 0]
# [0 1 0 1 0 1]]
reps のタプルの長さが A.ndim より短い場合
この場合、reps
の要素が尽きるまで、元の配列の次元に繰り返しが適用されます。足りない次元は繰り返されません(1回繰り返されるのと同じ)。
import numpy as np
# 例5: 2次元配列 (2,2) に対して reps が1次元タプル (2,) の場合
print("\n--- 例5: reps の長さが A.ndim より短い場合 ---")
arr_2d_short_reps = np.array([[1, 2],
[3, 4]])
tiled_arr_2d_short_reps = np.tile(arr_2d_short_reps, (2,)) # 軸0を2回繰り返す
print(f"元の配列:\n{arr_2d_short_reps}")
print(f"繰り返した配列:\n{tiled_arr_2d_short_reps}")
# 出力:
# 元の配列:
# [[1 2]
# [3 4]]
# 繰り返した配列:
# [[1 2]
# [3 4]
# [1 2]
# [3 4]]
この場合、元の配列 A
に新しい次元が追加され、その新しい次元と既存の次元の両方で繰り返しが行われます。これは少し直感的ではないかもしれません。A
の形状の左側に 1
が追加されて、reps
の長さと一致するように拡張されます。
import numpy as np
# 例6: 1次元配列 (3,) に対して reps が2次元タプル (2,3) の場合
print("\n--- 例6: reps の長さが A.ndim より長い場合 ---")
arr_1d_long_reps = np.array([1, 2, 3]) # 形状 (3,)
# np.tile は、arr_1d_long_reps を (1, 3) とみなし、(2, 3) の reps を適用します。
tiled_arr_1d_long_reps = np.tile(arr_1d_long_reps, (2, 3))
print(f"元の配列: {arr_1d_long_reps} (形状: {arr_1d_long_reps.shape})")
print(f"繰り返した配列:\n{tiled_arr_1d_long_reps} (形状: {tiled_arr_1d_long_reps.shape})")
# 出力:
# 元の配列: [1 2 3] (形状: (3,))
# 繰り返した配列:
# [[1 2 3 1 2 3 1 2 3]
# [1 2 3 1 2 3 1 2 3]] (形状: (2, 9))
ブロードキャストの代替としての利用(より明示的なサイズ調整)
ブロードキャストはNumPyの強力な機能ですが、理解が難しい場合や、より明示的に配列のサイズを合わせたい場合に tile
が使われます。
import numpy as np
# 例7: ブロードキャストが難しい場合のサイズ合わせ
print("\n--- 例7: ブロードキャストの代替としてのサイズ合わせ ---")
vector_row = np.array([1, 2, 3]) # (3,)
matrix = np.array([[10, 20, 30],
[40, 50, 60]]) # (2, 3)
# vector_row を matrix の行数に合わせて繰り返す
# まず vector_row を (1, 3) とみなし、行方向に2回繰り返す
tiled_vector_row = np.tile(vector_row, (2, 1))
print(f"元のベクトル (1D): {vector_row}")
print(f"元の行列:\n{matrix}")
print(f"タイル化されたベクトル:\n{tiled_vector_row}")
# これで加算できる
result_addition = matrix + tiled_vector_row
print(f"加算結果:\n{result_addition}")
# 出力:
# 元のベクトル (1D): [1 2 3]
# 元の行列:
# [[10 20 30]
# [40 50 60]]
# タイル化されたベクトル:
# [[1 2 3]
# [1 2 3]]
# 加算結果:
# [[11 22 33]
# [41 52 63]]
この例では、vector_row
は (3,)
の形状ですが、matrix
は (2, 3)
です。ブロードキャストのルールでは直接加算可能ですが、tile
を使うことで vector_row
を明示的に (2, 3)
の形状に変換し、各行に同じ [1, 2, 3]
を持つ配列を作成しています。
numpy.tile()
の代替方法
numpy.repeat()
numpy.repeat()
は numpy.tile()
と混同されやすい関数ですが、その目的が異なります。tile
が「配列全体をブロックとして繰り返す」のに対し、repeat
は「配列の要素を繰り返す」ために使われます。しかし、特定のシナリオでは tile
と同じ結果を得るために repeat
を使うことができます。
主な違い
np.repeat(a, repeats, axis=None)
:a
の各要素(または指定された軸に沿ったスライス)をrepeats
回繰り返す。np.tile(a, reps)
:a
を構成する「タイル」を並べる。
tile の代替として repeat を使う例
1次元配列を繰り返す場合、repeat
を少し工夫して使うことができます。
import numpy as np
arr = np.array([1, 2, 3])
# tile の場合
tiled_arr = np.tile(arr, 2)
print(f"tile の結果: {tiled_arr}") # [1 2 3 1 2 3]
# repeat を使って tile と同じ結果を得る(少し複雑)
# まず配列全体を repeat し、その後 reshape
repeated_arr = np.repeat(arr, 2) # [1 1 2 2 3 3]
# これを並び替えるのは難しいので、この場合は tile が最適
# しかし、以下のケースではrepeatが代替になりうる
特定の軸に沿った繰り返しの代替
numpy.tile(A, (rows, 1))
のような行方向の繰り返しは、numpy.repeat
と axis
を使って実現できます。
import numpy as np
arr_2d = np.array([[1, 2],
[3, 4]])
# tile で行方向に2回繰り返す
tiled_by_row = np.tile(arr_2d, (2, 1))
print(f"tile (行方向2回):\n{tiled_by_row}")
# 出力:
# [[1 2]
# [3 4]
# [1 2]
# [3 4]]
# repeat で行方向に2回繰り返す (axis=0)
repeated_by_row = np.repeat(arr_2d, 2, axis=0)
print(f"repeat (行方向2回):\n{repeated_by_row}")
# 出力:
# [[1 2]
# [3 4]
# [1 2]
# [3 4]]
この例のように、特定の軸に沿って配列全体を繰り返したい場合は np.repeat
も有効な選択肢となります。しかし、列方向(axis=1
)の繰り返しは repeat
では実現できません(要素が繰り返されるため)。
ブロードキャスト (Broadcasting)
NumPyのブロードキャスト機能は、異なる形状の配列間で算術演算を行う際に、自動的に配列の形状を合わせる強力なメカニズムです。多くの場合、tile
で行っていた次元の拡張や繰り返しは、ブロードキャストでより簡潔に、かつ効率的に記述できます。
tile をブロードキャストで代替する例
ある行ベクトルを複数行にコピーして行列を作成するような場合。
import numpy as np
row_vector = np.array([10, 20, 30]) # 形状 (3,)
# tile を使う場合
tiled_matrix = np.tile(row_vector, (4, 1)) # (4行, 列は1回繰り返し)
print(f"tile で生成:\n{tiled_matrix}")
# 出力:
# [[10 20 30]
# [10 20 30]
# [10 20 30]
# [10 20 30]]
# ブロードキャストを意識して、新しい軸を追加する
# np.newaxis (または None) で次元を追加すると、自動的にブロードキャストされる
broadcasted_matrix = row_vector[np.newaxis, :] # 形状 (1, 3)
broadcasted_matrix = np.tile(broadcasted_matrix, (4, 1)) # これでもOK
# あるいは、より直接的な方法で目的の行列を作る
# np.ones は指定された形状の配列を作成し、それに row_vector を掛ける
broadcasted_result = np.ones((4, 1)) * row_vector
print(f"\nブロードキャストで生成:\n{broadcasted_result}")
# 出力:
# [[10. 20. 30.]
# [10. 20. 30.]
# [10. 20. 30.]
# [10. 20. 30.]]
この例では、row_vector
が (3,)
であり、np.ones((4, 1))
が (4, 1)
です。これらを乗算すると、NumPyのブロードキャストルールにより、row_vector
は (1, 3)
に拡張され、np.ones((4, 1))
と互換性のある (4, 3)
の行列に自動的に拡張され、乗算が行われます。これは tile
よりも簡潔で、多くの場合効率的です。
配列のスライシングと結合 (np.concatenate, np.vstack, np.hstack)
特定のパターンで配列を結合したい場合、スライシングと結合関数を組み合わせることで tile
と同じ結果を得ることができます。これは、より複雑なパターンや、特定の配列のセグメントを繰り返す場合に有用です。
import numpy as np
arr = np.array([[1, 2],
[3, 4]])
# tile で行方向に2回繰り返す
tiled_result = np.tile(arr, (2, 1))
print(f"tile の結果:\n{tiled_result}")
# 出力:
# [[1 2]
# [3 4]
# [1 2]
# [3 4]]
# concatenate を使う場合
concatenated_result = np.vstack((arr, arr))
print(f"\nconcatenate (vstack) の結果:\n{concatenated_result}")
# 出力:
# [[1 2]
# [3 4]
# [1 2]
# [3 4]]
# 列方向に繰り返したい場合
tiled_cols = np.tile(arr, (1, 2))
print(f"\ntile (列方向2回):\n{tiled_cols}")
# 出力:
# [[1 2 1 2]
# [3 4 3 4]]
concatenated_cols = np.hstack((arr, arr))
print(f"\nconcatenate (hstack) の結果:\n{concatenated_cols}")
# 出力:
# [[1 2 1 2]
# [3 4 3 4]]
np.vstack()
は複数の配列を垂直(行方向)にスタックし、np.hstack()
は水平(列方向)にスタックします。これらはシンプルな繰り返しパターンにおいて tile
の代替となり得ます。
リスト内包表記と np.array()
Pythonのリスト内包表記と np.array()
を組み合わせて、より柔軟な繰り返しのロジックを実装することも可能です。特に、各繰り返しで少しずつ異なる処理を行いたい場合などに有効です。
import numpy as np
arr = np.array([1, 2, 3])
# tile の場合
tiled_arr = np.tile(arr, 3)
print(f"tile の結果: {tiled_arr}") # [1 2 3 1 2 3 1 2 3]
# リスト内包表記で代替
list_of_arrays = [arr for _ in range(3)] # [array([1, 2, 3]), array([1, 2, 3]), array([1, 2, 3])]
concatenated_from_list = np.concatenate(list_of_arrays)
print(f"リスト内包表記 + concatenate の結果: {concatenated_from_list}")
# 出力:
# リスト内包表記 + concatenate の結果: [1 2 3 1 2 3 1 2 3]
この方法は、より複雑なタイリングパターンを生成する際に、NumPyの低レベルな操作だけでは難しい場合に役立ちます。ただし、パフォーマンスは tile
やブロードキャストの方が一般的に優れています。
- 複雑なカスタムパターン
標準のNumPy関数では表現が難しい複雑な繰り返しパターンや、ループ内で特定の処理が必要な場合は、Pythonのリスト内包表記や通常のループとNumPyの結合関数を組み合わせることを検討してください。ただし、大規模なデータではパフォーマンスに注意が必要です。 - 単純な結合
複数の配列を縦または横に結合するだけでよい場合は、np.vstack()
やnp.hstack()
が簡潔です。 - 要素ごとの繰り返し
配列の各要素を繰り返したい場合は、迷わずnumpy.repeat()
を使用してください。 - パフォーマンスと簡潔性
可能な限りブロードキャストの使用を検討してください。NumPyのブロードキャストは非常に最適化されており、多くの場合tile
よりも高速でコードが簡潔になります。 - 最もシンプルで直感的
numpy.tile()
は、配列を単純にタイル状に並べたい場合に最も直接的な方法です。