2016-04-10 5 views
1

質問:パッドは、0年代二つ

どのように迅速冒頭に大きな配列(〜600個の000エントリ)に0を追加するには、配列の長さを持って次の2の威力。 (2^n)np.concatinate()のほかにもっと速い解決策がありますか?

  • の配列の長さが2のべき乗に等しくなるまでnp.concatenate(0、ARR)関数を使用して:私はすでに試みたもの

    。私が働いているコードは、非常に長い時間がかかります。

ここでパッド左機能です:

def PadLeft(arr): 
    nextPower = NextPowerOfTwo(len(arr)) 
    deficit = int(math.pow(2, nextPower) - len(arr)) 
    #for x in range(1, int(deficit)): 
    for x in range(0, deficit):  
     arr = np.concatenate(([0], arr)) 
    return arr 

は、ここでは、2つの関数の次の力です:

def NextPowerOfTwo(number): 
    # Returns next power of two following 'number' 
    return math.ceil(math.log(number,2)) 

私の実装:

arr = np.ones(()) 
a = PadLeft(arr) 

ありがとうございました!

+0

出力配列をゼロで初期化し、値を設定しますか? – Divakar

+0

私が扱っている配列はさまざまな長さで入ってきますので、私はそれを投稿したいと思います! – jackskis

+1

私は次のような意味を持っていました: 'out = np.zeros(deficit + len(arr)、dtype = arr.dtype); out [deficit:] = arr'を実行して、 'PadLeft(arr)' IIUCからの出力をシミュレートします。 – Divakar

答えて

4

forループ内の古い配列を1つの要素で拡張するのではなく、ゼロセット全体を一度に追加してみませんか?

arr = np.concatenate((np.zeros(deficit, dtype=arr.dtype), arr)) 

forループは使用しないでください。そこでは、必要なサイズの配列を一度作成し、必要に応じてそれを埋め込むよりもはるかに効率が悪い、繰り返しごとに新しい配列を作成するので、コードはゆっくり実行されます。これはいくつかの方法で行うことができます。これはちょうど1つで、あなた自身の解決策に近いものです。 np.zerosがデフォルトでnp.float DTYPE である配列を返しますので、

dtype=arr.dtypeが追加された理由は、あります。 arrのデータ型が(キャスティングの意味で) "less"の場合、結果は "より広い"データ型にキャストされます。浮動小数点型は自動的に発生するため、普通はそうではありません。 この有効な点はDivakarによって以下のコメントで作成されました。

+0

データ型を入力配列として保持するには、 '、dtype = arr.dtype'と' np.zeros'を多分使用しますか?これを初期化ベースのものと比較してタイミングをとっており、このように速くても高速であるように思えます。 – Divakar

+0

私は実際にあなたの初期設定の提案と似ていると思っていました(答えにしてください、それは*良い*回答なので、アップボトムしたいです)。実行する必要があります。 'dis'はおそらくそれを閉鎖しますが、ここにはpython-shellはありません。 –

+0

追加されました。しかし、np.zeros(deficit)はデフォルトでfloat配列になり、連結後でもfloatになるので、 'arr'がint配列の場合にdtypeをポストに追加できるかどうかはわかります。 – Divakar

5

正確にはnumpy.padがあります。

1Dアレイについて:

arr = np.pad(arr, (deficit,0), mode='constant') 

(left, right)パディングとして読み出します。

2D arrrayについて:

arr = np.pad(arr, ((0,0), (deficit,0)), mode='constant') 

第2のパラメータは、((top, bottom), (left, right))として読み出します。左に不足している配列をパディングします。完全にnumpyのを利用して

3

は、ここでは、初期化とアプローチだ -

def NextPowerOfTwo(number): 
    # Returns next power of two following 'number' 
    return np.ceil(np.log2(number)) 

def PadLeft_with_initialization(arr): 
    nextPower = NextPowerOfTwo(len(arr)) 
    deficit = int(np.power(2, nextPower) - len(arr)) 
    out = np.zeros(deficit+len(arr),dtype=arr.dtype) 
    out[deficit:] = arr 
    return out 

ランタイムテスト

レッツ・時間、この記事で提案された解決策とnp.concatenateベース1はOliver W.'s solutionに記載されている:

def PadLeft_with_concatente(arr): # Oliver W.'s solution 
    nextPower = NextPowerOfTwo(len(arr)) 
    deficit = int(np.power(2, nextPower) - len(arr)) 
    return np.concatenate((np.zeros(deficit,dtype=arr.dtype), arr)) 

タイミング -

In [226]: arr = np.random.randint(0,9,(600000)) 

In [227]: %timeit PadLeft_with_concatente(arr) 
100 loops, best of 3: 5.21 ms per loop 

In [228]: %timeit PadLeft_with_initialization(arr) 
100 loops, best of 3: 6.75 ms per loop 

クリーナーで速くなっているので、私はOliver W.'s solution with np.concatenateが行く方法だと思います。