Numpy ndarrayを「拡張」する良い方法はありますか?次のようなndarrayがあるとします。
[[1 2]
[3 4]]
そして、ゼロを埋めることで各行にさらに要素が含まれるようにします。
[[1 2 0 0 0]
[3 4 0 0 0]]
強引な方法がいくつかあるに違いないことを知っています(ゼロで大きな配列を作成し、古い小さな配列から要素をコピーするなど)。 numpy.reshape
しかし動作しませんでした:
import numpy as np
a = np.array([[1, 2], [3, 4]])
np.reshape(a, (2, 5))
Numpyからの不満:ValueError: total size of new array must be unchanged
インデックストリックがありますr_
およびc_
。
>>> import numpy as np
>>> a = np.array([[1, 2], [3, 4]])
>>> z = np.zeros((2, 3), dtype=a.dtype)
>>> np.c_[a, z]
array([[1, 2, 0, 0, 0],
[3, 4, 0, 0, 0]])
これがパフォーマンスが重要なコードである場合、同等のnp.concatenate
インデックスのトリックではなく。
>>> np.concatenate((a,z), axis=1)
array([[1, 2, 0, 0, 0],
[3, 4, 0, 0, 0]])
もあります np.resize
およびnp.ndarray.resize
、ただし、いくつかの制限があります(numpyがメモリにデータをレイアウトする方法のため)ので、それらのdocstringを読んでください。単純に連結する方が良いでしょう。
ところで、私がこれを行う必要があるとき、私は通常あなたが既に述べた基本的な方法でそれを行います(ゼロの配列を作成し、その中に小さな配列を割り当てます)、私はそれで何の問題も見ません!
次のように、numpy.pad
を使用できます。
>>> import numpy as np
>>> a=[[1,2],[3,4]]
>>> np.pad(a, ((0,0),(0,3)), mode='constant', constant_values=0)
array([[1, 2, 0, 0, 0],
[3, 4, 0, 0, 0]])
ここでnp.pad
は、「配列a
を取得し、その上に0行、その下に0行、その左に0列、その右に3列を追加します。これらの列を埋めますconstant_values
"で指定されたconstant
。
NumPy配列はnot拡張可能であるため、NumPy配列を拡張する「良い」方法はありません。配列が定義されると、メモリ内で占有するスペース(要素の数と各要素のサイズの組み合わせ)は固定され、変更できません。できることは、新しい配列を作成し、その要素の一部を元の配列の要素で置き換えることだけです。
多くの機能が便利に利用できます( np.concatenate
関数とそのnp.*stack
ショートカット、 np.column_stack
、インデックスルーチン np.r_
およびnp.c_
...)、しかしそれだけがあります:便利な機能。それらのいくつかは、Cレベルで最適化されています(np.concatenate
と他の人、私は思う)、そうでない人もいます。
大きな配列を「手で」(おそらくゼロで埋める)作成し、最初の配列で自分で埋めるという最初の提案には何もありません。より複雑なソリューションよりも読みやすいかもしれません。
np.column_stack
またはappend
を使用する必要があります
import numpy as np
p = np.array([ [1,2] , [3,4] ])
p = np.column_stack( [ p , [ 0 , 0 ],[0,0] ] )
p
Out[277]:
array([[1, 2, 0, 0],
[3, 4, 0, 0]])
ただし、追加の方が速いようです:
timeit np.column_stack( [ p , [ 0 , 0 ],[0,0] ] )
10000 loops, best of 3: 61.8 us per loop
timeit np.append(p, [[0,0],[0,0]],1)
10000 loops, best of 3: 48 us per loop
そして、np.c_
とnp.hstack
[まだ追加するのが最速のようです]との比較:
In [295]: z=np.zeros((2, 2), dtype=a.dtype)
In [296]: timeit np.c_[a, z]
10000 loops, best of 3: 47.2 us per loop
In [297]: timeit np.append(p, z,1)
100000 loops, best of 3: 13.1 us per loop
In [305]: timeit np.hstack((p,z))
10000 loops, best of 3: 20.8 us per loop
およびnp.concatenate
[append
]よりも少し高速です:
In [307]: timeit np.concatenate((p, z), axis=1)
100000 loops, best of 3: 11.6 us per loop
# what you want to expand
x = np.ones((3, 3))
# expand to what shape
target = np.zeros((6, 6))
# do expand
target[:x.shape[0], :x.shape[1]] = x
# print target
array([[ 1., 1., 1., 0., 0., 0.],
[ 1., 1., 1., 0., 0., 0.],
[ 1., 1., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.]])
https://stackoverflow.com/a/35751427/163767 から借用します。少し変更します。
def pad(array, reference_shape, offsets=None):
"""
array: Array to be padded
reference_shape: Tuple of size of narray to create
offsets: list of offsets (number of elements must be equal to the dimension of the array)
will throw a ValueError if offsets is too big and the reference_shape cannot handle the offsets
"""
if not offsets:
offsets = np.zeros(array.ndim, dtype=np.int32)
# Create an array of zeros with the reference shape
result = np.zeros(reference_shape, dtype=np.float32)
# Create a list of slices from offset to offset + shape in each dimension
insertHere = [slice(offsets[dim], offsets[dim] + array.shape[dim]) for dim in range(array.ndim)]
# Insert the array in the result at the specified offsets
result[insertHere] = array
return result
np.vstack、np.hstack、np.dstackなどの同様のメソッドもあります。 np.concatenteよりもこれらが好きです。どのディメンションが「拡張」されているかが明確になるからです。
temp = np.array([[1, 2], [3, 4]])
np.hstack((temp, np.zeros((2,3))))
numpyの最初の軸が垂直であり、vstackが最初の軸を拡張し、2番目の軸が水平であるためhstackであるため、覚えやすいです。