numpy
では、結果の配列の次元は実行時に異なります。多くの場合、1次元配列と1列の2次元配列の間で混乱が生じます。ある場合には、列を反復処理できますが、別の場合にはできません。
その問題をエレガントにどのように解決しますか?次元をチェックするif
ステートメントでコードを散らかすことを避けるために、この関数を使用します。
def reshape_to_vect(ar):
if len(ar.shape) == 1:
return ar.reshape(ar.shape[0],1)
return ar
ただし、これは上品でコストがかかります。より良い解決策はありますか?
最も簡単な方法:
ar.reshape(-1, 1)
あなたができる-
ar.reshape(ar.shape[0],-1)
reshape
への2番目の入力:-1
は、2番目の軸の要素数を処理します。したがって、2D
入力の場合、変更はありません。 1D
入力の場合、2D
が要素の合計数であるため、すべての要素が最初の軸に「プッシュ」されるar.shape[0]
配列を作成します。
サンプルの実行
1Dケース:
In [87]: ar
Out[87]: array([ 0.80203158, 0.25762844, 0.67039516, 0.31021513, 0.80701097])
In [88]: ar.reshape(ar.shape[0],-1)
Out[88]:
array([[ 0.80203158],
[ 0.25762844],
[ 0.67039516],
[ 0.31021513],
[ 0.80701097]])
2Dケース:
In [82]: ar
Out[82]:
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523],
[ 0.39728524, 0.03952238, 0.04153052, 0.82009233],
[ 0.38748174, 0.51377738, 0.40365096, 0.74823535]])
In [83]: ar.reshape(ar.shape[0],-1)
Out[83]:
array([[ 0.37684126, 0.16973899, 0.82157815, 0.38958523],
[ 0.39728524, 0.03952238, 0.04153052, 0.82009233],
[ 0.38748174, 0.51377738, 0.40365096, 0.74823535]])
Divakarによる回答のバリエーションはx = np.reshape(x, (len(x),-1))
です。これは、入力が1dまたは2dリストの場合も処理します。
そもそも形状を変更する必要を回避するために、リストで行/列をスライスする場合、または「実行中の」スライスで、1行/列の2D配列を取得します
import numpy as np
x = np.array(np.random.normal(size=(4,4)))
print x, '\n'
Result:
[[ 0.01360395 1.12130368 0.95429414 0.56827029]
[-0.66592215 1.04852182 0.20588886 0.37623406]
[ 0.9440652 0.69157556 0.8252977 -0.53993904]
[ 0.6437994 0.32704783 0.52523173 0.8320762 ]]
y = x[:,[0]]
print y, 'col vector \n'
Result:
[[ 0.01360395]
[-0.66592215]
[ 0.9440652 ]
[ 0.6437994 ]] col vector
y = x[[0],:]
print y, 'row vector \n'
Result:
[[ 0.01360395 1.12130368 0.95429414 0.56827029]] row vector
# Slice with "running" index on a column
y = x[:,0:1]
print y, '\n'
Result:
[[ 0.01360395]
[-0.66592215]
[ 0.9440652 ]
[ 0.6437994 ]]
代わりに、行/列の選択に単一の数値を使用すると、1D配列が発生します。これが問題の根本原因です。
y = x[:,0]
print y, '\n'
Result:
[ 0.01360395 -0.66592215 0.9440652 0.6437994 ]
あなたの例は不可解であるため、dtype
について尋ねました。
3つの要素(1d)と3つのフィールドを持つ構造化配列を作成できます。
_In [1]: A = np.ones((3,), dtype='i,i,i')
In [2]: A
Out[2]:
array([(1, 1, 1), (1, 1, 1), (1, 1, 1)],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
_
名前で1つのフィールドにアクセスできます(括弧を追加しても変更はありません)
_In [3]: A['f0'].shape
Out[3]: (3,)
_
しかし、2つのフィールドにアクセスすると、まだ1D配列が得られます
_In [4]: A[['f0','f1']].shape
Out[4]: (3,)
In [5]: A[['f0','f1']]
Out[5]:
array([(1, 1), (1, 1), (1, 1)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
_
実際に値を見ると、これらの余分な括弧は重要です
_In [22]: A['f0']
Out[22]: array([1, 1, 1], dtype=int32)
In [23]: A[['f0']]
Out[23]:
array([(1,), (1,), (1,)],
dtype=[('f0', '<i4')])
_
配列が単純な2D配列の場合、まだ形状がわかりません
_In [24]: A=np.ones((3,3),int)
In [25]: A[0].shape
Out[25]: (3,)
In [26]: A[[0]].shape
Out[26]: (1, 3)
In [27]: A[[0,1]].shape
Out[27]: (2, 3)
_
しかし、配列が2dであることを確認するという質問については、インデックスが1dまたは2を返すかどうかに関係なく、あなたの関数は基本的に大丈夫です
_def reshape_to_vect(ar):
if len(ar.shape) == 1:
return ar.reshape(ar.shape[0],1)
return ar
_
len(ar.shape)
の代わりに_ar.ndim
_をテストできます。しかし、いずれにせよ、コストはかかりません-つまり、実行時間は最小限です-大きな配列操作はありません。 reshape
はデータをコピーしません(ストライドが奇妙でない限り)ので、共有データポインターで新しい配列オブジェクトを作成するだけのコストです。
_np.atleast_2d
_;のコードを見てください。 0dと1dをテストします。 1dの場合、_result = ary[newaxis,:]
_を返します。余分な軸が最初に追加され、軸を追加するためのより自然なnumpy
位置が追加されます。最後に追加します。
ar.reshape(ar.shape[0],-1)
は、if
テストをバイパスする賢い方法です。小規模なタイミングテストではより高速になりますが、関数呼び出し層の影響であるマイクロ秒について説明しています。
_np.column_stack
_は、必要に応じて列配列を作成する別の関数です。それは使用しています:
_ if arr.ndim < 2:
arr = array(arr, copy=False, subok=True, ndmin=2).T
_
y = np.array(12)
y = y.reshape(-1,1)
print(y.shape)
O/P:- (1, 1)